]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'iio-for-3.15c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 6 Mar 2014 19:33:04 +0000 (11:33 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 6 Mar 2014 19:33:04 +0000 (11:33 -0800)
Jonathan writes:

Third IIO new drivers and cleanups series for 3.15.

New driver
* Xilinx XADC driver -  This has been ready for a while but was awaiting
  a device tree ack (or as it turns out 3+ weeks).

Cleanup
* Drop some unreachable code from mag3110 highlighted by smatch.

Fix
* vf610 - introduced this cycle - put a possible negative error code
  into an unsigned long. Another smatch find - this one promoted by
  guilt that Dan was busy fixing all our messups.

820 files changed:
Documentation/ABI/testing/sysfs-tty
Documentation/PCI/MSI-HOWTO.txt
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
Documentation/devicetree/bindings/net/sti-dwmac.txt [new file with mode: 0644]
Documentation/networking/3c505.txt [deleted file]
MAINTAINERS
Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/imx51-babbage.dts
arch/arm/boot/dts/imx53-m53evk.dts
arch/arm/boot/dts/imx53-mba53.dts
arch/arm/boot/dts/imx53-qsb.dts
arch/arm/boot/dts/imx6dl-hummingboard.dts
arch/arm/boot/dts/imx6dl.dtsi
arch/arm/boot/dts/imx6q-sabresd.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/omap3-gta04.dts
arch/arm/boot/dts/omap3-n9.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950.dts
arch/arm/boot/dts/omap3-overo-storm-tobi.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-overo-tobi-common.dtsi [moved from arch/arm/boot/dts/omap3-tobi.dts with 94% similarity]
arch/arm/boot/dts/omap3-overo-tobi.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-overo.dtsi
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/testcases/tests.dtsi [deleted file]
arch/arm/boot/dts/versatile-pb.dts
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/spinlock.h
arch/arm/kernel/setup.c
arch/arm/kvm/arm.c
arch/arm/kvm/interrupts.S
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/common.h
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/io.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/tegra.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm64/include/asm/percpu.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/stacktrace.c
arch/arm64/kvm/hyp.S
arch/avr32/Makefile
arch/avr32/boards/mimc200/fram.c
arch/avr32/include/asm/Kbuild
arch/avr32/include/asm/io.h
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/barrier.h [deleted file]
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/powerpc/include/asm/compat.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/include/asm/vdso.h
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/ftrace.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/vdso32/vdso32_wrapper.S
arch/powerpc/kernel/vdso64/vdso64_wrapper.S
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/subpage-prot.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/pci.c
arch/s390/kernel/compat_wrapper.S
arch/s390/pci/pci_dma.c
arch/sparc/Kconfig
arch/sparc/mm/srmmu.c
arch/x86/boot/compressed/aslr.c
arch/x86/include/asm/tsc.h
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/tsc.c
arch/x86/kernel/tsc_msr.c
arch/x86/kvm/mmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/xtensa/Kconfig
arch/xtensa/boot/dts/xtfpga.dtsi
arch/xtensa/include/asm/io.h
arch/xtensa/include/asm/traps.h
arch/xtensa/include/asm/vectors.h
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/time.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/mm/init.c
arch/xtensa/mm/mmu.c
arch/xtensa/platforms/xtfpga/setup.c
arch/xtensa/variants/fsf/include/variant/tie.h
drivers/acpi/ac.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/button.c
drivers/acpi/dock.c
drivers/acpi/fan.c
drivers/acpi/pci_irq.c
drivers/acpi/processor_throttling.c
drivers/acpi/sbs.c
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/libata-pmp.c
drivers/ata/pata_imx.c
drivers/ata/sata_mv.c
drivers/ata/sata_sil.c
drivers/base/dma-buf.c
drivers/base/firmware_class.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/powernow-k8.c
drivers/dma/imx-sdma.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v3.c
drivers/dma/ste_dma40.c
drivers/edac/i7300_edac.c
drivers/edac/i7core_edac.c
drivers/extcon/extcon-arizona.c
drivers/fmc/fmc-write-eeprom.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/engine/device/nv40.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_vga.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r600_audio.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_semaphore.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/ttm/ttm_agp_backend.c
drivers/gpu/drm/vmwgfx/svga3d_reg.h
drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
drivers/gpu/drm/vmwgfx/svga_reg.h
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
drivers/gpu/host1x/job.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-sensor-hub.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/max1668.c
drivers/iio/gyro/Kconfig
drivers/iio/gyro/st_gyro.h
drivers/iio/gyro/st_gyro_core.c
drivers/iio/gyro/st_gyro_i2c.c
drivers/iio/gyro/st_gyro_spi.c
drivers/iio/light/cm32181.c
drivers/iio/light/cm36651.c
drivers/input/misc/arizona-haptics.c
drivers/iommu/arm-smmu.c
drivers/iommu/omap-iommu-debug.c
drivers/irqchip/irq-metag-ext.c
drivers/irqchip/irq-metag.c
drivers/irqchip/irq-orion.c
drivers/md/dm-cache-target.c
drivers/md/dm-io.c
drivers/md/dm-mpath.c
drivers/md/dm-raid1.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/persistent-data/dm-space-map-metadata.h
drivers/mfd/da9055-i2c.c
drivers/mfd/max14577.c
drivers/mfd/max8997.c
drivers/mfd/max8998.c
drivers/mfd/sec-core.c
drivers/mfd/tps65217.c
drivers/mfd/wm8994-core.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/echo/Kconfig [moved from drivers/staging/echo/Kconfig with 100% similarity]
drivers/misc/echo/Makefile [moved from drivers/staging/echo/Makefile with 100% similarity]
drivers/misc/echo/echo.c [moved from drivers/staging/echo/echo.c with 100% similarity]
drivers/misc/echo/echo.h [moved from drivers/staging/echo/echo.h with 100% similarity]
drivers/misc/echo/fir.h [moved from drivers/staging/echo/fir.h with 100% similarity]
drivers/misc/echo/oslec.h [moved from drivers/staging/echo/oslec.h with 100% similarity]
drivers/misc/mei/client.c
drivers/mmc/card/queue.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/omap2.c
drivers/mtd/ubi/fastmap.c
drivers/net/Kconfig
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_3ad.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/can/usb/kvaser_usb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/Kconfig
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/ethernet/stmicro/stmmac/Makefile
drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c [new file with mode: 0644]
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/irda/irtty-sir.c
drivers/net/macvlan.c
drivers/net/phy/dp83640.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/gl620a.c
drivers/net/usb/mcs7830.c
drivers/net/usb/net1080.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/rndis_host.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/sr9800.c
drivers/net/usb/usbnet.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/hostap/hostap_proc.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/of/base.c
drivers/of/of_mdio.c
drivers/of/selftest.c
drivers/of/testcase-data/testcases.dtsi [new file with mode: 0644]
drivers/of/testcase-data/tests-interrupts.dtsi [moved from arch/arm/boot/dts/testcases/tests-interrupts.dtsi with 100% similarity]
drivers/of/testcase-data/tests-match.dtsi [new file with mode: 0644]
drivers/of/testcase-data/tests-phandle.dtsi [moved from arch/arm/boot/dts/testcases/tests-phandle.dtsi with 100% similarity]
drivers/pci/host/pci-mvebu.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/phy/phy-exynos-dp-video.c
drivers/phy/phy-exynos-mipi-video.c
drivers/phy/phy-mvebu-sata.c
drivers/phy/phy-omap-usb2.c
drivers/phy/phy-twl4030-usb.c
drivers/pwm/pwm-lp3943.c
drivers/regulator/core.c
drivers/regulator/da9063-regulator.c
drivers/regulator/max14577.c
drivers/regulator/s5m8767.c
drivers/s390/cio/chsc.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/sbus/char/jsflash.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/scsi/scsi_lib.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/Kconfig
drivers/staging/android/binder.c
drivers/staging/android/binder.h
drivers/staging/android/binder_trace.h
drivers/staging/android/lowmemorykiller.c
drivers/staging/android/uapi/binder.h
drivers/staging/bcm/Bcmnet.c
drivers/staging/bcm/InterfaceInit.c
drivers/staging/bcm/Qos.c
drivers/staging/ced1401/usb1401.c
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/comedidev.h
drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
drivers/staging/comedi/drivers/ke_counter.c
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/cxt1e1/comet_tables.c
drivers/staging/cxt1e1/functions.c
drivers/staging/cxt1e1/hwprobe.c
drivers/staging/cxt1e1/linux.c
drivers/staging/dgap/Makefile
drivers/staging/dgap/dgap.c [new file with mode: 0644]
drivers/staging/dgap/dgap.h [new file with mode: 0644]
drivers/staging/dgap/dgap_conf.h [deleted file]
drivers/staging/dgap/dgap_downld.h [deleted file]
drivers/staging/dgap/dgap_driver.c [deleted file]
drivers/staging/dgap/dgap_driver.h [deleted file]
drivers/staging/dgap/dgap_fep5.c [deleted file]
drivers/staging/dgap/dgap_fep5.h [deleted file]
drivers/staging/dgap/dgap_kcompat.h [deleted file]
drivers/staging/dgap/dgap_parse.c [deleted file]
drivers/staging/dgap/dgap_parse.h [deleted file]
drivers/staging/dgap/dgap_pci.h [deleted file]
drivers/staging/dgap/dgap_sysfs.c [deleted file]
drivers/staging/dgap/dgap_sysfs.h [deleted file]
drivers/staging/dgap/dgap_trace.c [deleted file]
drivers/staging/dgap/dgap_trace.h [deleted file]
drivers/staging/dgap/dgap_tty.c [deleted file]
drivers/staging/dgap/dgap_tty.h [deleted file]
drivers/staging/dgap/dgap_types.h [deleted file]
drivers/staging/dgap/digi.h [deleted file]
drivers/staging/dgap/downld.c [deleted file]
drivers/staging/echo/TODO [deleted file]
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/imx-drm/Kconfig
drivers/staging/imx-drm/Makefile
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-drm.h
drivers/staging/imx-drm/imx-fb.c [deleted file]
drivers/staging/imx-drm/imx-fbdev.c [deleted file]
drivers/staging/imx-drm/imx-hdmi.c
drivers/staging/imx-drm/imx-ldb.c
drivers/staging/imx-drm/imx-tve.c
drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
drivers/staging/imx-drm/ipu-v3/ipu-dc.c
drivers/staging/imx-drm/ipu-v3/ipu-di.c
drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/imx-drm/ipuv3-plane.c
drivers/staging/imx-drm/parallel-display.c
drivers/staging/line6/driver.c
drivers/staging/line6/driver.h
drivers/staging/line6/usbdefs.h
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
drivers/staging/lustre/lustre/include/cl_object.h
drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
drivers/staging/lustre/lustre/include/lustre_export.h
drivers/staging/lustre/lustre/include/lustre_import.h
drivers/staging/lustre/lustre/include/lustre_net.h
drivers/staging/lustre/lustre/include/obd.h
drivers/staging/lustre/lustre/include/obd_class.h
drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
drivers/staging/lustre/lustre/libcfs/workitem.c
drivers/staging/lustre/lustre/llite/dcache.c
drivers/staging/lustre/lustre/llite/dir.c
drivers/staging/lustre/lustre/llite/file.c
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/lmv/lmv_intent.c
drivers/staging/lustre/lustre/lmv/lmv_obd.c
drivers/staging/lustre/lustre/lov/lov_io.c
drivers/staging/lustre/lustre/mdc/mdc_internal.h
drivers/staging/lustre/lustre/mdc/mdc_locks.c
drivers/staging/lustre/lustre/mdc/mdc_reint.c
drivers/staging/lustre/lustre/mdc/mdc_request.c
drivers/staging/lustre/lustre/obdclass/genops.c
drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
drivers/staging/lustre/lustre/osc/osc_cache.c
drivers/staging/lustre/lustre/osc/osc_io.c
drivers/staging/lustre/lustre/osc/osc_quota.c
drivers/staging/lustre/lustre/ptlrpc/client.c
drivers/staging/lustre/lustre/ptlrpc/import.c
drivers/staging/lustre/lustre/ptlrpc/niobuf.c
drivers/staging/lustre/lustre/ptlrpc/recover.c
drivers/staging/netlogic/xlr_net.c
drivers/staging/octeon/ethernet-defines.h
drivers/staging/octeon/ethernet-mem.c
drivers/staging/octeon/ethernet-rgmii.c
drivers/staging/octeon/ethernet-tx.c
drivers/staging/octeon/ethernet.c
drivers/staging/ozwpan/ozpd.c
drivers/staging/ozwpan/ozpd.h
drivers/staging/ozwpan/ozproto.c
drivers/staging/ozwpan/ozproto.h
drivers/staging/panel/panel.c
drivers/staging/rtl8187se/Module.symvers [new file with mode: 0644]
drivers/staging/rtl8187se/ieee80211/ieee80211.h
drivers/staging/rtl8187se/r8180.h
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8187se/r8180_wx.c
drivers/staging/rtl8187se/r8185b_init.c
drivers/staging/rtl8188eu/core/rtw_ap.c
drivers/staging/rtl8188eu/core/rtw_br_ext.c
drivers/staging/rtl8188eu/core/rtw_debug.c
drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
drivers/staging/rtl8188eu/core/rtw_mp.c
drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
drivers/staging/rtl8188eu/core/rtw_recv.c
drivers/staging/rtl8188eu/core/rtw_wlan_util.c
drivers/staging/rtl8188eu/core/rtw_xmit.c
drivers/staging/rtl8188eu/os_dep/os_intfs.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
drivers/staging/rtl8821ae/base.c
drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
drivers/staging/rtl8821ae/core.c
drivers/staging/rtl8821ae/core.h
drivers/staging/rtl8821ae/debug.c
drivers/staging/rtl8821ae/debug.h
drivers/staging/rtl8821ae/efuse.c
drivers/staging/rtl8821ae/pci.c
drivers/staging/rtl8821ae/pci.h
drivers/staging/rtl8821ae/ps.c
drivers/staging/rtl8821ae/regd.c
drivers/staging/rtl8821ae/rtl8821ae/dm.c
drivers/staging/rtl8821ae/rtl8821ae/fw.c
drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
drivers/staging/rtl8821ae/rtl8821ae/hw.c
drivers/staging/rtl8821ae/rtl8821ae/phy.c
drivers/staging/rtl8821ae/rtl8821ae/phy.h
drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
drivers/staging/rtl8821ae/rtl8821ae/reg.h
drivers/staging/rtl8821ae/rtl8821ae/sw.c
drivers/staging/rtl8821ae/rtl8821ae/trx.c
drivers/staging/rtl8821ae/wifi.h
drivers/staging/rts5208/ms.c
drivers/staging/sb105x/Kconfig [deleted file]
drivers/staging/sb105x/Makefile [deleted file]
drivers/staging/sb105x/sb_mp_register.h [deleted file]
drivers/staging/sb105x/sb_pci_mp.c [deleted file]
drivers/staging/sb105x/sb_pci_mp.h [deleted file]
drivers/staging/sb105x/sb_ser_core.h [deleted file]
drivers/staging/sep/sep_crypto.c
drivers/staging/sep/sep_main.c
drivers/staging/slicoss/slic.h
drivers/staging/slicoss/slicoss.c
drivers/staging/sm7xxfb/Kconfig [deleted file]
drivers/staging/sm7xxfb/Makefile [deleted file]
drivers/staging/sm7xxfb/TODO [deleted file]
drivers/staging/sm7xxfb/sm7xx.h [deleted file]
drivers/staging/sm7xxfb/sm7xxfb.c [deleted file]
drivers/staging/tidspbridge/core/io_sm.c
drivers/staging/tidspbridge/core/tiomap3430_pwr.c
drivers/staging/tidspbridge/dynload/tramp.c
drivers/staging/tidspbridge/rmgr/dbdcd.c
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/tidspbridge/rmgr/nldr.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/staging/unisys/Documentation/overview.txt [new file with mode: 0644]
drivers/staging/unisys/Documentation/proc-entries.txt [new file with mode: 0644]
drivers/staging/unisys/Kconfig [new file with mode: 0644]
drivers/staging/unisys/MAINTAINERS [new file with mode: 0644]
drivers/staging/unisys/Makefile [new file with mode: 0644]
drivers/staging/unisys/TODO [new file with mode: 0644]
drivers/staging/unisys/channels/Kconfig [new file with mode: 0644]
drivers/staging/unisys/channels/Makefile [new file with mode: 0644]
drivers/staging/unisys/channels/channel.c [new file with mode: 0644]
drivers/staging/unisys/channels/chanstub.c [new file with mode: 0644]
drivers/staging/unisys/channels/chanstub.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/channel.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/channel_guid.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/controlframework.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/diagchannel.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/iochannel.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/channels/vbuschannel.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/controlvmcompletionstatus.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/diagnostics/appos_subsystems.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/iovmcall_gnuc.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/version.h [new file with mode: 0644]
drivers/staging/unisys/common-spar/include/vmcallinterface.h [new file with mode: 0644]
drivers/staging/unisys/include/commontypes.h [new file with mode: 0644]
drivers/staging/unisys/include/guestlinuxdebug.h [new file with mode: 0644]
drivers/staging/unisys/include/guidutils.h [new file with mode: 0644]
drivers/staging/unisys/include/periodic_work.h [new file with mode: 0644]
drivers/staging/unisys/include/procobjecttree.h [new file with mode: 0644]
drivers/staging/unisys/include/sparstop.h [new file with mode: 0644]
drivers/staging/unisys/include/timskmod.h [new file with mode: 0644]
drivers/staging/unisys/include/timskmodutils.h [new file with mode: 0644]
drivers/staging/unisys/include/uisqueue.h [new file with mode: 0644]
drivers/staging/unisys/include/uisthread.h [new file with mode: 0644]
drivers/staging/unisys/include/uisutils.h [new file with mode: 0644]
drivers/staging/unisys/include/uniklog.h [new file with mode: 0644]
drivers/staging/unisys/include/vbushelper.h [new file with mode: 0644]
drivers/staging/unisys/uislib/Kconfig [new file with mode: 0644]
drivers/staging/unisys/uislib/Makefile [new file with mode: 0644]
drivers/staging/unisys/uislib/uislib.c [new file with mode: 0644]
drivers/staging/unisys/uislib/uisqueue.c [new file with mode: 0644]
drivers/staging/unisys/uislib/uisthread.c [new file with mode: 0644]
drivers/staging/unisys/uislib/uisutils.c [new file with mode: 0644]
drivers/staging/unisys/virthba/Kconfig [new file with mode: 0644]
drivers/staging/unisys/virthba/Makefile [new file with mode: 0644]
drivers/staging/unisys/virthba/virthba.c [new file with mode: 0644]
drivers/staging/unisys/virthba/virthba.h [new file with mode: 0644]
drivers/staging/unisys/virtpci/Kconfig [new file with mode: 0644]
drivers/staging/unisys/virtpci/Makefile [new file with mode: 0644]
drivers/staging/unisys/virtpci/virtpci.c [new file with mode: 0644]
drivers/staging/unisys/virtpci/virtpci.h [new file with mode: 0644]
drivers/staging/unisys/visorchannel/Kconfig [new file with mode: 0644]
drivers/staging/unisys/visorchannel/Makefile [new file with mode: 0644]
drivers/staging/unisys/visorchannel/globals.h [new file with mode: 0644]
drivers/staging/unisys/visorchannel/visorchannel.h [new file with mode: 0644]
drivers/staging/unisys/visorchannel/visorchannel_funcs.c [new file with mode: 0644]
drivers/staging/unisys/visorchannel/visorchannel_main.c [new file with mode: 0644]
drivers/staging/unisys/visorchipset/Kconfig [new file with mode: 0644]
drivers/staging/unisys/visorchipset/Makefile [new file with mode: 0644]
drivers/staging/unisys/visorchipset/controlvm.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/controlvm_direct.c [new file with mode: 0644]
drivers/staging/unisys/visorchipset/file.c [new file with mode: 0644]
drivers/staging/unisys/visorchipset/file.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/filexfer.c [new file with mode: 0644]
drivers/staging/unisys/visorchipset/filexfer.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/globals.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/parser.c [new file with mode: 0644]
drivers/staging/unisys/visorchipset/parser.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/testing.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/visorchipset.h [new file with mode: 0644]
drivers/staging/unisys/visorchipset/visorchipset_main.c [new file with mode: 0644]
drivers/staging/unisys/visorchipset/visorchipset_umode.h [new file with mode: 0644]
drivers/staging/unisys/visorutil/Kconfig [new file with mode: 0644]
drivers/staging/unisys/visorutil/Makefile [new file with mode: 0644]
drivers/staging/unisys/visorutil/charqueue.c [new file with mode: 0644]
drivers/staging/unisys/visorutil/charqueue.h [new file with mode: 0644]
drivers/staging/unisys/visorutil/easyproc.c [new file with mode: 0644]
drivers/staging/unisys/visorutil/easyproc.h [new file with mode: 0644]
drivers/staging/unisys/visorutil/memregion.h [new file with mode: 0644]
drivers/staging/unisys/visorutil/memregion_direct.c [new file with mode: 0644]
drivers/staging/unisys/visorutil/periodic_work.c [new file with mode: 0644]
drivers/staging/unisys/visorutil/procobjecttree.c [new file with mode: 0644]
drivers/staging/unisys/visorutil/visorkmodutils.c [new file with mode: 0644]
drivers/staging/usbip/stub_dev.c
drivers/staging/usbip/uapi/usbip.h [new file with mode: 0644]
drivers/staging/usbip/usbip_common.h
drivers/staging/usbip/userspace/libsrc/usbip_common.h
drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
drivers/staging/usbip/userspace/libsrc/vhci_driver.c
drivers/staging/vt6656/device.h
drivers/staging/vt6656/dpc.c
drivers/staging/vt6656/int.c
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/rxtx.c
drivers/staging/vt6656/usbpipe.c
drivers/staging/vt6656/wcmd.c
drivers/staging/vt6656/wcmd.h
drivers/staging/xgifb/XGI_main_26.c
drivers/target/target_core_sbc.c
drivers/target/target_core_transport.c
drivers/tty/tty_io.c
drivers/usb/chipidea/udc.c
drivers/usb/gadget/bcm63xx_udc.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_virthub.c
drivers/usb/musb/omap2430.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/watchdog/w83697hf_wdt.c
fs/ceph/acl.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifsacl.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb1ops.c
fs/cifs/smb2glob.h
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/ioctl.c
fs/ext4/resize.c
fs/ext4/super.c
fs/fs-writeback.c
fs/fscache/object-list.c
fs/fscache/object.c
fs/jbd2/transaction.c
fs/jfs/acl.c
fs/kernfs/mount.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs3proc.c
fs/nfs/nfs4client.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4state.c
fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.c
fs/notify/group.c
fs/notify/inotify/inotify.h
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/notification.c
fs/quota/dquot.c
fs/reiserfs/do_balan.c
fs/sync.c
fs/sysfs/mount.c
fs/udf/file.c
fs/udf/inode.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_sb.c
fs/xfs/xfs_super.c
include/asm-generic/pgtable.h
include/drm/drm_crtc.h
include/drm/ttm/ttm_page_alloc.h
include/linux/ceph/ceph_fs.h
include/linux/cgroup.h
include/linux/dma-buf.h
include/linux/fsnotify_backend.h
include/linux/ipc_namespace.h
include/linux/kernfs.h
include/linux/mfd/max8997-private.h
include/linux/mfd/max8998-private.h
include/linux/mfd/tps65217.h
include/linux/netdevice.h
include/linux/pci.h
include/linux/skbuff.h
include/linux/syscalls.h
include/linux/workqueue.h
include/linux/writeback.h
include/net/sctp/structs.h
include/sound/soc-dapm.h
include/trace/events/writeback.h
include/uapi/asm-generic/unistd.h
include/uapi/drm/drm.h
include/uapi/drm/vmwgfx_drm.h
ipc/mq_sysctl.c
ipc/mqueue.c
kernel/audit_tree.c
kernel/audit_watch.c
kernel/cgroup.c
kernel/events/core.c
kernel/power/console.c
kernel/printk/printk.c
kernel/sched/core.c
kernel/sched/cpudeadline.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/sched.h
kernel/time/sched_clock.c
kernel/user_namespace.c
kernel/workqueue.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory.c
mm/mprotect.c
mm/vmpressure.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/hard-interface.c
net/batman-adv/originator.c
net/batman-adv/originator.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/translation-table.c
net/bluetooth/hidp/core.c
net/bluetooth/hidp/hidp.h
net/core/dev.c
net/core/flow_dissector.c
net/core/rtnetlink.c
net/dccp/ccids/lib/tfrc.c
net/dccp/ccids/lib/tfrc.h
net/ipv4/ip_forward.c
net/ipv4/ipconfig.c
net/ipv4/route.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/mac80211/iface.c
net/packet/af_packet.c
net/sched/sch_pie.c
net/sctp/associola.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/ulpevent.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/xprtsock.c
net/tipc/core.h
net/tipc/link.c
scripts/Makefile.lib
security/selinux/ss/policydb.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/blackfin/Kconfig
sound/soc/codecs/ad1980.c
sound/soc/codecs/da732x.c
sound/soc/codecs/da9055.c
sound/soc/codecs/isabelle.c
sound/soc/codecs/max98090.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/fsl_esai.c
sound/soc/fsl/fsl_esai.h
sound/soc/fsl/imx-mc13783.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/fsl/imx-wm8962.c
sound/soc/samsung/Kconfig
sound/soc/soc-dapm.c
sound/soc/txx9/txx9aclc-ac97.c
sound/usb/mixer_maps.c
tools/perf/builtin-report.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/Makefile
tools/perf/config/feature-checks/Makefile
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/include/linux/bitops.h
tools/perf/util/parse-events.c
tools/perf/util/probe-event.c
tools/perf/util/session.c
tools/perf/util/symbol.c

index a2ccec35ffce2cedb601d4cad55012b56a3c4e6f..ad22fb0ee765b792a3bc0ab7f9d2995c69f1d5d0 100644 (file)
@@ -3,8 +3,7 @@ Date:           Nov 2010
 Contact:       Kay Sievers <kay.sievers@vrfy.org>
 Description:
                 Shows the list of currently configured
-                tty devices used for the console,
-                like 'tty1 ttyS0'.
+                console devices, like 'tty1 ttyS0'.
                 The last entry in the file is the active
                 device connected to /dev/console.
                 The file supports poll() to detect virtual
index a8d01005f480ad6be4c86f187665e9ef3d75d08e..10a93696e55ad33c821a5466ed813a07e9fb9930 100644 (file)
@@ -82,7 +82,19 @@ Most of the hard work is done for the driver in the PCI layer.  It simply
 has to request that the PCI layer set up the MSI capability for this
 device.
 
-4.2.1 pci_enable_msi_range
+4.2.1 pci_enable_msi
+
+int pci_enable_msi(struct pci_dev *dev)
+
+A successful call allocates ONE interrupt to the device, regardless
+of how many MSIs the device supports.  The device is switched from
+pin-based interrupt mode to MSI mode.  The dev->irq number is changed
+to a new number which represents the message signaled interrupt;
+consequently, this function should be called before the driver calls
+request_irq(), because an MSI is delivered via a vector that is
+different from the vector of a pin-based interrupt.
+
+4.2.2 pci_enable_msi_range
 
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
 
@@ -147,6 +159,11 @@ static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec)
        return pci_enable_msi_range(pdev, nvec, nvec);
 }
 
+Note, unlike pci_enable_msi_exact() function, which could be also used to
+enable a particular number of MSI-X interrupts, pci_enable_msi_range()
+returns either a negative errno or 'nvec' (not negative errno or 0 - as
+pci_enable_msi_exact() does).
+
 4.2.1.3 Single MSI mode
 
 The most notorious example of the request type described above is
@@ -158,7 +175,27 @@ static int foo_driver_enable_single_msi(struct pci_dev *pdev)
        return pci_enable_msi_range(pdev, 1, 1);
 }
 
-4.2.2 pci_disable_msi
+Note, unlike pci_enable_msi() function, which could be also used to
+enable the single MSI mode, pci_enable_msi_range() returns either a
+negative errno or 1 (not negative errno or 0 - as pci_enable_msi()
+does).
+
+4.2.3 pci_enable_msi_exact
+
+int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+
+This variation on pci_enable_msi_range() call allows a device driver to
+request exactly 'nvec' MSIs.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to request any more MSI interrupts for
+this device.
+
+By contrast with pci_enable_msi_range() function, pci_enable_msi_exact()
+returns zero in case of success, which indicates MSI interrupts have been
+successfully allocated.
+
+4.2.4 pci_disable_msi
 
 void pci_disable_msi(struct pci_dev *dev)
 
@@ -172,7 +209,7 @@ on any interrupt for which it previously called request_irq().
 Failure to do so results in a BUG_ON(), leaving the device with
 MSI enabled and thus leaking its vector.
 
-4.2.3 pci_msi_vec_count
+4.2.4 pci_msi_vec_count
 
 int pci_msi_vec_count(struct pci_dev *dev)
 
@@ -257,8 +294,8 @@ possible, likely up to the limit returned by pci_msix_vec_count() function:
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-       return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-                                   1, nvec);
+       return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                    1, nvec);
 }
 
 Note the value of 'minvec' parameter is 1.  As 'minvec' is inclusive,
@@ -269,8 +306,8 @@ In this case the function could look like this:
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-       return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-                                   FOO_DRIVER_MINIMUM_NVEC, nvec);
+       return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                    FOO_DRIVER_MINIMUM_NVEC, nvec);
 }
 
 4.3.1.2 Exact number of MSI-X interrupts
@@ -282,10 +319,15 @@ parameters:
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-       return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-                                   nvec, nvec);
+       return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                    nvec, nvec);
 }
 
+Note, unlike pci_enable_msix_exact() function, which could be also used to
+enable a particular number of MSI-X interrupts, pci_enable_msix_range()
+returns either a negative errno or 'nvec' (not negative errno or 0 - as
+pci_enable_msix_exact() does).
+
 4.3.1.3 Specific requirements to the number of MSI-X interrupts
 
 As noted above, there could be devices that can not operate with just any
@@ -332,7 +374,64 @@ Note how pci_enable_msix_range() return value is analized for a fallback -
 any error code other than -ENOSPC indicates a fatal error and should not
 be retried.
 
-4.3.2 pci_disable_msix
+4.3.2 pci_enable_msix_exact
+
+int pci_enable_msix_exact(struct pci_dev *dev,
+                         struct msix_entry *entries, int nvec)
+
+This variation on pci_enable_msix_range() call allows a device driver to
+request exactly 'nvec' MSI-Xs.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to allocate any more MSI-X interrupts for
+this device.
+
+By contrast with pci_enable_msix_range() function, pci_enable_msix_exact()
+returns zero in case of success, which indicates MSI-X interrupts have been
+successfully allocated.
+
+Another version of a routine that enables MSI-X mode for a device with
+specific requirements described in chapter 4.3.1.3 might look like this:
+
+/*
+ * Assume 'minvec' and 'maxvec' are non-zero
+ */
+static int foo_driver_enable_msix(struct foo_adapter *adapter,
+                                 int minvec, int maxvec)
+{
+       int rc;
+
+       minvec = roundup_pow_of_two(minvec);
+       maxvec = rounddown_pow_of_two(maxvec);
+
+       if (minvec > maxvec)
+               return -ERANGE;
+
+retry:
+       rc = pci_enable_msix_exact(adapter->pdev,
+                                  adapter->msix_entries, maxvec);
+
+       /*
+        * -ENOSPC is the only error code allowed to be analyzed
+        */
+       if (rc == -ENOSPC) {
+               if (maxvec == 1)
+                       return -ENOSPC;
+
+               maxvec /= 2;
+
+               if (minvec > maxvec)
+                       return -ENOSPC;
+
+               goto retry;
+       } else if (rc < 0) {
+               return rc;
+       }
+
+       return maxvec;
+}
+
+4.3.3 pci_disable_msix
 
 void pci_disable_msix(struct pci_dev *dev)
 
index 34dc40cffdfd8bfa316d55c2db5cc7a49fc1e999..af9b4a0d902b3f7a182864b02dbfec13fb6c2cba 100644 (file)
@@ -91,7 +91,7 @@ Boards:
   compatible = "ti,omap3-beagle", "ti,omap3"
 
 - OMAP3 Tobi with Overo : Commercial expansion board with daughter board
-  compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
+  compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3"
 
 - OMAP4 SDP : Software Development Board
   compatible = "ti,omap4-sdp", "ti,omap4430"
index 68b83ecc385007216d391f1a0edf06527dad5fb9..ee9be9961524cdcb45a0c43890064e8483702323 100644 (file)
@@ -1,12 +1,16 @@
 * Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
 
 Required properties:
-- compatible : Should be "fsl,imx31-sdma", "fsl,imx31-to1-sdma",
-  "fsl,imx31-to2-sdma", "fsl,imx35-sdma", "fsl,imx35-to1-sdma",
-  "fsl,imx35-to2-sdma", "fsl,imx51-sdma", "fsl,imx53-sdma" or
-  "fsl,imx6q-sdma". The -to variants should be preferred since they
-  allow to determnine the correct ROM script addresses needed for
-  the driver to work without additional firmware.
+- compatible : Should be one of
+      "fsl,imx25-sdma"
+      "fsl,imx31-sdma", "fsl,imx31-to1-sdma", "fsl,imx31-to2-sdma"
+      "fsl,imx35-sdma", "fsl,imx35-to1-sdma", "fsl,imx35-to2-sdma"
+      "fsl,imx51-sdma"
+      "fsl,imx53-sdma"
+      "fsl,imx6q-sdma"
+  The -to variants should be preferred since they allow to determnine the
+  correct ROM script addresses needed for the driver to work without additional
+  firmware.
 - reg : Should contain SDMA registers location and length
 - interrupts : Should contain SDMA interrupt
 - #dma-cells : Must be <3>.
diff --git a/Documentation/devicetree/bindings/net/sti-dwmac.txt b/Documentation/devicetree/bindings/net/sti-dwmac.txt
new file mode 100644 (file)
index 0000000..3dd3d0b
--- /dev/null
@@ -0,0 +1,58 @@
+STMicroelectronics SoC DWMAC glue layer controller
+
+The device node has following properties.
+
+Required properties:
+ - compatible  : Can be "st,stih415-dwmac", "st,stih416-dwmac" or
+   "st,stid127-dwmac".
+ - reg         : Offset of the glue configuration register map in system
+   configuration regmap pointed by st,syscon property and size.
+
+ - reg-names   : Should be "sti-ethconf".
+
+ - st,syscon   : Should be phandle to system configuration node which
+   encompases this glue registers.
+
+ - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be
+   wired up in from different sources. One via TXCLK pin and other via CLK_125
+   pin. This wiring is totally board dependent. However the retiming glue
+   logic should be configured accordingly. Possible values for this property
+
+          "txclk" - if 125Mhz clock is wired up via txclk line.
+          "clk_125" - if 125Mhz clock is wired up via clk_125 line.
+
+   This property is only valid for Giga bit setup( GMII, RGMII), and it is
+   un-used for non-giga bit (MII and RMII) setups. Also note that internal
+   clockgen can not generate stable 125Mhz clock.
+
+ - st,ext-phyclk: This boolean property indicates who is generating the clock
+  for tx and rx. This property is only valid for RMII case where the clock can
+  be generated from the MAC or PHY.
+
+ - clock-names: should be "sti-ethclk".
+ - clocks: Should point to ethernet clockgen which can generate phyclk.
+
+
+Example:
+
+ethernet0: dwmac@fe810000 {
+       device_type     = "network";
+       compatible      = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710";
+       reg             = <0xfe810000 0x8000>, <0x8bc 0x4>;
+       reg-names       = "stmmaceth", "sti-ethconf";
+       interrupts      = <0 133 0>, <0 134 0>, <0 135 0>;
+       interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+       phy-mode        = "mii";
+
+       st,syscon       = <&syscfg_rear>;
+
+       snps,pbl        = <32>;
+       snps,mixed-burst;
+
+       resets          = <&softreset STIH416_ETH0_SOFTRESET>;
+       reset-names     = "stmmaceth";
+       pinctrl-0       = <&pinctrl_mii0>;
+       pinctrl-names   = "default";
+       clocks          = <&CLK_S_GMAC0_PHY>;
+       clock-names     = "stmmaceth";
+};
diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt
deleted file mode 100644 (file)
index 72f38b1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-The 3Com Etherlink Plus (3c505) driver.
-
-This driver now uses DMA.  There is currently no support for PIO operation.
-The default DMA channel is 6; this is _not_ autoprobed, so you must
-make sure you configure it correctly.  If loading the driver as a
-module, you can do this with "modprobe 3c505 dma=n".  If the driver is
-linked statically into the kernel, you must either use an "ether="
-statement on the command line, or change the definition of ELP_DMA in 3c505.h.
-
-The driver will warn you if it has to fall back on the compiled in
-default DMA channel. 
-
-If no base address is given at boot time, the driver will autoprobe
-ports 0x300, 0x280 and 0x310 (in that order).  If no IRQ is given, the driver
-will try to probe for it.
-
-The driver can be used as a loadable module.
-
-Theoretically, one instance of the driver can now run multiple cards,
-in the standard way (when loading a module, say "modprobe 3c505
-io=0x300,0x340 irq=10,11 dma=6,7" or whatever).  I have not tested
-this, though.
-
-The driver may now support revision 2 hardware; the dependency on
-being able to read the host control register has been removed.  This
-is also untested, since I don't have a suitable card.
-
-Known problems:
- I still see "DMA upload timed out" messages from time to time.  These
-seem to be fairly non-fatal though.
- The card is old and slow.
-
-To do:
- Improve probe/setup code
- Test multicast and promiscuous operation
-
-Authors:
- The driver is mainly written by Craig Southeren, email
- <craigs@ineluki.apana.org.au>.
- Parts of the driver (adapting the driver to 1.1.4+ kernels,
- IRQ/address detection, some changes) and this README by
- Juha Laiho <jlaiho@ichaos.nullnet.fi>.
- DMA mode, more fixes, etc, by Philip Blundell <pjb27@cam.ac.uk>
- Multicard support, Software configurable DMA, etc., by
- Christopher Collins <ccollins@pcug.org.au>
index 9e484c081b8aeeb38c83605f8481b12fc93fa281..c3ff6236fca881ccccf2a4d6f3904262cbe9380f 100644 (file)
@@ -538,7 +538,7 @@ F:  arch/alpha/
 ALTERA UART/JTAG UART SERIAL DRIVERS
 M:     Tobias Klauser <tklauser@distanz.ch>
 L:     linux-serial@vger.kernel.org
-L:     nios2-dev@sopc.et.ntust.edu.tw (moderated for non-subscribers)
+L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/tty/serial/altera_uart.c
 F:     drivers/tty/serial/altera_jtaguart.c
@@ -1860,6 +1860,7 @@ F:        drivers/net/ethernet/broadcom/bnx2x/
 
 BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
 M:     Christian Daudt <bcm@fixthebug.org>
+M:     Matt Porter <mporter@linaro.org>
 L:     bcm-kernel-feedback-list@broadcom.com
 T:     git git://git.github.com/broadcom/bcm11351
 S:     Maintained
@@ -2408,8 +2409,10 @@ F:       tools/power/cpupower/
 
 CPUSETS
 M:     Li Zefan <lizefan@huawei.com>
+L:     cgroups@vger.kernel.org
 W:     http://www.bullopensource.org/cpuset/
 W:     http://oss.sgi.com/projects/cpusets/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
 S:     Maintained
 F:     Documentation/cgroups/cpusets.txt
 F:     include/linux/cpuset.h
@@ -2608,9 +2611,9 @@ DC395x SCSI driver
 M:     Oliver Neukum <oliver@neukum.org>
 M:     Ali Akcaagac <aliakc@web.de>
 M:     Jamie Lenehan <lenehan@twibble.org>
-W:     http://twibble.org/dist/dc395x/
 L:     dc395x@twibble.org
-L:     http://lists.twibble.org/mailman/listinfo/dc395x/
+W:     http://twibble.org/dist/dc395x/
+W:     http://lists.twibble.org/mailman/listinfo/dc395x/
 S:     Maintained
 F:     Documentation/scsi/dc395x.txt
 F:     drivers/scsi/dc395x.*
@@ -2845,12 +2848,22 @@ F:      lib/kobj*
 DRM DRIVERS
 M:     David Airlie <airlied@linux.ie>
 L:     dri-devel@lists.freedesktop.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+T:     git git://people.freedesktop.org/~airlied/linux
 S:     Maintained
 F:     drivers/gpu/drm/
 F:     include/drm/
 F:     include/uapi/drm/
 
+RADEON DRM DRIVERS
+M:     Alex Deucher <alexander.deucher@amd.com>
+M:     Christian König <christian.koenig@amd.com>
+L:     dri-devel@lists.freedesktop.org
+T:     git git://people.freedesktop.org/~agd5f/linux
+S:     Supported
+F:     drivers/gpu/drm/radeon/
+F:     include/drm/radeon*
+F:     include/uapi/drm/radeon*
+
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
 M:     Jani Nikula <jani.nikula@linux.intel.com>
@@ -3324,6 +3337,17 @@ S:       Maintained
 F:     include/linux/netfilter_bridge/
 F:     net/bridge/
 
+ETHERNET PHY LIBRARY
+M:     Florian Fainelli <f.fainelli@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     include/linux/phy.h
+F:     include/linux/phy_fixed.h
+F:     drivers/net/phy/
+F:     Documentation/networking/phy.txt
+F:     drivers/of/of_mdio.c
+F:     drivers/of/of_net.c
+
 EXT2 FILE SYSTEM
 M:     Jan Kara <jack@suse.cz>
 L:     linux-ext4@vger.kernel.org
@@ -5487,6 +5511,11 @@ W:       http://www.kernel.org/doc/man-pages
 L:     linux-man@vger.kernel.org
 S:     Maintained
 
+MARVELL ARMADA DRM SUPPORT
+M:     Russell King <rmk+kernel@arm.linux.org.uk>
+S:     Maintained
+F:     drivers/gpu/drm/armada/
+
 MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
 M:     Mirko Lindner <mlindner@marvell.com>
 M:     Stephen Hemminger <stephen@networkplumber.org>
@@ -8435,8 +8464,8 @@ TARGET SUBSYSTEM
 M:     Nicholas A. Bellinger <nab@linux-iscsi.org>
 L:     linux-scsi@vger.kernel.org
 L:     target-devel@vger.kernel.org
-L:     http://groups.google.com/group/linux-iscsi-target-dev
 W:     http://www.linux-iscsi.org
+W:     http://groups.google.com/group/linux-iscsi-target-dev
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
 S:     Supported
 F:     drivers/target/
@@ -9721,7 +9750,6 @@ F:        drivers/xen/*swiotlb*
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
 M:     Dave Chinner <david@fromorbit.com>
-M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
 W:     http://oss.sgi.com/projects/xfs
index 893d6f0e875bf7589f5de14317c60457fd2a9513..78209ee1f9811724f2ccc79b023fe2c7ad321105 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc5
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
@@ -605,10 +605,11 @@ endif
 ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
   stackp-flag := -fstack-protector
   ifeq ($(call cc-option, $(stackp-flag)),)
-    $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \
-             -fstack-protector not supported by compiler))
+    $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \
+             -fstack-protector not supported by compiler)
   endif
-else ifdef CONFIG_CC_STACKPROTECTOR_STRONG
+else
+ifdef CONFIG_CC_STACKPROTECTOR_STRONG
   stackp-flag := -fstack-protector-strong
   ifeq ($(call cc-option, $(stackp-flag)),)
     $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
@@ -618,6 +619,7 @@ else
   # Force off for distro compilers that enable stack protector by default.
   stackp-flag := $(call cc-option, -fno-stack-protector)
 endif
+endif
 KBUILD_CFLAGS += $(stackp-flag)
 
 # This warning generated too much noise in a regular build.
index 6d1e43d461871abdb0c94234da68ce21e67492b1..032030361bef2448ce84075212615d58c469cb8b 100644 (file)
@@ -209,7 +209,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
        omap3-n900.dtb \
        omap3-n9.dtb \
        omap3-n950.dtb \
-       omap3-tobi.dtb \
+       omap3-overo-tobi.dtb \
+       omap3-overo-storm-tobi.dtb \
        omap3-gta04.dtb \
        omap3-igep0020.dtb \
        omap3-igep0030.dtb \
index 4718ec4a4dbfef5e2a7273726cb6a8f0750623e3..486880b7483134c88f8638a6e7fb4cc98518e7e3 100644 (file)
                ti,model = "AM335x-EVMSK";
                ti,audio-codec = <&tlv320aic3106>;
                ti,mcasp-controller = <&mcasp1>;
-               ti,codec-clock-rate = <24576000>;
+               ti,codec-clock-rate = <24000000>;
                ti,audio-routing =
                        "Headphone Jack",       "HPLOUT",
                        "Headphone Jack",       "HPROUT";
                >;
        };
 
+       mmc1_pins: pinmux_mmc1_pins {
+               pinctrl-single,pins = <
+                       0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+               >;
+       };
+
        mcasp1_pins: mcasp1_pins {
                pinctrl-single,pins = <
                        0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
        status = "okay";
        vmmc-supply = <&vmmc_reg>;
        bus-width = <4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
 };
 
 &sham {
index 66609684d41b59ef701530fd2076553ffc4e9b6b..9480cf891f8cd0ce475d87cf2eed904a6a740eb7 100644 (file)
@@ -23,6 +23,7 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
+               eth3 = &eth3;
        };
 
        cpus {
                                interrupts = <91>;
                        };
 
-                       ethernet@34000 {
+                       eth3: ethernet@34000 {
                                compatible = "marvell,armada-370-neta";
                                reg = <0x34000 0x4000>;
                                interrupts = <14>;
index 2b76524f4aa74ee475d7e027f24683097ef4770f..187fd46b7b5ef018c2985e7db5298784338f0507 100644 (file)
                                #clock-cells = <1>;
                        };
 
-                       pmu_intc: pmu-interrupt-ctrl@d0050 {
-                               compatible = "marvell,dove-pmu-intc";
-                               interrupt-controller;
-                               #interrupt-cells = <1>;
-                               reg = <0xd0050 0x8>;
-                               interrupts = <33>;
-                               marvell,#interrupts = <7>;
-                       };
-
                        pinctrl: pin-ctrl@d0200 {
                                compatible = "marvell,dove-pinctrl";
                                reg = <0xd0200 0x10>;
                        rtc: real-time-clock@d8500 {
                                compatible = "marvell,orion-rtc";
                                reg = <0xd8500 0x20>;
-                               interrupt-parent = <&pmu_intc>;
-                               interrupts = <5>;
                        };
 
                        gpio2: gpio-ctrl@e8400 {
index be1407cf5abd1b1479e55fbfeac48be44dc90d4c..6ff15a0eacb3ccfcb52ce450b189f6e0ebc51aa7 100644 (file)
@@ -21,7 +21,7 @@
                reg = <0x90000000 0x20000000>;
        };
 
-       display@di0 {
+       display0: display@di0 {
                compatible = "fsl,imx-parallel-display";
                crtcs = <&ipu 0>;
                interface-pix-fmt = "rgb24";
@@ -43,7 +43,7 @@
                };
        };
 
-       display@di1 {
+       display1: display@di1 {
                compatible = "fsl,imx-parallel-display";
                crtcs = <&ipu 1>;
                interface-pix-fmt = "rgb565";
                };
        };
 
+       imx-drm {
+               compatible = "fsl,imx-drm";
+               crtcs = <&ipu 0>, <&ipu 1>;
+               connectors = <&display0>, <&display1>;
+       };
+
        sound {
                compatible = "fsl,imx51-babbage-sgtl5000",
                             "fsl,imx-audio-sgtl5000";
index 7d304d02ed384e744c4789e3329ccdd80e103ac6..ee6107b6484c64798caea5b1fefcc7c4e46eb6b6 100644 (file)
@@ -21,7 +21,7 @@
        };
 
        soc {
-               display@di1 {
+               display1: display@di1 {
                        compatible = "fsl,imx-parallel-display";
                        crtcs = <&ipu 1>;
                        interface-pix-fmt = "bgr666";
                default-brightness-level = <6>;
        };
 
+       imx-drm {
+               compatible = "fsl,imx-drm";
+               crtcs = <&ipu 1>;
+               connectors = <&display1>;
+       };
+
        leds {
                compatible = "gpio-leds";
                pinctrl-names = "default";
index a630902679410f9a4f356ab430a3199bf3ac852b..9b6e76980a74c736def32e1926e9967312c9f390 100644 (file)
                status = "disabled";
        };
 
+       imx-drm {
+               compatible = "fsl,imx-drm";
+               crtcs = <&ipu 1>;
+               connectors = <&disp1>, <&tve>;
+       };
+
        reg_3p2v: 3p2v {
                compatible = "regulator-fixed";
                regulator-name = "3P2V";
index 91a5935a4aacd63879f2f2104f546d6f41bb7e60..3cb4f7791a9120c8ceb89afbe324904d3e0c49f2 100644 (file)
@@ -21,7 +21,7 @@
                reg = <0x70000000 0x40000000>;
        };
 
-       display@di0 {
+       display0: display@di0 {
                compatible = "fsl,imx-parallel-display";
                crtcs = <&ipu 0>;
                interface-pix-fmt = "rgb565";
                };
        };
 
+       imx-drm {
+               compatible = "fsl,imx-drm";
+               crtcs = <&ipu 0>;
+               connectors = <&display0>;
+       };
+
        leds {
                compatible = "gpio-leds";
                pinctrl-names = "default";
index fd8fc7cd53f3158bf7e030659a09a0c3ae476edc..5bfae54fb7806f4391a93ab89bdb1dd621358c03 100644 (file)
                };
        };
 
-       codec: spdif-transmitter {
-               compatible = "linux,spdif-dit";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_hummingboard_spdif>;
-       };
-
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
                model = "imx-spdif";
                };
 
                pinctrl_hummingboard_spdif: hummingboard-spdif {
-                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>;
+                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
                };
 
                pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus {
 };
 
 &spdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hummingboard_spdif>;
        status = "okay";
 };
 
index 9e8ae118fdd4e6c6c1df48a0b4a66c20e0504ae6..6dc39702221437f9cc60ea9d057fff311209f593 100644 (file)
@@ -88,3 +88,8 @@
                crtcs = <&ipu1 0>, <&ipu1 1>;
        };
 };
+
+&hdmi {
+       compatible = "fsl,imx6dl-hdmi";
+       crtcs = <&ipu1 0>, <&ipu1 1>;
+};
index 9cbdfe7a0931ff4fa8c09db3c9ea0fa3bb397609..66f220a82e4593b817fdee321bdf3fa63cfe4def 100644 (file)
        compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
 };
 
+&imx_drm {
+       crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
+
 &sata {
        status = "okay";
 };
index f024ef28b34b9373895dbbb913c475eebb33298a..187fe33ba515e86126a3447a0bdf518f00f4a46e 100644 (file)
                crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
        };
 };
+
+&hdmi {
+       compatible = "fsl,imx6q-hdmi";
+       crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
index 64daa3b311f6f057e8ecf05ec6f7ea84b9c36ed8..c2a24888a2768969263e1b8536e98ec869b4ff4f 100644 (file)
                };
        };
 
-       codec: spdif-transmitter {
-               compatible = "linux,spdif-dit";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_cubox_i_spdif>;
-       };
-
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
                model = "imx-spdif";
@@ -89,7 +83,7 @@
                };
 
                pinctrl_cubox_i_spdif: cubox-i-spdif {
-                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>;
+                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
                };
 
                pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
 };
 
 &spdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cubox_i_spdif>;
        status = "okay";
 };
 
index e75e11b36dffec5ea9e695c01d8f66ac35b83dee..dfca3e001398fa6e90a82a81e8e128291a440c86 100644 (file)
                };
        };
 
+       imx_drm: imx-drm {
+               compatible = "fsl,imx-drm";
+               crtcs = <&ipu1 0>, <&ipu1 1>;
+               connectors = <&ldb>;
+       };
+
        sound {
                compatible = "fsl,imx6q-sabresd-wm8962",
                           "fsl,imx-audio-wm8962";
index fb28b2ecb1db37a28a9effbd7bea591ace78554a..930ebe0c29370498fd847cda27093b050e1f9c53 100644 (file)
                                };
                        };
 
+                       hdmi: hdmi@0120000 {
+                               reg = <0x00120000 0x9000>;
+                               interrupts = <0 115 0x04>;
+                               gpr = <&gpr>;
+                               clocks = <&clks 123>, <&clks 124>;
+                               clock-names = "iahb", "isfr";
+                               status = "disabled";
+                       };
+
                        dcic1: dcic@020e4000 {
                                reg = <0x020e4000 0x4000>;
                                interrupts = <0 124 0x04>;
index b9b55c95a566c3ea6f6f21e55b787b9c31c2194f..c551e4af4d83712f67b69b260be16434523305d9 100644 (file)
@@ -32,7 +32,7 @@
                aux-button {
                        label = "aux";
                        linux,code = <169>;
-                       gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+                       gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
                        gpio-key,wakeup;
                };
        };
@@ -92,6 +92,8 @@
        bmp085@77 {
                compatible = "bosch,bmp085";
                reg = <0x77>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <17 IRQ_TYPE_EDGE_RISING>;
        };
 
        /* leds */
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        vmmc-supply = <&vmmc1>;
-       vmmc_aux-supply = <&vsim>;
        bus-width = <4>;
+       ti,non-removable;
 };
 
 &mmc2 {
index 39828ce464ee527b900ff6a2013660fe1c231822..9938b5dc1909c00f01e587f15a4a1c1d2a6bc665 100644 (file)
@@ -14,5 +14,5 @@
 
 / {
        model = "Nokia N9";
-       compatible = "nokia,omap3-n9", "ti,omap3";
+       compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3";
 };
index 6fc85f96353024ad61d04d74d7ca51f8afb1c7ce..0bf40c90faba626c88b539965a1f928aa09bf313 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Pavel Machek <pavel@ucw.cz>
- * Copyright 2013 Aaro Koskinen <aaro.koskinen@iki.fi>
+ * Copyright (C) 2013-2014 Aaro Koskinen <aaro.koskinen@iki.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 (or later) as
@@ -13,7 +13,7 @@
 
 / {
        model = "Nokia N900";
-       compatible = "nokia,omap3-n900", "ti,omap3";
+       compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3";
 
        cpus {
                cpu@0 {
index b076a526b99973a3489bf831e0cec5c1dcff93bb..261c5589bfa3170e76cc8f469ac1d6ca07a02765 100644 (file)
@@ -14,5 +14,5 @@
 
 / {
        model = "Nokia N950";
-       compatible = "nokia,omap3-n950", "ti,omap3";
+       compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3";
 };
diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts
new file mode 100644 (file)
index 0000000..966b5c9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * 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.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+       model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi";
+       compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3";
+};
+
similarity index 94%
rename from arch/arm/boot/dts/omap3-tobi.dts
rename to arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
index 7e4ad2aec37a8c82c2b88e771bfa741c13500fa5..4edc013a91c1717f3ae0757e3c2c23ce80bf383e 100644 (file)
@@ -13,9 +13,6 @@
 #include "omap3-overo.dtsi"
 
 / {
-       model = "TI OMAP3 Gumstix Overo on Tobi";
-       compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3";
-
        leds {
                compatible = "gpio-leds";
                heartbeat {
diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts
new file mode 100644 (file)
index 0000000..de5653e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * 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.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+       model = "OMAP35xx Gumstix Overo on Tobi";
+       compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3";
+};
+
index a461d2fd1fb0e81862805ccec939e1c1b3a41244..597099907f8ef77423210bcf6cb2be26f8799eb5 100644 (file)
@@ -9,9 +9,6 @@
 /*
  * The Gumstix Overo must be combined with an expansion board.
  */
-/dts-v1/;
-
-#include "omap34xx.dtsi"
 
 / {
        pwmleds {
index 389e987ec2819e31725329102f84d6f3cecbb5cd..44ec401ec36682289d8e4afa3b9b87791cd82c73 100644 (file)
@@ -57,6 +57,8 @@
                        resets = <&tegra_car 27>;
                        reset-names = "dc";
 
+                       nvidia,head = <0>;
+
                        rgb {
                                status = "disabled";
                        };
@@ -72,6 +74,8 @@
                        resets = <&tegra_car 26>;
                        reset-names = "dc";
 
+                       nvidia,head = <1>;
+
                        rgb {
                                status = "disabled";
                        };
index 480ecda3416b841b8941105d24646f1240f5ab37..48d2a7f4d0c05e2808a5cb2150298c41c1aa3367 100644 (file)
@@ -94,6 +94,8 @@
                        resets = <&tegra_car 27>;
                        reset-names = "dc";
 
+                       nvidia,head = <0>;
+
                        rgb {
                                status = "disabled";
                        };
                        resets = <&tegra_car 26>;
                        reset-names = "dc";
 
+                       nvidia,head = <1>;
+
                        rgb {
                                status = "disabled";
                        };
index 9104224124eeaac83bcedbd0e2fb7bcb3887d631..1e156d9d0506085c4ea615ac8c7e06193573edcb 100644 (file)
@@ -28,7 +28,7 @@
        compatible = "nvidia,cardhu", "nvidia,tegra30";
 
        aliases {
-               rtc0 = "/i2c@7000d000/tps6586x@34";
+               rtc0 = "/i2c@7000d000/tps65911@2d";
                rtc1 = "/rtc@7000e000";
        };
 
index ed8e7700b46dac0ba9d5ba34754fb5f8ae3dd976..19a84e933f4eae0799fc194b386bfdc51b85b880 100644 (file)
                        resets = <&tegra_car 27>;
                        reset-names = "dc";
 
+                       nvidia,head = <0>;
+
                        rgb {
                                status = "disabled";
                        };
                        resets = <&tegra_car 26>;
                        reset-names = "dc";
 
+                       nvidia,head = <1>;
+
                        rgb {
                                status = "disabled";
                        };
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
deleted file mode 100644 (file)
index 3f123ec..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/include/ "tests-phandle.dtsi"
-/include/ "tests-interrupts.dtsi"
index f43907c40c93a8cb9b101d72043fc48621e0f795..65f6577113235749c3635dc30d321fa3c775b1c0 100644 (file)
@@ -1,4 +1,4 @@
-/include/ "versatile-ab.dts"
+#include <versatile-ab.dts>
 
 / {
        model = "ARM Versatile PB";
@@ -47,4 +47,4 @@
        };
 };
 
-/include/ "testcases/tests.dtsi"
+#include <testcases.dtsi>
index e9a49fe0284e41c2f6d6d9448fb73e9a2ad99ead..8b8b61685a3436158923b30cc80106364e02d509 100644 (file)
@@ -212,6 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 static inline void __flush_icache_all(void)
 {
        __flush_icache_preferred();
+       dsb();
 }
 
 /*
index 03243f7eeddfc57beebb8100132dae059f96af77..85c60adc8b60bd04a68c3012b0c22ec7c1bf9bba 100644 (file)
 /*
  * 2nd stage PTE definitions for LPAE.
  */
-#define L_PTE_S2_MT_UNCACHED    (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITEBACK   (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_RDONLY                 (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
-#define L_PTE_S2_RDWR           (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_MT_UNCACHED           (_AT(pteval_t, 0x0) << 2) /* strongly ordered */
+#define L_PTE_S2_MT_WRITETHROUGH       (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */
+#define L_PTE_S2_MT_WRITEBACK          (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */
+#define L_PTE_S2_MT_DEV_SHARED         (_AT(pteval_t, 0x1) << 2) /* device */
+#define L_PTE_S2_MT_MASK               (_AT(pteval_t, 0xf) << 2)
 
-#define L_PMD_S2_RDWR           (_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_RDONLY                        (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
+#define L_PTE_S2_RDWR                  (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
+
+#define L_PMD_S2_RDWR                  (_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
 
 /*
  * Hyp-mode PL2 PTE definitions for LPAE.
index ef3c6072aa45345ae4594f22aebbe9a9ebc538f1..ac4bfae26702b0be3333c1184f1ac552f6c0eddd 100644 (file)
 
 static inline void dsb_sev(void)
 {
-#if __LINUX_ARM_ARCH__ >= 7
-       __asm__ __volatile__ (
-               "dsb ishst\n"
-               SEV
-       );
-#else
-       __asm__ __volatile__ (
-               "mcr p15, 0, %0, c7, c10, 4\n"
-               SEV
-               : : "r" (0)
-       );
-#endif
+
+       dsb(ishst);
+       __asm__(SEV);
 }
 
 /*
index b0df9761de6dc1109f727e0300ff91448f8fd55b..1e8b030dbefd8b2b19da27d9ca8ecabfaf610bba 100644 (file)
@@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
        kernel_data.end     = virt_to_phys(_end - 1);
 
        for_each_memblock(memory, region) {
-               res = memblock_virt_alloc_low(sizeof(*res), 0);
+               res = memblock_virt_alloc(sizeof(*res), 0);
                res->name  = "System RAM";
                res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
                res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
index 1d8248ea5669fa81209b2a7a8a055b7855a8c1f3..bd18bb8b2770ced6a65e5b3ad50dd79963d49c3b 100644 (file)
@@ -878,7 +878,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
                                    unsigned long cmd,
                                    void *v)
 {
-       if (cmd == CPU_PM_EXIT) {
+       if (cmd == CPU_PM_EXIT &&
+           __hyp_get_vectors() == hyp_default_vectors) {
                cpu_init_hyp_mode(NULL);
                return NOTIFY_OK;
        }
index ddc15539bad2c5996dcd5167e694b16dbdd9488b..0d68d4073068e8ad665840b8f51319e9b2bdbd89 100644 (file)
@@ -220,6 +220,10 @@ after_vfp_restore:
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
  * passed in r0 and r1.
  *
+ * A function pointer with a value of 0xffffffff has a special meaning,
+ * and is used to implement __hyp_get_vectors in the same way as in
+ * arch/arm/kernel/hyp_stub.S.
+ *
  * The calling convention follows the standard AAPCS:
  *   r0 - r3: caller save
  *   r12:     caller save
@@ -363,6 +367,11 @@ hyp_hvc:
 host_switch_to_hyp:
        pop     {r0, r1, r2}
 
+       /* Check for __hyp_get_vectors */
+       cmp     r0, #-1
+       mrceq   p15, 4, r0, c12, c0, 0  @ get HVBAR
+       beq     1f
+
        push    {lr}
        mrs     lr, SPSR
        push    {lr}
@@ -378,7 +387,7 @@ THUMB(      orr     lr, #1)
        pop     {lr}
        msr     SPSR_csxf, lr
        pop     {lr}
-       eret
+1:     eret
 
 guest_trap:
        load_vcpu                       @ Load VCPU pointer to r0
index befcaf5d05740c4ad1a417d8be62ddae9a38f59a..ec419649320ffe8fd6cae929d4664ae8071c9fff 100644 (file)
@@ -101,11 +101,9 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 
-ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
 # i.MX6SL reuses i.MX6Q code
 obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o
-endif
 
 # i.MX5 based machines
 obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
index 59c3b9b26bb40bbabe40f471d6a420efee43a1c2..baf439dc22d8268d65bd269f508c968aae822046 100644 (file)
@@ -144,13 +144,11 @@ void imx6q_set_chicken_bit(void);
 void imx_cpu_die(unsigned int cpu);
 int imx_cpu_kill(unsigned int cpu);
 
-#ifdef CONFIG_PM
 void imx6q_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
+#ifdef CONFIG_PM
 void imx5_pm_init(void);
 #else
-static inline void imx6q_pm_init(void) {}
-static inline void imx6q_pm_set_ccm_base(void __iomem *base) {}
 static inline void imx5_pm_init(void) {}
 #endif
 
index 91449c5cb70f46affaf85602ec8f98b6f393d10f..85089d821982193b2e2d79f5f5fbf050eefad464 100644 (file)
@@ -156,6 +156,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
        .register_dev   = 1,
        .hmc_mode       = 16,
        .pins[0]        = 6,
+       .extcon         = "tahvo-usb",
 };
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
index e2ce4f8366a785237b8c73c7a1792f0a2cadd0a7..0af7ca02314d99aa72baefb69959ccfba3380758 100644 (file)
@@ -50,6 +50,7 @@ config SOC_OMAP5
        bool "TI OMAP5"
        depends on ARCH_MULTI_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select CPU_V7
@@ -63,6 +64,7 @@ config SOC_AM33XX
        bool "TI AM33XX"
        depends on ARCH_MULTI_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select CPU_V7
        select MULTI_IRQ_HANDLER
@@ -72,6 +74,7 @@ config SOC_AM43XX
        depends on ARCH_MULTI_V7
        select CPU_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select MULTI_IRQ_HANDLER
        select ARM_GIC
        select MACH_OMAP_GENERIC
@@ -80,6 +83,7 @@ config SOC_DRA7XX
        bool "TI DRA7XX"
        depends on ARCH_MULTI_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select CPU_V7
@@ -268,9 +272,6 @@ config MACH_OMAP_3430SDP
        default y
        select OMAP_PACKAGE_CBB
 
-config MACH_NOKIA_N800
-       bool
-
 config MACH_NOKIA_N810
        bool
 
@@ -281,7 +282,6 @@ config MACH_NOKIA_N8X0
        bool "Nokia N800/N810"
        depends on SOC_OMAP2420
        default y
-       select MACH_NOKIA_N800
        select MACH_NOKIA_N810
        select MACH_NOKIA_N810_WIMAX
        select OMAP_PACKAGE_ZAC
index d24926e6340fa714cf0aeacca14a6578e5b481a4..ab43755364f5a7c06ecfc367c0f055d65876dc54 100644 (file)
@@ -1339,7 +1339,7 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
                of_property_read_bool(np, "gpmc,time-para-granularity");
 }
 
-#ifdef CONFIG_MTD_NAND
+#if IS_ENABLED(CONFIG_MTD_NAND)
 
 static const char * const nand_xfer_types[] = {
        [NAND_OMAP_PREFETCH_POLLED]             = "prefetch-polled",
@@ -1429,7 +1429,7 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
 }
 #endif
 
-#ifdef CONFIG_MTD_ONENAND
+#if IS_ENABLED(CONFIG_MTD_ONENAND)
 static int gpmc_probe_onenand_child(struct platform_device *pdev,
                                 struct device_node *child)
 {
index d408b15b4fbfd97ecd3d82aaa46cc86788e63a8c..af432b191255030a7c8fda2be849be0a75620482 100644 (file)
@@ -179,15 +179,6 @@ static struct map_desc omap34xx_io_desc[] __initdata = {
                .length         = L4_EMU_34XX_SIZE,
                .type           = MT_DEVICE
        },
-#if defined(CONFIG_DEBUG_LL) &&                                                        \
-       (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3))
-       {
-               .virtual        = ZOOM_UART_VIRT,
-               .pfn            = __phys_to_pfn(ZOOM_UART_BASE),
-               .length         = SZ_1M,
-               .type           = MT_DEVICE
-       },
-#endif
 };
 #endif
 
index f70583fee59f8b61e59a1022f07b36c26fd3210c..29997bde277d1be730aa85d98a2ae17bc0bc2da5 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/reboot.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/max1586.h>
 #include <linux/slab.h>
 #include <linux/i2c/pxa-i2c.h>
@@ -714,6 +715,10 @@ static struct gpio global_gpios[] = {
        { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" },
 };
 
+static struct regulator_consumer_supply fixed_5v0_consumers[] = {
+       REGULATOR_SUPPLY("power", "pwm-backlight"),
+};
+
 static void __init mioa701_machine_init(void)
 {
        int rc;
@@ -753,6 +758,10 @@ static void __init mioa701_machine_init(void)
        pxa_set_i2c_info(&i2c_pdata);
        pxa27x_set_i2c_power_info(NULL);
        pxa_set_camera_info(&mioa701_pxacamera_platform_data);
+
+       regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers,
+                                    ARRAY_SIZE(fixed_5v0_consumers),
+                                    5000000);
 }
 
 static void mioa701_machine_exit(void)
index 4ae0286b468db6209311d14d13cd9cc673fb200b..f55b05a29b55f3ed655b36b1edf1f93f85d09c9d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/suspend.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <linux/clk/tegra.h>
 
 #include <asm/smp_plat.h>
index 303a285d80fd7b7d7cc4280779c343b4a3123f4a..6191603379e13cad2da1552954c3e2fb903cc241 100644 (file)
@@ -73,10 +73,20 @@ u32 tegra_uart_config[3] = {
 static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
+       static const struct of_device_id pl310_ids[] __initconst = {
+               { .compatible = "arm,pl310-cache",  },
+               {}
+       };
+
+       struct device_node *np;
        int ret;
        void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
        u32 aux_ctrl, cache_type;
 
+       np = of_find_matching_node(NULL, pl310_ids);
+       if (!np)
+               return;
+
        cache_type = readl(p + L2X0_CACHE_TYPE);
        aux_ctrl = (cache_type & 0x700) << (17-8);
        aux_ctrl |= 0x7C400001;
index 1a77450e728ad17cf6b8fec2beb3111a2a8bfb94..11b3914660d2a9f518f15b09028d3dad78ad07e0 100644 (file)
@@ -1358,7 +1358,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
-       if (gfp & GFP_ATOMIC)
+       if (!(gfp & __GFP_WAIT))
                return __iommu_alloc_atomic(dev, size, handle);
 
        /*
index d5a982d15a88e2a37a524267f31633f497aa0d4b..7ea641b7aa7d2b6ffd240b9fe0e7f7897a5a2d1a 100644 (file)
@@ -38,6 +38,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt)
 
 struct mem_type {
        pteval_t prot_pte;
+       pteval_t prot_pte_s2;
        pmdval_t prot_l1;
        pmdval_t prot_sect;
        unsigned int domain;
index 4f08c133cc255e2e2c2b93a0f28b79caaf3fc795..a623cb3ad012b196aacd11fc7f122fb84c0e3765 100644 (file)
@@ -232,12 +232,16 @@ __setup("noalign", noalign_setup);
 #endif /* ifdef CONFIG_CPU_CP15 / else */
 
 #define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
+#define PROT_PTE_S2_DEVICE     PROT_PTE_DEVICE
 #define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
 static struct mem_type mem_types[] = {
        [MT_DEVICE] = {           /* Strongly ordered / ARMv6 shared device */
                .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
                                  L_PTE_SHARED,
+               .prot_pte_s2    = s2_policy(PROT_PTE_S2_DEVICE) |
+                                 s2_policy(L_PTE_S2_MT_DEV_SHARED) |
+                                 L_PTE_SHARED,
                .prot_l1        = PMD_TYPE_TABLE,
                .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_S,
                .domain         = DOMAIN_IO,
@@ -508,7 +512,8 @@ static void __init build_mem_type_table(void)
        cp = &cache_policies[cachepolicy];
        vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
        s2_pgprot = cp->pte_s2;
-       hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+       hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+       s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2;
 
        /*
         * ARMv6 and above have extended page tables.
index 45dc29f85d56ca79ae7fa6076f3cee103465e15b..32b3558321c40db0d31e6898ad3ea329e049bca4 100644 (file)
@@ -208,7 +208,6 @@ __v6_setup:
        mcr     p15, 0, r0, c7, c14, 0          @ clean+invalidate D cache
        mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
        mcr     p15, 0, r0, c7, c15, 0          @ clean+invalidate cache
-       mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
 #ifdef CONFIG_MMU
        mcr     p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
        mcr     p15, 0, r0, c2, c0, 2           @ TTB control register
@@ -218,6 +217,8 @@ __v6_setup:
        ALT_UP(orr      r8, r8, #TTB_FLAGS_UP)
        mcr     p15, 0, r8, c2, c0, 1           @ load TTB1
 #endif /* CONFIG_MMU */
+       mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer and
+                                               @ complete invalidations
        adr     r5, v6_crval
        ldmia   r5, {r5, r6}
  ARM_BE8(orr   r6, r6, #1 << 25)               @ big-endian page tables
index bd1781979a391825043d078192666e5a846cdae5..74f6033e76dd1702e89631334a813f5ea9ec1046 100644 (file)
@@ -351,7 +351,6 @@ __v7_setup:
 
 4:     mov     r10, #0
        mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
-       dsb
 #ifdef CONFIG_MMU
        mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
        v7_ttb_setup r10, r4, r8, r5            @ TTBCR, TTBRx setup
@@ -360,6 +359,7 @@ __v7_setup:
        mcr     p15, 0, r5, c10, c2, 0          @ write PRRR
        mcr     p15, 0, r6, c10, c2, 1          @ write NMRR
 #endif
+       dsb                                     @ Complete invalidations
 #ifndef CONFIG_ARM_THUMBEE
        mrc     p15, 0, r0, c0, c1, 0           @ read ID_PFR0 for ThumbEE
        and     r0, r0, #(0xf << 12)            @ ThumbEE enabled field
index 13fb0b3efc5f7206bb8e187ea07ff6c3337ff2be..453a179469a34fd9ffa72ec723a6bada988d4e73 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __ASM_PERCPU_H
 #define __ASM_PERCPU_H
 
+#ifdef CONFIG_SMP
+
 static inline void set_my_cpu_offset(unsigned long off)
 {
        asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
@@ -36,6 +38,12 @@ static inline unsigned long __my_cpu_offset(void)
 }
 #define __my_cpu_offset __my_cpu_offset()
 
+#else  /* !CONFIG_SMP */
+
+#define set_my_cpu_offset(x)   do { } while (0)
+
+#endif /* CONFIG_SMP */
+
 #include <asm-generic/percpu.h>
 
 #endif /* __ASM_PERCPU_H */
index b524dcd17243d712b4d461cf77d4dd56ed04c8bb..aa3917c8b62318aef9424735d560be305f3465d3 100644 (file)
@@ -136,11 +136,11 @@ extern struct page *empty_zero_page;
 /*
  * The following only work if pte_present(). Undefined behaviour otherwise.
  */
-#define pte_present(pte)       (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
-#define pte_dirty(pte)         (pte_val(pte) & PTE_DIRTY)
-#define pte_young(pte)         (pte_val(pte) & PTE_AF)
-#define pte_special(pte)       (pte_val(pte) & PTE_SPECIAL)
-#define pte_write(pte)         (pte_val(pte) & PTE_WRITE)
+#define pte_present(pte)       (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
+#define pte_dirty(pte)         (!!(pte_val(pte) & PTE_DIRTY))
+#define pte_young(pte)         (!!(pte_val(pte) & PTE_AF))
+#define pte_special(pte)       (!!(pte_val(pte) & PTE_SPECIAL))
+#define pte_write(pte)         (!!(pte_val(pte) & PTE_WRITE))
 #define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #define pte_valid_user(pte) \
index c3b6c63ea5fb3abe0f154544aee2eb09063c0eb8..38f0558f0c0a56a7a57fe9bb12d08eb01dea7cdc 100644 (file)
@@ -48,7 +48,11 @@ int unwind_frame(struct stackframe *frame)
 
        frame->sp = fp + 0x10;
        frame->fp = *(unsigned long *)(fp);
-       frame->pc = *(unsigned long *)(fp + 8);
+       /*
+        * -4 here because we care about the PC at time of bl,
+        * not where the return will go.
+        */
+       frame->pc = *(unsigned long *)(fp + 8) - 4;
 
        return 0;
 }
index 3b47c36e10ffcdac920a08277ee9e3e1df00a211..2c56012cb2d2c8d82588063058f4444e188d13f6 100644 (file)
@@ -694,6 +694,24 @@ __hyp_panic_str:
 
        .align  2
 
+/*
+ * u64 kvm_call_hyp(void *hypfn, ...);
+ *
+ * This is not really a variadic function in the classic C-way and care must
+ * be taken when calling this to ensure parameters are passed in registers
+ * only, since the stack will change between the caller and the callee.
+ *
+ * Call the function with the first argument containing a pointer to the
+ * function you wish to call in Hyp mode, and subsequent arguments will be
+ * passed as x0, x1, and x2 (a maximum of 3 arguments in addition to the
+ * function pointer can be passed).  The function being called must be mapped
+ * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
+ * passed in r0 and r1.
+ *
+ * A function pointer with a value of 0 has a special meaning, and is
+ * used to implement __hyp_get_vectors in the same way as in
+ * arch/arm64/kernel/hyp_stub.S.
+ */
 ENTRY(kvm_call_hyp)
        hvc     #0
        ret
@@ -737,7 +755,12 @@ el1_sync:                                  // Guest trapped into EL2
        pop     x2, x3
        pop     x0, x1
 
-       push    lr, xzr
+       /* Check for __hyp_get_vectors */
+       cbnz    x0, 1f
+       mrs     x0, vbar_el2
+       b       2f
+
+1:     push    lr, xzr
 
        /*
         * Compute the function address in EL2, and shuffle the parameters.
@@ -750,7 +773,7 @@ el1_sync:                                   // Guest trapped into EL2
        blr     lr
 
        pop     lr, xzr
-       eret
+2:     eret
 
 el1_trap:
        /*
index 22fb66590dcd0e6f7339c9723a9128eb078cdb06..dba48a5d5bb9db351ff62bafc23a62a7047b42b5 100644 (file)
@@ -11,7 +11,7 @@ all: uImage vmlinux.elf
 
 KBUILD_DEFCONFIG       := atstk1002_defconfig
 
-KBUILD_CFLAGS  += -pipe -fno-builtin -mno-pic
+KBUILD_CFLAGS  += -pipe -fno-builtin -mno-pic -D__linux__
 KBUILD_AFLAGS  += -mrelax -mno-pic
 KBUILD_CFLAGS_MODULE += -mno-relax
 LDFLAGS_vmlinux        += --relax
index 9764a1a1073e933aa1c2d6a73e51483553da2dfa..c1466a872b9c8598ca184f65eb32f3320669f4b1 100644 (file)
@@ -11,6 +11,7 @@
 #define FRAM_VERSION   "1.0"
 
 #include <linux/miscdevice.h>
+#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/io.h>
index cfb9fe1b8df9528b8bdbf8d2570b860af3fd4a4b..c7c64a63c29f470ebbec5071422d148ba9bc074a 100644 (file)
@@ -17,5 +17,6 @@ generic-y       += scatterlist.h
 generic-y       += sections.h
 generic-y       += topology.h
 generic-y      += trace_clock.h
+generic-y += vga.h
 generic-y       += xor.h
 generic-y      += hash.h
index fc6483f83ccca748a3dc4319bb1ee849f8435654..4f5ec2bb71727279a952843051f44e3297c7b222 100644 (file)
@@ -295,6 +295,8 @@ extern void __iounmap(void __iomem *addr);
 #define iounmap(addr)                          \
        __iounmap(addr)
 
+#define ioremap_wc ioremap_nocache
+
 #define cached(addr) P1SEGADDR(addr)
 #define uncached(addr) P2SEGADDR(addr)
 
index 7cc8c364924dff8e8529be82406f0acfb7dfe0f2..6fb9e813a91074cb8ae41205bb8f899bcc35cf38 100644 (file)
@@ -1,4 +1,4 @@
-
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += clkdev.h
 generic-y += cputime.h
@@ -6,6 +6,7 @@ generic-y += device.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
@@ -18,6 +19,7 @@ generic-y += local.h
 generic-y += mman.h
 generic-y += mutex.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -31,5 +33,3 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h
deleted file mode 100644 (file)
index 15c5f77..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _M68K_BARRIER_H
-#define _M68K_BARRIER_H
-
-#define nop()          do { asm volatile ("nop"); barrier(); } while (0)
-
-#include <asm-generic/barrier.h>
-
-#endif /* _M68K_BARRIER_H */
index 014f288fc81354e0eb088e500184e7e032ea6ba3..9d38b73989eb597d677acd95ea53cf0ddb99b624 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            349
+#define NR_syscalls            351
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index 625f321001dc077fe13da02eb0844a50099653dc..b932dd470041c2c5130dfcc44448c80033525259 100644 (file)
 #define __NR_process_vm_writev 346
 #define __NR_kcmp              347
 #define __NR_finit_module      348
+#define __NR_sched_setattr     349
+#define __NR_sched_getattr     350
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 3f04ea0ab802750866835fcd9c3aa75ac7b28282..b6223dc41d82870953be64b35fc409c4b5634070 100644 (file)
@@ -369,4 +369,6 @@ ENTRY(sys_call_table)
        .long sys_process_vm_writev
        .long sys_kcmp
        .long sys_finit_module
+       .long sys_sched_setattr
+       .long sys_sched_getattr         /* 350 */
 
index 84fdf6857c31d1ccf878911b416f32e104eba8fb..a613d2c82fd9e7cbb024a28f493c0be54748d7e0 100644 (file)
@@ -200,10 +200,11 @@ static inline void __user *arch_compat_alloc_user_space(long len)
 
        /*
         * We can't access below the stack pointer in the 32bit ABI and
-        * can access 288 bytes in the 64bit ABI
+        * can access 288 bytes in the 64bit big-endian ABI,
+        * or 512 bytes with the new ELFv2 little-endian ABI.
         */
        if (!is_32bit_task())
-               usp -= 288;
+               usp -= USER_REDZONE_SIZE;
 
        return (void __user *) (usp - len);
 }
index 9e39ceb1d19fd706014794a6918f671ef12a5a58..d4dd41fb951b343918dda3db91399702d0e86423 100644 (file)
@@ -172,10 +172,20 @@ struct eeh_ops {
 };
 
 extern struct eeh_ops *eeh_ops;
-extern int eeh_subsystem_enabled;
+extern bool eeh_subsystem_enabled;
 extern raw_spinlock_t confirm_error_lock;
 extern int eeh_probe_mode;
 
+static inline bool eeh_enabled(void)
+{
+       return eeh_subsystem_enabled;
+}
+
+static inline void eeh_set_enable(bool mode)
+{
+       eeh_subsystem_enabled = mode;
+}
+
 #define EEH_PROBE_MODE_DEV     (1<<0)  /* From PCI device      */
 #define EEH_PROBE_MODE_DEVTREE (1<<1)  /* From device tree     */
 
@@ -246,7 +256,7 @@ void eeh_remove_device(struct pci_dev *);
  * If this macro yields TRUE, the caller relays to eeh_check_failure()
  * which does further tests out of line.
  */
-#define EEH_POSSIBLE_ERROR(val, type)  ((val) == (type)~0 && eeh_subsystem_enabled)
+#define EEH_POSSIBLE_ERROR(val, type)  ((val) == (type)~0 && eeh_enabled())
 
 /*
  * Reads from a device which has been isolated by EEH will return
@@ -257,6 +267,13 @@ void eeh_remove_device(struct pci_dev *);
 
 #else /* !CONFIG_EEH */
 
+static inline bool eeh_enabled(void)
+{
+        return false;
+}
+
+static inline void eeh_set_enable(bool mode) { }
+
 static inline int eeh_init(void)
 {
        return 0;
index d750336b171db4cf2c75f7e1fb95cbf6bcba8d74..623f2971ce0ed8d4d947642c862d4dce7640d28d 100644 (file)
@@ -127,7 +127,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
                                            unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_PPC64
-       return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+       return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1));
 #else
        return __pte(pte_update(ptep, ~0UL, 0));
 #endif
index 40157e2ca6914467cddae0225070d8582ad0861c..ed82142a325111ca18ecbc5ad05ec5760cb03a87 100644 (file)
@@ -816,8 +816,8 @@ int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe,
 int64_t opal_pci_poll(uint64_t phb_id);
 int64_t opal_return_cpu(void);
 
-int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, __be64 *val);
-int64_t opal_xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val);
+int64_t opal_xscom_read(uint32_t gcid, uint64_t pcb_addr, __be64 *val);
+int64_t opal_xscom_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val);
 
 int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
                       uint32_t addr, uint32_t data, uint32_t sz);
index bc141c950b1e6c8128769b786df189eb275f583f..eb9261024f5192386dec97bff1ee10e62da4b7c3 100644 (file)
@@ -195,6 +195,7 @@ extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 static inline unsigned long pte_update(struct mm_struct *mm,
                                       unsigned long addr,
                                       pte_t *ptep, unsigned long clr,
+                                      unsigned long set,
                                       int huge)
 {
 #ifdef PTE_ATOMIC_UPDATES
@@ -205,14 +206,15 @@ static inline unsigned long pte_update(struct mm_struct *mm,
        andi.   %1,%0,%6\n\
        bne-    1b \n\
        andc    %1,%0,%4 \n\
+       or      %1,%1,%7\n\
        stdcx.  %1,0,%3 \n\
        bne-    1b"
        : "=&r" (old), "=&r" (tmp), "=m" (*ptep)
-       : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
+       : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set)
        : "cc" );
 #else
        unsigned long old = pte_val(*ptep);
-       *ptep = __pte(old & ~clr);
+       *ptep = __pte((old & ~clr) | set);
 #endif
        /* huge pages use the old page table lock */
        if (!huge)
@@ -231,9 +233,9 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
 {
        unsigned long old;
 
-               if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
+       if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
                return 0;
-       old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0);
+       old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
        return (old & _PAGE_ACCESSED) != 0;
 }
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -252,7 +254,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
        if ((pte_val(*ptep) & _PAGE_RW) == 0)
                return;
 
-       pte_update(mm, addr, ptep, _PAGE_RW, 0);
+       pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
 }
 
 static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
@@ -261,7 +263,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
        if ((pte_val(*ptep) & _PAGE_RW) == 0)
                return;
 
-       pte_update(mm, addr, ptep, _PAGE_RW, 1);
+       pte_update(mm, addr, ptep, _PAGE_RW, 0, 1);
 }
 
 /*
@@ -284,14 +286,14 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
                                       unsigned long addr, pte_t *ptep)
 {
-       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0);
+       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
        return __pte(old);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
                             pte_t * ptep)
 {
-       pte_update(mm, addr, ptep, ~0UL, 0);
+       pte_update(mm, addr, ptep, ~0UL, 0, 0);
 }
 
 
@@ -506,7 +508,9 @@ extern int pmdp_set_access_flags(struct vm_area_struct *vma,
 
 extern unsigned long pmd_hugepage_update(struct mm_struct *mm,
                                         unsigned long addr,
-                                        pmd_t *pmdp, unsigned long clr);
+                                        pmd_t *pmdp,
+                                        unsigned long clr,
+                                        unsigned long set);
 
 static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
                                              unsigned long addr, pmd_t *pmdp)
@@ -515,7 +519,7 @@ static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
 
        if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
                return 0;
-       old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED);
+       old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
        return ((old & _PAGE_ACCESSED) != 0);
 }
 
@@ -542,7 +546,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
        if ((pmd_val(*pmdp) & _PAGE_RW) == 0)
                return;
 
-       pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW);
+       pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0);
 }
 
 #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
index f83b6f3e1b39b68c5b25f8df6a107f59bf20ae1b..3ebb188c3ff51a5ec0d55c31ce26601354a1bef7 100644 (file)
@@ -75,12 +75,34 @@ static inline pte_t pte_mknuma(pte_t pte)
        return pte;
 }
 
+#define ptep_set_numa ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pte_t *ptep)
+{
+       if ((pte_val(*ptep) & _PAGE_PRESENT) == 0)
+               VM_BUG_ON(1);
+
+       pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0);
+       return;
+}
+
 #define pmd_numa pmd_numa
 static inline int pmd_numa(pmd_t pmd)
 {
        return pte_numa(pmd_pte(pmd));
 }
 
+#define pmdp_set_numa pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pmd_t *pmdp)
+{
+       if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0)
+               VM_BUG_ON(1);
+
+       pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA);
+       return;
+}
+
 #define pmd_mknonnuma pmd_mknonnuma
 static inline pmd_t pmd_mknonnuma(pmd_t pmd)
 {
index becc08e6a65c585e0b6bc995f7699d74e2c36338..279b80f3bb293d0bceceecb9eb38ff344e26b8fb 100644 (file)
 
 #ifdef __powerpc64__
 
+/*
+ * Size of redzone that userspace is allowed to use below the stack
+ * pointer.  This is 288 in the 64-bit big-endian ELF ABI, and 512 in
+ * the new ELFv2 little-endian ABI, so we allow the larger amount.
+ *
+ * For kernel code we allow a 288-byte redzone, in order to conserve
+ * kernel stack space; gcc currently only uses 288 bytes, and will
+ * hopefully allow explicit control of the redzone size in future.
+ */
+#define USER_REDZONE_SIZE      512
+#define KERNEL_REDZONE_SIZE    288
+
 #define STACK_FRAME_OVERHEAD   112     /* size of minimum stack frame */
 #define STACK_FRAME_LR_SAVE    2       /* Location of LR in stack frame */
 #define STACK_FRAME_REGS_MARKER        ASM_CONST(0x7265677368657265)
 #define STACK_INT_FRAME_SIZE   (sizeof(struct pt_regs) + \
-                                       STACK_FRAME_OVERHEAD + 288)
+                                STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
 #define STACK_FRAME_MARKER     12
 
 /* Size of dummy stack frame allocated when calling signal handler. */
@@ -41,6 +53,8 @@
 
 #else /* __powerpc64__ */
 
+#define USER_REDZONE_SIZE      0
+#define KERNEL_REDZONE_SIZE    0
 #define STACK_FRAME_OVERHEAD   16      /* size of minimum stack frame */
 #define STACK_FRAME_LR_SAVE    1       /* Location of LR in stack frame */
 #define STACK_FRAME_REGS_MARKER        ASM_CONST(0x72656773)
index 0d9cecddf8a4f5ae133415f5e0bd49d780318e01..c53f5f6d1761f711b280c9e29509da15e6f1f4b8 100644 (file)
@@ -4,11 +4,11 @@
 #ifdef __KERNEL__
 
 /* Default link addresses for the vDSOs */
-#define VDSO32_LBASE   0x100000
-#define VDSO64_LBASE   0x100000
+#define VDSO32_LBASE   0x0
+#define VDSO64_LBASE   0x0
 
 /* Default map addresses for 32bit vDSO */
-#define VDSO32_MBASE   VDSO32_LBASE
+#define VDSO32_MBASE   0x100000
 
 #define VDSO_VERSION_STRING    LINUX_2.6.15
 
index 11c1d069d920a1fc97ec601ab0542c41708d7cc1..7a13f378ca2c7b1c715b9719e01329f99bf2ef2e 100644 (file)
@@ -98,17 +98,19 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
                        size_t csize, unsigned long offset, int userbuf)
 {
        void  *vaddr;
+       phys_addr_t paddr;
 
        if (!csize)
                return 0;
 
        csize = min_t(size_t, csize, PAGE_SIZE);
+       paddr = pfn << PAGE_SHIFT;
 
-       if ((min_low_pfn < pfn) && (pfn < max_pfn)) {
-               vaddr = __va(pfn << PAGE_SHIFT);
+       if (memblock_is_region_memory(paddr, csize)) {
+               vaddr = __va(paddr);
                csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
        } else {
-               vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
+               vaddr = __ioremap(paddr, PAGE_SIZE, 0);
                csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
                iounmap(vaddr);
        }
index 148db72a8c4371e69f79009683eb8b3baf12c3d6..e7b76a6bf15083704136459dc1dc69f2c6c9183e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/rbtree.h>
+#include <linux/reboot.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/export.h>
@@ -89,7 +90,7 @@
 /* Platform dependent EEH operations */
 struct eeh_ops *eeh_ops = NULL;
 
-int eeh_subsystem_enabled;
+bool eeh_subsystem_enabled = false;
 EXPORT_SYMBOL(eeh_subsystem_enabled);
 
 /*
@@ -364,7 +365,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
 
        eeh_stats.total_mmio_ffs++;
 
-       if (!eeh_subsystem_enabled)
+       if (!eeh_enabled())
                return 0;
 
        if (!edev) {
@@ -747,6 +748,17 @@ int __exit eeh_ops_unregister(const char *name)
        return -EEXIST;
 }
 
+static int eeh_reboot_notifier(struct notifier_block *nb,
+                              unsigned long action, void *unused)
+{
+       eeh_set_enable(false);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block eeh_reboot_nb = {
+       .notifier_call = eeh_reboot_notifier,
+};
+
 /**
  * eeh_init - EEH initialization
  *
@@ -778,6 +790,14 @@ int eeh_init(void)
        if (machine_is(powernv) && cnt++ <= 0)
                return ret;
 
+       /* Register reboot notifier */
+       ret = register_reboot_notifier(&eeh_reboot_nb);
+       if (ret) {
+               pr_warn("%s: Failed to register notifier (%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
        /* call platform initialization function */
        if (!eeh_ops) {
                pr_warning("%s: Platform EEH operation not found\n",
@@ -822,7 +842,7 @@ int eeh_init(void)
                        return ret;
        }
 
-       if (eeh_subsystem_enabled)
+       if (eeh_enabled())
                pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
        else
                pr_warning("EEH: No capable adapters found\n");
@@ -897,7 +917,7 @@ void eeh_add_device_late(struct pci_dev *dev)
        struct device_node *dn;
        struct eeh_dev *edev;
 
-       if (!dev || !eeh_subsystem_enabled)
+       if (!dev || !eeh_enabled())
                return;
 
        pr_debug("EEH: Adding device %s\n", pci_name(dev));
@@ -1005,7 +1025,7 @@ void eeh_remove_device(struct pci_dev *dev)
 {
        struct eeh_dev *edev;
 
-       if (!dev || !eeh_subsystem_enabled)
+       if (!dev || !eeh_enabled())
                return;
        edev = pci_dev_to_eeh_dev(dev);
 
@@ -1045,7 +1065,7 @@ void eeh_remove_device(struct pci_dev *dev)
 
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
-       if (0 == eeh_subsystem_enabled) {
+       if (!eeh_enabled()) {
                seq_printf(m, "EEH Subsystem is globally disabled\n");
                seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs);
        } else {
index 9b27b293a9226903c81529a4f01aee64a7f07d23..b0ded97ee4e11148cd436809aaab2c36c106893a 100644 (file)
@@ -74,6 +74,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
  */
 static int test_24bit_addr(unsigned long ip, unsigned long addr)
 {
+       addr = ppc_function_entry((void *)addr);
 
        /* use the create_branch to verify that this offset can be branched */
        return create_branch((unsigned int *)ip, addr, 0);
index 879f09620f8341e27dbfd1ed6be47fe242eab812..7c6bb4b17b4960d111f29bc7f37632f9026d944c 100644 (file)
@@ -57,11 +57,14 @@ _GLOBAL(call_do_softirq)
        mtlr    r0
        blr
 
+/*
+ * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
+ */
 _GLOBAL(call_do_irq)
        mflr    r0
        stw     r0,4(r1)
        lwz     r10,THREAD+KSP_LIMIT(r2)
-       addi    r11,r3,THREAD_INFO_GAP
+       addi    r11,r4,THREAD_INFO_GAP
        stwu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
        mr      r1,r4
        stw     r10,8(r1)
index e35bf773df7a8d972990374cbb1507db261ccea2..8d253c29649b514e6f12694a5794329e008f1ea2 100644 (file)
@@ -65,8 +65,8 @@ struct rt_sigframe {
        struct siginfo __user *pinfo;
        void __user *puc;
        struct siginfo info;
-       /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
-       char abigap[288];
+       /* New 64 bit little-endian ABI allows redzone of 512 bytes below sp */
+       char abigap[USER_REDZONE_SIZE];
 } __attribute__ ((aligned (16)));
 
 static const char fmt32[] = KERN_INFO \
index 79683d0393f5d01577503b02d7d298018647a758..6ac107ac402a93ffcabb5f0cd365132f922fe88d 100644 (file)
@@ -6,7 +6,7 @@
        .globl vdso32_start, vdso32_end
        .balign PAGE_SIZE
 vdso32_start:
-       .incbin "arch/powerpc/kernel/vdso32/vdso32.so"
+       .incbin "arch/powerpc/kernel/vdso32/vdso32.so.dbg"
        .balign PAGE_SIZE
 vdso32_end:
 
index 8df9e2463007c1601012aae7062c6a8896ebf9ef..df60fca6a13d1eb745612e78c0be86a32fb78c45 100644 (file)
@@ -6,7 +6,7 @@
        .globl vdso64_start, vdso64_end
        .balign PAGE_SIZE
 vdso64_start:
-       .incbin "arch/powerpc/kernel/vdso64/vdso64.so"
+       .incbin "arch/powerpc/kernel/vdso64/vdso64.so.dbg"
        .balign PAGE_SIZE
 vdso64_end:
 
index 65b7b65e8708bd1867861f4b519d207b25beb5a7..62bf5e8e78daaaf5051fb6e5727bfd99be81a088 100644 (file)
@@ -510,7 +510,8 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
 }
 
 unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
-                                 pmd_t *pmdp, unsigned long clr)
+                                 pmd_t *pmdp, unsigned long clr,
+                                 unsigned long set)
 {
 
        unsigned long old, tmp;
@@ -526,14 +527,15 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
                andi.   %1,%0,%6\n\
                bne-    1b \n\
                andc    %1,%0,%4 \n\
+               or      %1,%1,%7\n\
                stdcx.  %1,0,%3 \n\
                bne-    1b"
        : "=&r" (old), "=&r" (tmp), "=m" (*pmdp)
-       : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY)
+       : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set)
        : "cc" );
 #else
        old = pmd_val(*pmdp);
-       *pmdp = __pmd(old & ~clr);
+       *pmdp = __pmd((old & ~clr) | set);
 #endif
        if (old & _PAGE_HASHPTE)
                hpte_do_hugepage_flush(mm, addr, pmdp);
@@ -708,7 +710,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
-       pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT);
+       pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
 }
 
 /*
@@ -835,7 +837,7 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm,
        unsigned long old;
        pgtable_t *pgtable_slot;
 
-       old = pmd_hugepage_update(mm, addr, pmdp, ~0UL);
+       old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
        old_pmd = __pmd(old);
        /*
         * We have pmd == none and we are holding page_table_lock.
index a770df2dae7050bafd28daf1c354165113e378f9..6c0b1f5f8d2ccef746ccddfed70684c45f3adec2 100644 (file)
@@ -78,7 +78,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr,
        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
        arch_enter_lazy_mmu_mode();
        for (; npages > 0; --npages) {
-               pte_update(mm, addr, pte, 0, 0);
+               pte_update(mm, addr, pte, 0, 0, 0);
                addr += PAGE_SIZE;
                ++pte;
        }
index e1e71618b70cfe5d4caa7d15e30bc42a37361c56..253fefe3d1a0e76fd4ed3996711b6f1784725d6c 100644 (file)
@@ -44,7 +44,8 @@ static int ioda_eeh_event(struct notifier_block *nb,
 
        /* We simply send special EEH event */
        if ((changed_evts & OPAL_EVENT_PCI_ERROR) &&
-           (events & OPAL_EVENT_PCI_ERROR))
+           (events & OPAL_EVENT_PCI_ERROR) &&
+           eeh_enabled())
                eeh_send_failure_event(NULL);
 
        return 0;
@@ -113,6 +114,7 @@ DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get,
                        ioda_eeh_inbB_dbgfs_set, "0x%llx\n");
 #endif /* CONFIG_DEBUG_FS */
 
+
 /**
  * ioda_eeh_post_init - Chip dependent post initialization
  * @hose: PCI controller
@@ -220,6 +222,22 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
        return ret;
 }
 
+static void ioda_eeh_phb_diag(struct pci_controller *hose)
+{
+       struct pnv_phb *phb = hose->private_data;
+       long rc;
+
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
+       if (rc != OPAL_SUCCESS) {
+               pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
+                           __func__, hose->global_number, rc);
+               return;
+       }
+
+       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+}
+
 /**
  * ioda_eeh_get_state - Retrieve the state of PE
  * @pe: EEH PE
@@ -271,6 +289,9 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
                        result |= EEH_STATE_DMA_ACTIVE;
                        result |= EEH_STATE_MMIO_ENABLED;
                        result |= EEH_STATE_DMA_ENABLED;
+               } else if (!(pe->state & EEH_PE_ISOLATED)) {
+                       eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+                       ioda_eeh_phb_diag(hose);
                }
 
                return result;
@@ -314,6 +335,15 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
                           __func__, fstate, hose->global_number, pe_no);
        }
 
+       /* Dump PHB diag-data for frozen PE */
+       if (result != EEH_STATE_NOT_SUPPORT &&
+           (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) !=
+           (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
+           !(pe->state & EEH_PE_ISOLATED)) {
+               eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+               ioda_eeh_phb_diag(hose);
+       }
+
        return result;
 }
 
@@ -489,8 +519,7 @@ static int ioda_eeh_bridge_reset(struct pci_controller *hose,
 static int ioda_eeh_reset(struct eeh_pe *pe, int option)
 {
        struct pci_controller *hose = pe->phb;
-       struct eeh_dev *edev;
-       struct pci_dev *dev;
+       struct pci_bus *bus;
        int ret;
 
        /*
@@ -519,72 +548,16 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
        if (pe->type & EEH_PE_PHB) {
                ret = ioda_eeh_phb_reset(hose, option);
        } else {
-               if (pe->type & EEH_PE_DEVICE) {
-                       /*
-                        * If it's device PE, we didn't refer to the parent
-                        * PCI bus yet. So we have to figure it out indirectly.
-                        */
-                       edev = list_first_entry(&pe->edevs,
-                                       struct eeh_dev, list);
-                       dev = eeh_dev_to_pci_dev(edev);
-                       dev = dev->bus->self;
-               } else {
-                       /*
-                        * If it's bus PE, the parent PCI bus is already there
-                        * and just pick it up.
-                        */
-                       dev = pe->bus->self;
-               }
-
-               /*
-                * Do reset based on the fact that the direct upstream bridge
-                * is root bridge (port) or not.
-                */
-               if (dev->bus->number == 0)
+               bus = eeh_pe_bus_get(pe);
+               if (pci_is_root_bus(bus))
                        ret = ioda_eeh_root_reset(hose, option);
                else
-                       ret = ioda_eeh_bridge_reset(hose, dev, option);
+                       ret = ioda_eeh_bridge_reset(hose, bus->self, option);
        }
 
        return ret;
 }
 
-/**
- * ioda_eeh_get_log - Retrieve error log
- * @pe: EEH PE
- * @severity: Severity level of the log
- * @drv_log: buffer to store the log
- * @len: space of the log buffer
- *
- * The function is used to retrieve error log from P7IOC.
- */
-static int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
-                           char *drv_log, unsigned long len)
-{
-       s64 ret;
-       unsigned long flags;
-       struct pci_controller *hose = pe->phb;
-       struct pnv_phb *phb = hose->private_data;
-
-       spin_lock_irqsave(&phb->lock, flags);
-
-       ret = opal_pci_get_phb_diag_data2(phb->opal_id,
-                       phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
-       if (ret) {
-               spin_unlock_irqrestore(&phb->lock, flags);
-               pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n",
-                          __func__, hose->global_number, pe->addr, ret);
-               return -EIO;
-       }
-
-       /* The PHB diag-data is always indicative */
-       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
-
-       spin_unlock_irqrestore(&phb->lock, flags);
-
-       return 0;
-}
-
 /**
  * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
  * @pe: EEH PE
@@ -666,22 +639,6 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
        }
 }
 
-static void ioda_eeh_phb_diag(struct pci_controller *hose)
-{
-       struct pnv_phb *phb = hose->private_data;
-       long rc;
-
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
-                                        PNV_PCI_DIAG_BUF_SIZE);
-       if (rc != OPAL_SUCCESS) {
-               pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
-                           __func__, hose->global_number, rc);
-               return;
-       }
-
-       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
-}
-
 static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
                               struct eeh_pe **pe)
 {
@@ -854,6 +811,20 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
                                __func__, err_type);
                }
 
+               /*
+                * EEH core will try recover from fenced PHB or
+                * frozen PE. In the time for frozen PE, EEH core
+                * enable IO path for that before collecting logs,
+                * but it ruins the site. So we have to dump the
+                * log in advance here.
+                */
+               if ((ret == EEH_NEXT_ERR_FROZEN_PE  ||
+                   ret == EEH_NEXT_ERR_FENCED_PHB) &&
+                   !((*pe)->state & EEH_PE_ISOLATED)) {
+                       eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
+                       ioda_eeh_phb_diag(hose);
+               }
+
                /*
                 * If we have no errors on the specific PHB or only
                 * informative error there, we continue poking it.
@@ -872,7 +843,6 @@ struct pnv_eeh_ops ioda_eeh_ops = {
        .set_option             = ioda_eeh_set_option,
        .get_state              = ioda_eeh_get_state,
        .reset                  = ioda_eeh_reset,
-       .get_log                = ioda_eeh_get_log,
        .configure_bridge       = ioda_eeh_configure_bridge,
        .next_error             = ioda_eeh_next_error
 };
index a79fddc5e74e58ac0a0b18fc1b7cb5db607095b2..a59788e83b8b377152ed5d70db86fbb7bc9fb805 100644 (file)
@@ -145,7 +145,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
         * Enable EEH explicitly so that we will do EEH check
         * while accessing I/O stuff
         */
-       eeh_subsystem_enabled = 1;
+       eeh_set_enable(true);
 
        /* Save memory bars */
        eeh_save_bars(edev);
index 4fbf276ac99eeb4e2900196e3905a3343bedc988..4cd2ea6c0dbe13ecf2fb7926838cfeac9277730c 100644 (file)
@@ -71,11 +71,11 @@ static int opal_xscom_err_xlate(int64_t rc)
        }
 }
 
-static u64 opal_scom_unmangle(u64 reg)
+static u64 opal_scom_unmangle(u64 addr)
 {
        /*
         * XSCOM indirect addresses have the top bit set. Additionally
-        * the reset of the top 3 nibbles is always 0.
+        * the rest of the top 3 nibbles is always 0.
         *
         * Because the debugfs interface uses signed offsets and shifts
         * the address left by 3, we basically cannot use the top 4 bits
@@ -86,10 +86,13 @@ static u64 opal_scom_unmangle(u64 reg)
         * conversion here. To leave room for further xscom address
         * expansion, we only clear out the top byte
         *
+        * For in-kernel use, we also support the real indirect bit, so
+        * we test for any of the top 5 bits
+        *
         */
-       if (reg & (1ull << 59))
-               reg = (reg & ~(0xffull << 56)) | (1ull << 63);
-       return reg;
+       if (addr & (0x1full << 59))
+               addr = (addr & ~(0xffull << 56)) | (1ull << 63);
+       return addr;
 }
 
 static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
@@ -98,8 +101,8 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
        int64_t rc;
        __be64 v;
 
-       reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v));
+       reg = opal_scom_unmangle(m->addr + reg);
+       rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v));
        *value = be64_to_cpu(v);
        return opal_xscom_err_xlate(rc);
 }
@@ -109,8 +112,8 @@ static int opal_scom_write(scom_map_t map, u64 reg, u64 value)
        struct opal_scom_map *m = map;
        int64_t rc;
 
-       reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_write(m->chip, m->addr + reg, value);
+       reg = opal_scom_unmangle(m->addr + reg);
+       rc = opal_xscom_write(m->chip, reg, value);
        return opal_xscom_err_xlate(rc);
 }
 
index 95633d79ef5d6d3dd373ceed1552b05c8eed0a5c..8518817dcdfdc95d04e3b1fc10bfe54432330079 100644 (file)
@@ -134,57 +134,72 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose,
        pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
                hose->global_number, common->version);
 
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-       pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
-       pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+       if (data->brdgCtl)
+               pr_info("  brdgCtl:     %08x\n",
+                       data->brdgCtl);
+       if (data->portStatusReg || data->rootCmplxStatus ||
+           data->busAgentStatus)
+               pr_info("  UtlSts:      %08x %08x %08x\n",
+                       data->portStatusReg, data->rootCmplxStatus,
+                       data->busAgentStatus);
+       if (data->deviceStatus || data->slotStatus   ||
+           data->linkStatus   || data->devCmdStatus ||
+           data->devSecStatus)
+               pr_info("  RootSts:     %08x %08x %08x %08x %08x\n",
+                       data->deviceStatus, data->slotStatus,
+                       data->linkStatus, data->devCmdStatus,
+                       data->devSecStatus);
+       if (data->rootErrorStatus   || data->uncorrErrorStatus ||
+           data->corrErrorStatus)
+               pr_info("  RootErrSts:  %08x %08x %08x\n",
+                       data->rootErrorStatus, data->uncorrErrorStatus,
+                       data->corrErrorStatus);
+       if (data->tlpHdr1 || data->tlpHdr2 ||
+           data->tlpHdr3 || data->tlpHdr4)
+               pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+                       data->tlpHdr1, data->tlpHdr2,
+                       data->tlpHdr3, data->tlpHdr4);
+       if (data->sourceId || data->errorClass ||
+           data->correlator)
+               pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+                       data->sourceId, data->errorClass,
+                       data->correlator);
+       if (data->p7iocPlssr || data->p7iocCsr)
+               pr_info("  PhbSts:      %016llx %016llx\n",
+                       data->p7iocPlssr, data->p7iocCsr);
+       if (data->lemFir || data->lemErrorMask ||
+           data->lemWOF)
+               pr_info("  Lem:         %016llx %016llx %016llx\n",
+                       data->lemFir, data->lemErrorMask,
+                       data->lemWOF);
+       if (data->phbErrorStatus || data->phbFirstErrorStatus ||
+           data->phbErrorLog0   || data->phbErrorLog1)
+               pr_info("  PhbErr:      %016llx %016llx %016llx %016llx\n",
+                       data->phbErrorStatus, data->phbFirstErrorStatus,
+                       data->phbErrorLog0, data->phbErrorLog1);
+       if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
+           data->mmioErrorLog0   || data->mmioErrorLog1)
+               pr_info("  OutErr:      %016llx %016llx %016llx %016llx\n",
+                       data->mmioErrorStatus, data->mmioFirstErrorStatus,
+                       data->mmioErrorLog0, data->mmioErrorLog1);
+       if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
+           data->dma0ErrorLog0   || data->dma0ErrorLog1)
+               pr_info("  InAErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma0ErrorStatus, data->dma0FirstErrorStatus,
+                       data->dma0ErrorLog0, data->dma0ErrorLog1);
+       if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
+           data->dma1ErrorLog0   || data->dma1ErrorLog1)
+               pr_info("  InBErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma1ErrorStatus, data->dma1FirstErrorStatus,
+                       data->dma1ErrorLog0, data->dma1ErrorLog1);
 
        for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
                if ((data->pestA[i] >> 63) == 0 &&
                    (data->pestB[i] >> 63) == 0)
                        continue;
 
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+               pr_info("  PE[%3d] A/B: %016llx %016llx\n",
+                       i, data->pestA[i], data->pestB[i]);
        }
 }
 
@@ -197,62 +212,77 @@ static void pnv_pci_dump_phb3_diag_data(struct pci_controller *hose,
        data = (struct OpalIoPhb3ErrorData*)common;
        pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n",
                hose->global_number, common->version);
-
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-
-       pr_info("  nFir:                 %016llx\n", data->nFir);
-       pr_info("  nFirMask:             %016llx\n", data->nFirMask);
-       pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
-       pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
-       pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+       if (data->brdgCtl)
+               pr_info("  brdgCtl:     %08x\n",
+                       data->brdgCtl);
+       if (data->portStatusReg || data->rootCmplxStatus ||
+           data->busAgentStatus)
+               pr_info("  UtlSts:      %08x %08x %08x\n",
+                       data->portStatusReg, data->rootCmplxStatus,
+                       data->busAgentStatus);
+       if (data->deviceStatus || data->slotStatus   ||
+           data->linkStatus   || data->devCmdStatus ||
+           data->devSecStatus)
+               pr_info("  RootSts:     %08x %08x %08x %08x %08x\n",
+                       data->deviceStatus, data->slotStatus,
+                       data->linkStatus, data->devCmdStatus,
+                       data->devSecStatus);
+       if (data->rootErrorStatus || data->uncorrErrorStatus ||
+           data->corrErrorStatus)
+               pr_info("  RootErrSts:  %08x %08x %08x\n",
+                       data->rootErrorStatus, data->uncorrErrorStatus,
+                       data->corrErrorStatus);
+       if (data->tlpHdr1 || data->tlpHdr2 ||
+           data->tlpHdr3 || data->tlpHdr4)
+               pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+                       data->tlpHdr1, data->tlpHdr2,
+                       data->tlpHdr3, data->tlpHdr4);
+       if (data->sourceId || data->errorClass ||
+           data->correlator)
+               pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+                       data->sourceId, data->errorClass,
+                       data->correlator);
+       if (data->nFir || data->nFirMask ||
+           data->nFirWOF)
+               pr_info("  nFir:        %016llx %016llx %016llx\n",
+                       data->nFir, data->nFirMask,
+                       data->nFirWOF);
+       if (data->phbPlssr || data->phbCsr)
+               pr_info("  PhbSts:      %016llx %016llx\n",
+                       data->phbPlssr, data->phbCsr);
+       if (data->lemFir || data->lemErrorMask ||
+           data->lemWOF)
+               pr_info("  Lem:         %016llx %016llx %016llx\n",
+                       data->lemFir, data->lemErrorMask,
+                       data->lemWOF);
+       if (data->phbErrorStatus || data->phbFirstErrorStatus ||
+           data->phbErrorLog0   || data->phbErrorLog1)
+               pr_info("  PhbErr:      %016llx %016llx %016llx %016llx\n",
+                       data->phbErrorStatus, data->phbFirstErrorStatus,
+                       data->phbErrorLog0, data->phbErrorLog1);
+       if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
+           data->mmioErrorLog0   || data->mmioErrorLog1)
+               pr_info("  OutErr:      %016llx %016llx %016llx %016llx\n",
+                       data->mmioErrorStatus, data->mmioFirstErrorStatus,
+                       data->mmioErrorLog0, data->mmioErrorLog1);
+       if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
+           data->dma0ErrorLog0   || data->dma0ErrorLog1)
+               pr_info("  InAErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma0ErrorStatus, data->dma0FirstErrorStatus,
+                       data->dma0ErrorLog0, data->dma0ErrorLog1);
+       if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
+           data->dma1ErrorLog0   || data->dma1ErrorLog1)
+               pr_info("  InBErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma1ErrorStatus, data->dma1FirstErrorStatus,
+                       data->dma1ErrorLog0, data->dma1ErrorLog1);
 
        for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
                if ((data->pestA[i] >> 63) == 0 &&
                    (data->pestB[i] >> 63) == 0)
                        continue;
 
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+               pr_info("  PE[%3d] A/B: %016llx %016llx\n",
+                       i, data->pestA[i], data->pestB[i]);
        }
 }
 
index 9ef3cc8ebc11c7f533a3bc966d90bd6c085d891d..8a8f0472d98fd0e56d9c199c85c4d513e04f8d9a 100644 (file)
@@ -265,7 +265,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
                        enable = 1;
 
                if (enable) {
-                       eeh_subsystem_enabled = 1;
+                       eeh_set_enable(true);
                        eeh_add_to_parent_pe(edev);
 
                        pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
index 82789e79e53985cf2b6c856f313628ff1eb0ca3e..0ea99e3d4815733a74b8098864f3594839ed97eb 100644 (file)
 #include "offline_states.h"
 
 /* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
-       .token = RTAS_UNKNOWN_SERVICE,
-       .nargs = 0,
-       .nret = 1,
-       .rets = &rtas_stop_self_args.args[0],
-};
+static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
 
 static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) =
                                                        CPU_STATE_OFFLINE;
@@ -93,15 +88,20 @@ void set_default_offline_state(int cpu)
 
 static void rtas_stop_self(void)
 {
-       struct rtas_args *args = &rtas_stop_self_args;
+       struct rtas_args args = {
+               .token = cpu_to_be32(rtas_stop_self_token),
+               .nargs = 0,
+               .nret = 1,
+               .rets = &args.args[0],
+       };
 
        local_irq_disable();
 
-       BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+       BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
 
        printk("cpu %u (hwid %u) Ready to die...\n",
               smp_processor_id(), hard_smp_processor_id());
-       enter_rtas(__pa(args));
+       enter_rtas(__pa(&args));
 
        panic("Alas, I survived.\n");
 }
@@ -392,10 +392,10 @@ static int __init pseries_cpu_hotplug_init(void)
                }
        }
 
-       rtas_stop_self_args.token = rtas_token("stop-self");
+       rtas_stop_self_token = rtas_token("stop-self");
        qcss_tok = rtas_token("query-cpu-stopped-state");
 
-       if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+       if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE ||
                        qcss_tok == RTAS_UNKNOWN_SERVICE) {
                printk(KERN_INFO "CPU Hotplug not supported by firmware "
                                "- disabling.\n");
index 70670a2d9cf2ddd691a936dbe489d8e338ed4029..c413ec158ff5a6587e7c611659f817dc33d9c7e4 100644 (file)
@@ -113,7 +113,8 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
        struct device_node *dn, *pdn;
        struct pci_bus *bus;
-       const __be32 *pcie_link_speed_stats;
+       u32 pcie_link_speed_stats[2];
+       int rc;
 
        bus = bridge->bus;
 
@@ -122,38 +123,45 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
 
        for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
-               pcie_link_speed_stats = of_get_property(pdn,
-                       "ibm,pcie-link-speed-stats", NULL);
-               if (pcie_link_speed_stats)
+               rc = of_property_read_u32_array(pdn,
+                               "ibm,pcie-link-speed-stats",
+                               &pcie_link_speed_stats[0], 2);
+               if (!rc)
                        break;
        }
 
        of_node_put(pdn);
 
-       if (!pcie_link_speed_stats) {
+       if (rc) {
                pr_err("no ibm,pcie-link-speed-stats property\n");
                return 0;
        }
 
-       switch (be32_to_cpup(pcie_link_speed_stats)) {
+       switch (pcie_link_speed_stats[0]) {
        case 0x01:
                bus->max_bus_speed = PCIE_SPEED_2_5GT;
                break;
        case 0x02:
                bus->max_bus_speed = PCIE_SPEED_5_0GT;
                break;
+       case 0x04:
+               bus->max_bus_speed = PCIE_SPEED_8_0GT;
+               break;
        default:
                bus->max_bus_speed = PCI_SPEED_UNKNOWN;
                break;
        }
 
-       switch (be32_to_cpup(pcie_link_speed_stats)) {
+       switch (pcie_link_speed_stats[1]) {
        case 0x01:
                bus->cur_bus_speed = PCIE_SPEED_2_5GT;
                break;
        case 0x02:
                bus->cur_bus_speed = PCIE_SPEED_5_0GT;
                break;
+       case 0x04:
+               bus->cur_bus_speed = PCIE_SPEED_8_0GT;
+               break;
        default:
                bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
                break;
index 59c8efce1b99b52964950f0933b4934a12b6a9db..0248949a756d7765d11a1d39f1568d37e3934406 100644 (file)
@@ -1421,5 +1421,5 @@ ENTRY(sys_sched_setattr_wrapper)
 ENTRY(sys_sched_getattr_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # const char __user *
-       llgfr   %r3,%r3                 # unsigned int
+       llgfr   %r4,%r4                 # unsigned int
        jg      sys_sched_getattr
index 60c11a629d96d0220d6b01cf1e1425d41c0ffaab..f91c03119804751894c39433eb52da1844dbcf3b 100644 (file)
@@ -206,11 +206,13 @@ static void dma_cleanup_tables(struct zpci_dev *zdev)
        zdev->dma_table = NULL;
 }
 
-static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, unsigned long start,
-                                  int size)
+static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev,
+                                      unsigned long start, int size)
 {
-       unsigned long boundary_size = 0x1000000;
+       unsigned long boundary_size;
 
+       boundary_size = ALIGN(dma_get_seg_boundary(&zdev->pdev->dev) + 1,
+                             PAGE_SIZE) >> PAGE_SHIFT;
        return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
                                start, size, 0, boundary_size, 0);
 }
index c51efdcd07a2d09e76c06e31671efcd19a6db4ed..7d8b7e94b93b6fb8e9795f49368c056053597bec 100644 (file)
@@ -27,7 +27,7 @@ config SPARC
        select RTC_DRV_M48T59
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
-       select HAVE_ARCH_JUMP_LABEL
+       select HAVE_ARCH_JUMP_LABEL if SPARC64
        select GENERIC_IRQ_SHOW
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_PCI_IOMAP
index 869023abe5a4440c3ec08777e987c7abcc9777b8..cfbe53c17b0dbb61b25f8ae48c0f3017f307cc6f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/log2.h>
@@ -62,6 +63,7 @@ extern unsigned long last_valid_pfn;
 static pgd_t *srmmu_swapper_pg_dir;
 
 const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+EXPORT_SYMBOL(sparc32_cachetlb_ops);
 
 #ifdef CONFIG_SMP
 const struct sparc32_cachetlb_ops *local_ops;
index 90a21f430117d1690f847c8b198e80d6afb3c825..4dbf967da50daab8c7ed9f3952fa08b18b5b6271 100644 (file)
@@ -111,7 +111,7 @@ struct mem_vector {
 };
 
 #define MEM_AVOID_MAX 5
-struct mem_vector mem_avoid[MEM_AVOID_MAX];
+static struct mem_vector mem_avoid[MEM_AVOID_MAX];
 
 static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
 {
@@ -180,7 +180,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
 }
 
 /* Does this memory vector overlap a known avoided area? */
-bool mem_avoid_overlap(struct mem_vector *img)
+static bool mem_avoid_overlap(struct mem_vector *img)
 {
        int i;
 
@@ -192,8 +192,9 @@ bool mem_avoid_overlap(struct mem_vector *img)
        return false;
 }
 
-unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN];
-unsigned long slot_max = 0;
+static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
+                          CONFIG_PHYSICAL_ALIGN];
+static unsigned long slot_max;
 
 static void slots_append(unsigned long addr)
 {
index 57ae63cd6ee2ec8aba5135a33e363267b65e4075..94605c0e9ceebc0058b18b995a5ac4f73a0d2aa6 100644 (file)
@@ -66,6 +66,6 @@ extern void tsc_save_sched_clock_state(void);
 extern void tsc_restore_sched_clock_state(void);
 
 /* MSR based TSC calibration for Intel Atom SoC platforms */
-int try_msr_calibrate_tsc(unsigned long *fast_calibrate);
+unsigned long try_msr_calibrate_tsc(void);
 
 #endif /* _ASM_X86_TSC_H */
index b88645191fe559b89b8d330c984865d07dbae21b..79f9f848bee4b1c021b80bed07e0dcbcec88a20b 100644 (file)
@@ -1192,6 +1192,9 @@ static void x86_pmu_del(struct perf_event *event, int flags)
        for (i = 0; i < cpuc->n_events; i++) {
                if (event == cpuc->event_list[i]) {
 
+                       if (i >= cpuc->n_events - cpuc->n_added)
+                               --cpuc->n_added;
+
                        if (x86_pmu.put_event_constraints)
                                x86_pmu.put_event_constraints(cpuc, event);
 
@@ -1521,6 +1524,8 @@ static int __init init_hw_perf_events(void)
 
        pr_cont("%s PMU driver.\n", x86_pmu.name);
 
+       x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
+
        for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
                quirk->func();
 
@@ -1534,7 +1539,6 @@ static int __init init_hw_perf_events(void)
                __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
                                   0, x86_pmu.num_counters, 0, 0);
 
-       x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
        x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
        if (x86_pmu.event_attrs)
@@ -1820,9 +1824,12 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
        if (ret)
                return ret;
 
+       if (x86_pmu.attr_rdpmc_broken)
+               return -ENOTSUPP;
+
        if (!!val != !!x86_pmu.attr_rdpmc) {
                x86_pmu.attr_rdpmc = !!val;
-               smp_call_function(change_rdpmc, (void *)val, 1);
+               on_each_cpu(change_rdpmc, (void *)val, 1);
        }
 
        return count;
index c1a861829d817a2749372060df21c6d689294fff..4972c244d0bc2fbe445706943e0248073fd17a26 100644 (file)
@@ -409,6 +409,7 @@ struct x86_pmu {
        /*
         * sysfs attrs
         */
+       int             attr_rdpmc_broken;
        int             attr_rdpmc;
        struct attribute **format_attrs;
        struct attribute **event_attrs;
index 0fa4f242f0504ad53297360966e957b84a0edab8..aa333d9668866f808955209f8cd71737d447eafc 100644 (file)
@@ -1361,10 +1361,8 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
        intel_pmu_disable_all();
        handled = intel_pmu_drain_bts_buffer();
        status = intel_pmu_get_status();
-       if (!status) {
-               intel_pmu_enable_all(0);
-               return handled;
-       }
+       if (!status)
+               goto done;
 
        loops = 0;
 again:
@@ -2310,10 +2308,7 @@ __init int intel_pmu_init(void)
        if (version > 1)
                x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
 
-       /*
-        * v2 and above have a perf capabilities MSR
-        */
-       if (version > 1) {
+       if (boot_cpu_has(X86_FEATURE_PDCM)) {
                u64 capabilities;
 
                rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities);
index 29c248799cede4432ac2d57ca8689a215c35d0cc..c88f7f4b03ee063ba090ec1e53c864fa4279fdec 100644 (file)
@@ -501,8 +501,11 @@ static struct extra_reg snbep_uncore_cbox_extra_regs[] = {
        SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
                                  SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
@@ -1178,10 +1181,15 @@ static struct extra_reg ivt_uncore_cbox_extra_regs[] = {
        SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
                                  SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
        SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
        SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
index b1e2fe11532329bb9828ac4407f6b10093073187..7c1a0c07b607f1d882781978e1d08a8a94a546d2 100644 (file)
@@ -231,31 +231,49 @@ static __initconst const struct x86_pmu p6_pmu = {
 
 };
 
+static __init void p6_pmu_rdpmc_quirk(void)
+{
+       if (boot_cpu_data.x86_mask < 9) {
+               /*
+                * PPro erratum 26; fixed in stepping 9 and above.
+                */
+               pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
+               x86_pmu.attr_rdpmc_broken = 1;
+               x86_pmu.attr_rdpmc = 0;
+       }
+}
+
 __init int p6_pmu_init(void)
 {
+       x86_pmu = p6_pmu;
+
        switch (boot_cpu_data.x86_model) {
-       case 1:
-       case 3:  /* Pentium Pro */
-       case 5:
-       case 6:  /* Pentium II */
-       case 7:
-       case 8:
-       case 11: /* Pentium III */
-       case 9:
-       case 13:
-               /* Pentium M */
+       case  1: /* Pentium Pro */
+               x86_add_quirk(p6_pmu_rdpmc_quirk);
+               break;
+
+       case  3: /* Pentium II - Klamath */
+       case  5: /* Pentium II - Deschutes */
+       case  6: /* Pentium II - Mendocino */
                break;
+
+       case  7: /* Pentium III - Katmai */
+       case  8: /* Pentium III - Coppermine */
+       case 10: /* Pentium III Xeon */
+       case 11: /* Pentium III - Tualatin */
+               break;
+
+       case  9: /* Pentium M - Banias */
+       case 13: /* Pentium M - Dothan */
+               break;
+
        default:
-               pr_cont("unsupported p6 CPU model %d ",
-                       boot_cpu_data.x86_model);
+               pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
                return -ENODEV;
        }
 
-       x86_pmu = p6_pmu;
-
        memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
                sizeof(hw_cache_event_ids));
 
-
        return 0;
 }
index 4eabc160696f510ec5ffaddc7939dd71856463d5..679cef0791cd842448216f4a6158cd2ae24fe0e0 100644 (file)
@@ -279,5 +279,7 @@ void arch_crash_save_vmcoreinfo(void)
        VMCOREINFO_SYMBOL(node_data);
        VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
 #endif
+       vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
+                             (unsigned long)&_text - __START_KERNEL);
 }
 
index 872079a67e4d262151dfdbe74f537033be5ebcc0..f7d0672481fd7c328682d601467313acb586280a 100644 (file)
@@ -100,8 +100,10 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
        flag |= __GFP_ZERO;
 again:
        page = NULL;
-       if (!(flag & GFP_ATOMIC))
+       /* CMA can be used only in the context which permits sleeping */
+       if (flag & __GFP_WAIT)
                page = dma_alloc_from_contiguous(dev, count, get_order(size));
+       /* fallback */
        if (!page)
                page = alloc_pages_node(dev_to_node(dev), flag, get_order(size));
        if (!page)
index acb3b606613eb5b4937cdacab17adc74c4ec2c30..cfbe99f888300d819b53552a7668ab9bd12c3708 100644 (file)
@@ -653,13 +653,10 @@ unsigned long native_calibrate_tsc(void)
 
        /* Calibrate TSC using MSR for Intel Atom SoCs */
        local_irq_save(flags);
-       i = try_msr_calibrate_tsc(&fast_calibrate);
+       fast_calibrate = try_msr_calibrate_tsc();
        local_irq_restore(flags);
-       if (i >= 0) {
-               if (i == 0)
-                       pr_warn("Fast TSC calibration using MSR failed\n");
+       if (fast_calibrate)
                return fast_calibrate;
-       }
 
        local_irq_save(flags);
        fast_calibrate = quick_pit_calibrate();
index 8b5434f4389fc4afbbc7d297ab61ec403aedb9d8..92ae6acac8a7fbcb9b91cb386b3c23015c5377ea 100644 (file)
@@ -53,7 +53,7 @@ static struct freq_desc freq_desc_tables[] = {
        /* TNG */
        { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } },
        /* VLV2 */
-       { 6, 0x37, 1, { 0, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
+       { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
        /* ANN */
        { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } },
 };
@@ -77,21 +77,18 @@ static int match_cpu(u8 family, u8 model)
 
 /*
  * Do MSR calibration only for known/supported CPUs.
- * Return values:
- * -1: CPU is unknown/unsupported for MSR based calibration
- *  0: CPU is known/supported, but calibration failed
- *  1: CPU is known/supported, and calibration succeeded
+ *
+ * Returns the calibration value or 0 if MSR calibration failed.
  */
-int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
+unsigned long try_msr_calibrate_tsc(void)
 {
-       int cpu_index;
        u32 lo, hi, ratio, freq_id, freq;
+       unsigned long res;
+       int cpu_index;
 
        cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model);
        if (cpu_index < 0)
-               return -1;
-
-       *fast_calibrate = 0;
+               return 0;
 
        if (freq_desc_tables[cpu_index].msr_plat) {
                rdmsr(MSR_PLATFORM_INFO, lo, hi);
@@ -103,7 +100,7 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
        pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
 
        if (!ratio)
-               return 0;
+               goto fail;
 
        /* Get FSB FREQ ID */
        rdmsr(MSR_FSB_FREQ, lo, hi);
@@ -112,16 +109,19 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
        pr_info("Resolved frequency ID: %u, frequency: %u KHz\n",
                                freq_id, freq);
        if (!freq)
-               return 0;
+               goto fail;
 
        /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
-       *fast_calibrate = freq * ratio;
-       pr_info("TSC runs at %lu KHz\n", *fast_calibrate);
+       res = freq * ratio;
+       pr_info("TSC runs at %lu KHz\n", res);
 
 #ifdef CONFIG_X86_LOCAL_APIC
        lapic_timer_frequency = (freq * 1000) / HZ;
        pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency);
 #endif
+       return res;
 
-       return 1;
+fail:
+       pr_warn("Fast TSC calibration using MSR failed\n");
+       return 0;
 }
index e50425d0f5f792c1c940f85cd66e890e5fa3a6ac..9b531351a5876835e3dda6527571383a7fbae751 100644 (file)
@@ -2672,6 +2672,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
                        break;
                }
 
+               drop_large_spte(vcpu, iterator.sptep);
                if (!is_shadow_present_pte(*iterator.sptep)) {
                        u64 base_addr = iterator.addr;
 
index a06f101ef64b4ae43e954319bbaa81a5c24c326b..3927528347510bb137e8420f4e26b07d09055483 100644 (file)
@@ -6688,7 +6688,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                else if (is_page_fault(intr_info))
                        return enable_ept;
                else if (is_no_device(intr_info) &&
-                        !(nested_read_cr0(vmcs12) & X86_CR0_TS))
+                        !(vmcs12->guest_cr0 & X86_CR0_TS))
                        return 0;
                return vmcs12->exception_bitmap &
                                (1u << (intr_info & INTR_INFO_VECTOR_MASK));
index 39c28f09dfd5f03ca064be4bb5cfa01eb0d673a4..2b8578432d5bccd296fa6d5859e3575c0fe4aa02 100644 (file)
@@ -6186,7 +6186,7 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
                frag->len -= len;
        }
 
-       if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
+       if (vcpu->mmio_cur_fragment >= vcpu->mmio_nr_fragments) {
                vcpu->mmio_needed = 0;
 
                /* FIXME: return into emulator if single-stepping.  */
index ba56e11cbf77697f4e972fadd7dd3281f07d4376..c87ae7c6e5f94636ab576a649ada006b4fb376dc 100644 (file)
@@ -20,6 +20,7 @@ config XTENSA
        select HAVE_FUNCTION_TRACER
        select HAVE_IRQ_TIME_ACCOUNTING
        select HAVE_PERF_EVENTS
+       select COMMON_CLK
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
          primarily for embedded systems.  These processors are both
@@ -80,7 +81,6 @@ choice
 config XTENSA_VARIANT_FSF
        bool "fsf - default (not generic) configuration"
        select MMU
-       select HAVE_XTENSA_GPIO32
 
 config XTENSA_VARIANT_DC232B
        bool "dc232b - Diamond 232L Standard Core Rev.B (LE)"
@@ -135,7 +135,6 @@ config HAVE_SMP
 config SMP
        bool "Enable Symmetric multi-processing support"
        depends on HAVE_SMP
-       select USE_GENERIC_SMP_HELPERS
        select GENERIC_SMP_IDLE_THREAD
        help
          Enabled SMP Software; allows more than one CPU/CORE
index 46b4f5eab421badbec1ae38cab4afac88fb7c731..e7370b11348e8d06c113d420704664740dbdec9b 100644 (file)
                interrupt-controller;
        };
 
+       clocks {
+               osc: main-oscillator {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+               };
+       };
+
        serial0: serial@fd050020 {
                device_type = "serial";
                compatible = "ns16550a";
@@ -42,9 +49,7 @@
                reg = <0xfd050020 0x20>;
                reg-shift = <2>;
                interrupts = <0 1>; /* external irq 0 */
-               /* Filled in by platform_setup from FPGA register
-                * clock-frequency = <100000000>;
-                */
+               clocks = <&osc>;
        };
 
        enet0: ethoc@fd030000 {
@@ -52,5 +57,6 @@
                reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
                interrupts = <1 1>; /* external irq 1 */
                local-mac-address = [00 50 c2 13 6f 00];
+               clocks = <&osc>;
        };
 };
index 2a042d430c253b7dae704633727f0eabc0d5fc91..74944207167eccfb0f6e122ad7418d5728d4a2b7 100644 (file)
@@ -25,7 +25,7 @@
 
 #ifdef CONFIG_MMU
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 extern unsigned long xtensa_kio_paddr;
 
 static inline unsigned long xtensa_get_kio_paddr(void)
index 8c194f6af45e09932976b3f71d8d70a8f556488f..677bfcf4ee5ddab2207ed0e5f2885b4accd29f16 100644 (file)
@@ -23,25 +23,37 @@ void secondary_trap_init(void);
 
 static inline void spill_registers(void)
 {
-
+#if XCHAL_NUM_AREGS > 16
        __asm__ __volatile__ (
-               "movi   a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t"
-               "mov    a12, a0\n\t"
-               "rsr    a13, sar\n\t"
-               "xsr    a14, ps\n\t"
-               "movi   a0, _spill_registers\n\t"
-               "rsync\n\t"
-               "callx0 a0\n\t"
-               "mov    a0, a12\n\t"
-               "wsr    a13, sar\n\t"
-               "wsr    a14, ps\n\t"
-               : :
-#if defined(CONFIG_FRAME_POINTER)
-               : "a2", "a3", "a4",       "a11", "a12", "a13", "a14", "a15",
+               "       call12  1f\n"
+               "       _j      2f\n"
+               "       retw\n"
+               "       .align  4\n"
+               "1:\n"
+               "       _entry  a1, 48\n"
+               "       addi    a12, a0, 3\n"
+#if XCHAL_NUM_AREGS > 32
+               "       .rept   (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
+               "       _entry  a1, 48\n"
+               "       mov     a12, a0\n"
+               "       .endr\n"
+#endif
+               "       _entry  a1, 48\n"
+#if XCHAL_NUM_AREGS % 12 == 0
+               "       mov     a8, a8\n"
+#elif XCHAL_NUM_AREGS % 12 == 4
+               "       mov     a12, a12\n"
+#elif XCHAL_NUM_AREGS % 12 == 8
+               "       mov     a4, a4\n"
+#endif
+               "       retw\n"
+               "2:\n"
+               : : : "a12", "a13", "memory");
 #else
-               : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15",
+       __asm__ __volatile__ (
+               "       mov     a12, a12\n"
+               : : : "memory");
 #endif
-                 "memory");
 }
 
 #endif /* _XTENSA_TRAPS_H */
index 5791b45d5a5d5b25f97f9d7d5ee8e05b80ace6cb..f74ddfbb92ef56587b618db2a7e80a2c96593499 100644 (file)
@@ -25,7 +25,7 @@
 #define XCHAL_KIO_DEFAULT_PADDR                0xf0000000
 #define XCHAL_KIO_SIZE                 0x10000000
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 #define XCHAL_KIO_PADDR                        xtensa_get_kio_paddr()
 #else
 #define XCHAL_KIO_PADDR                        XCHAL_KIO_DEFAULT_PADDR
index 51940fec6990f2b9a1c86fa5c43a199c3eade2f0..b9395529f02d465643091d71c4d6b6ca9650ff4b 100644 (file)
@@ -734,7 +734,12 @@ __SYSCALL(332, sys_finit_module, 3)
 #define __NR_accept4                           333
 __SYSCALL(333, sys_accept4, 4)
 
-#define __NR_syscall_count                     334
+#define __NR_sched_setattr                     334
+__SYSCALL(334, sys_sched_setattr, 2)
+#define __NR_sched_getattr                     335
+__SYSCALL(335, sys_sched_getattr, 3)
+
+#define __NR_syscall_count                     336
 
 /*
  * sysxtensa syscall handler
index 21dbe6bdb8edc661d729f656a02a5f1cf01a18c1..ef7f4990722b4fde3a175a0d524f82c3b2ce8b7b 100644 (file)
@@ -1081,196 +1081,53 @@ ENTRY(fast_syscall_spill_registers)
 
        rsr     a0, sar
        s32i    a3, a2, PT_AREG3
-       s32i    a4, a2, PT_AREG4
-       s32i    a0, a2, PT_AREG5        # store SAR to PT_AREG5
+       s32i    a0, a2, PT_SAR
 
-       /* The spill routine might clobber a7, a11, and a15. */
+       /* The spill routine might clobber a4, a7, a8, a11, a12, and a15. */
 
+       s32i    a4, a2, PT_AREG4
        s32i    a7, a2, PT_AREG7
+       s32i    a8, a2, PT_AREG8
        s32i    a11, a2, PT_AREG11
+       s32i    a12, a2, PT_AREG12
        s32i    a15, a2, PT_AREG15
 
-       call0   _spill_registers        # destroys a3, a4, and SAR
-
-       /* Advance PC, restore registers and SAR, and return from exception. */
-
-       l32i    a3, a2, PT_AREG5
-       l32i    a4, a2, PT_AREG4
-       l32i    a0, a2, PT_AREG0
-       wsr     a3, sar
-       l32i    a3, a2, PT_AREG3
-
-       /* Restore clobbered registers. */
-
-       l32i    a7, a2, PT_AREG7
-       l32i    a11, a2, PT_AREG11
-       l32i    a15, a2, PT_AREG15
-
-       movi    a2, 0
-       rfe
-
-ENDPROC(fast_syscall_spill_registers)
-
-/* Fixup handler.
- *
- * We get here if the spill routine causes an exception, e.g. tlb miss.
- * We basically restore WINDOWBASE and WINDOWSTART to the condition when
- * we entered the spill routine and jump to the user exception handler.
- *
- * a0: value of depc, original value in depc
- * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
- * a3: exctable, original value in excsave1
- */
-
-ENTRY(fast_syscall_spill_registers_fixup)
-
-       rsr     a2, windowbase  # get current windowbase (a2 is saved)
-       xsr     a0, depc        # restore depc and a0
-       ssl     a2              # set shift (32 - WB)
-
-       /* We need to make sure the current registers (a0-a3) are preserved.
-        * To do this, we simply set the bit for the current window frame
-        * in WS, so that the exception handlers save them to the task stack.
-        */
-
-       xsr     a3, excsave1    # get spill-mask
-       slli    a3, a3, 1       # shift left by one
-
-       slli    a2, a3, 32-WSBITS
-       src     a2, a3, a2      # a2 = xxwww1yyxxxwww1yy......
-       wsr     a2, windowstart # set corrected windowstart
-
-       srli    a3, a3, 1
-       rsr     a2, excsave1
-       l32i    a2, a2, EXC_TABLE_DOUBLE_SAVE   # restore a2
-       xsr     a2, excsave1
-       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE   # save a3
-       l32i    a3, a2, EXC_TABLE_PARAM # original WB (in user task)
-       xsr     a2, excsave1
-
-       /* Return to the original (user task) WINDOWBASE.
-        * We leave the following frame behind:
-        * a0, a1, a2   same
-        * a3:          trashed (saved in EXC_TABLE_DOUBLE_SAVE)
-        * depc:        depc (we have to return to that address)
-        * excsave_1:   exctable
-        */
-
-       wsr     a3, windowbase
-       rsync
-
-       /* We are now in the original frame when we entered _spill_registers:
-        *  a0: return address
-        *  a1: used, stack pointer
-        *  a2: kernel stack pointer
-        *  a3: available
-        *  depc: exception address
-        *  excsave: exctable
-        * Note: This frame might be the same as above.
-        */
-
-       /* Setup stack pointer. */
-
-       addi    a2, a2, -PT_USER_SIZE
-       s32i    a0, a2, PT_AREG0
-
-       /* Make sure we return to this fixup handler. */
-
-       movi    a3, fast_syscall_spill_registers_fixup_return
-       s32i    a3, a2, PT_DEPC         # setup depc
-
-       /* Jump to the exception handler. */
-
-       rsr     a3, excsave1
-       rsr     a0, exccause
-       addx4   a0, a0, a3                      # find entry in table
-       l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
-       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
-       jx      a0
-
-ENDPROC(fast_syscall_spill_registers_fixup)
-
-ENTRY(fast_syscall_spill_registers_fixup_return)
-
-       /* When we return here, all registers have been restored (a2: DEPC) */
-
-       wsr     a2, depc                # exception address
-
-       /* Restore fixup handler. */
-
-       rsr     a2, excsave1
-       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE
-       movi    a3, fast_syscall_spill_registers_fixup
-       s32i    a3, a2, EXC_TABLE_FIXUP
-       rsr     a3, windowbase
-       s32i    a3, a2, EXC_TABLE_PARAM
-       l32i    a2, a2, EXC_TABLE_KSTK
-
-       /* Load WB at the time the exception occurred. */
-
-       rsr     a3, sar                 # WB is still in SAR
-       neg     a3, a3
-       wsr     a3, windowbase
-       rsync
-
-       rsr     a3, excsave1
-       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
-
-       rfde
-
-ENDPROC(fast_syscall_spill_registers_fixup_return)
-
-/*
- * spill all registers.
- *
- * This is not a real function. The following conditions must be met:
- *
- *  - must be called with call0.
- *  - uses a3, a4 and SAR.
- *  - the last 'valid' register of each frame are clobbered.
- *  - the caller must have registered a fixup handler
- *    (or be inside a critical section)
- *  - PS_EXCM must be set (PS_WOE cleared?)
- */
-
-ENTRY(_spill_registers)
-
        /*
         * Rotate ws so that the current windowbase is at bit 0.
         * Assume ws = xxxwww1yy (www1 current window frame).
         * Rotate ws right so that a4 = yyxxxwww1.
         */
 
-       rsr     a4, windowbase
+       rsr     a0, windowbase
        rsr     a3, windowstart         # a3 = xxxwww1yy
-       ssr     a4                      # holds WB
-       slli    a4, a3, WSBITS
-       or      a3, a3, a4              # a3 = xxxwww1yyxxxwww1yy
+       ssr     a0                      # holds WB
+       slli    a0, a3, WSBITS
+       or      a3, a3, a0              # a3 = xxxwww1yyxxxwww1yy
        srl     a3, a3                  # a3 = 00xxxwww1yyxxxwww1
 
        /* We are done if there are no more than the current register frame. */
 
        extui   a3, a3, 1, WSBITS-1     # a3 = 0yyxxxwww
-       movi    a4, (1 << (WSBITS-1))
+       movi    a0, (1 << (WSBITS-1))
        _beqz   a3, .Lnospill           # only one active frame? jump
 
        /* We want 1 at the top, so that we return to the current windowbase */
 
-       or      a3, a3, a4              # 1yyxxxwww
+       or      a3, a3, a0              # 1yyxxxwww
 
        /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
 
        wsr     a3, windowstart         # save shifted windowstart
-       neg     a4, a3
-       and     a3, a4, a3              # first bit set from right: 000010000
+       neg     a0, a3
+       and     a3, a0, a3              # first bit set from right: 000010000
 
-       ffs_ws  a4, a3                  # a4: shifts to skip empty frames
+       ffs_ws  a0, a3                  # a0: shifts to skip empty frames
        movi    a3, WSBITS
-       sub     a4, a3, a4              # WSBITS-a4:number of 0-bits from right
-       ssr     a4                      # save in SAR for later.
+       sub     a0, a3, a0              # WSBITS-a0:number of 0-bits from right
+       ssr     a0                      # save in SAR for later.
 
        rsr     a3, windowbase
-       add     a3, a3, a4
+       add     a3, a3, a0
        wsr     a3, windowbase
        rsync
 
@@ -1285,22 +1142,6 @@ ENTRY(_spill_registers)
         * we have to save 4,8. or 12 registers.
         */
 
-       _bbsi.l a3, 1, .Lc4
-       _bbsi.l a3, 2, .Lc8
-
-       /* Special case: we have a call12-frame starting at a4. */
-
-       _bbci.l a3, 3, .Lc12    # bit 3 shouldn't be zero! (Jump to Lc12 first)
-
-       s32e    a4, a1, -16     # a1 is valid with an empty spill area
-       l32e    a4, a5, -12
-       s32e    a8, a4, -48
-       mov     a8, a4
-       l32e    a4, a1, -16
-       j       .Lc12c
-
-.Lnospill:
-       ret
 
 .Lloop: _bbsi.l        a3, 1, .Lc4
        _bbci.l a3, 2, .Lc12
@@ -1314,20 +1155,10 @@ ENTRY(_spill_registers)
        s32e    a9, a4, -28
        s32e    a10, a4, -24
        s32e    a11, a4, -20
-
        srli    a11, a3, 2              # shift windowbase by 2
        rotw    2
        _bnei   a3, 1, .Lloop
-
-.Lexit: /* Done. Do the final rotation, set WS, and return. */
-
-       rotw    1
-       rsr     a3, windowbase
-       ssl     a3
-       movi    a3, 1
-       sll     a3, a3
-       wsr     a3, windowstart
-       ret
+       j       .Lexit
 
 .Lc4:  s32e    a4, a9, -16
        s32e    a5, a9, -12
@@ -1343,11 +1174,11 @@ ENTRY(_spill_registers)
 
        /* 12-register frame (call12) */
 
-       l32e    a2, a5, -12
-       s32e    a8, a2, -48
-       mov     a8, a2
+       l32e    a0, a5, -12
+       s32e    a8, a0, -48
+       mov     a8, a0
 
-.Lc12c: s32e   a9, a8, -44
+       s32e    a9, a8, -44
        s32e    a10, a8, -40
        s32e    a11, a8, -36
        s32e    a12, a8, -32
@@ -1367,30 +1198,54 @@ ENTRY(_spill_registers)
         */
 
        rotw    1
-       mov     a5, a13
+       mov     a4, a13
        rotw    -1
 
-       s32e    a4, a9, -16
-       s32e    a5, a9, -12
-       s32e    a6, a9, -8
-       s32e    a7, a9, -4
+       s32e    a4, a8, -16
+       s32e    a5, a8, -12
+       s32e    a6, a8, -8
+       s32e    a7, a8, -4
 
        rotw    3
 
        _beqi   a3, 1, .Lexit
        j       .Lloop
 
-.Linvalid_mask:
+.Lexit:
 
-       /* We get here because of an unrecoverable error in the window
-        * registers. If we are in user space, we kill the application,
-        * however, this condition is unrecoverable in kernel space.
-        */
+       /* Done. Do the final rotation and set WS */
+
+       rotw    1
+       rsr     a3, windowbase
+       ssl     a3
+       movi    a3, 1
+       sll     a3, a3
+       wsr     a3, windowstart
+.Lnospill:
+
+       /* Advance PC, restore registers and SAR, and return from exception. */
+
+       l32i    a3, a2, PT_SAR
+       l32i    a0, a2, PT_AREG0
+       wsr     a3, sar
+       l32i    a3, a2, PT_AREG3
 
-       rsr     a0, ps
-       _bbci.l a0, PS_UM_BIT, 1f
+       /* Restore clobbered registers. */
 
-       /* User space: Setup a dummy frame and kill application.
+       l32i    a4, a2, PT_AREG4
+       l32i    a7, a2, PT_AREG7
+       l32i    a8, a2, PT_AREG8
+       l32i    a11, a2, PT_AREG11
+       l32i    a12, a2, PT_AREG12
+       l32i    a15, a2, PT_AREG15
+
+       movi    a2, 0
+       rfe
+
+.Linvalid_mask:
+
+       /* We get here because of an unrecoverable error in the window
+        * registers, so set up a dummy frame and kill the user application.
         * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
         */
 
@@ -1414,14 +1269,136 @@ ENTRY(_spill_registers)
        movi    a4, do_exit
        callx4  a4
 
-1:     /* Kernel space: PANIC! */
+       /* shouldn't return, so panic */
 
        wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0              # should not return
 1:     j       1b
 
-ENDPROC(_spill_registers)
+
+ENDPROC(fast_syscall_spill_registers)
+
+/* Fixup handler.
+ *
+ * We get here if the spill routine causes an exception, e.g. tlb miss.
+ * We basically restore WINDOWBASE and WINDOWSTART to the condition when
+ * we entered the spill routine and jump to the user exception handler.
+ *
+ * Note that we only need to restore the bits in windowstart that have not
+ * been spilled yet by the _spill_register routine. Luckily, a3 contains a
+ * rotated windowstart with only those bits set for frames that haven't been
+ * spilled yet. Because a3 is rotated such that bit 0 represents the register
+ * frame for the current windowbase - 1, we need to rotate a3 left by the
+ * value of the current windowbase + 1 and move it to windowstart.
+ *
+ * a0: value of depc, original value in depc
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
+ * a3: exctable, original value in excsave1
+ */
+
+ENTRY(fast_syscall_spill_registers_fixup)
+
+       rsr     a2, windowbase  # get current windowbase (a2 is saved)
+       xsr     a0, depc        # restore depc and a0
+       ssl     a2              # set shift (32 - WB)
+
+       /* We need to make sure the current registers (a0-a3) are preserved.
+        * To do this, we simply set the bit for the current window frame
+        * in WS, so that the exception handlers save them to the task stack.
+        *
+        * Note: we use a3 to set the windowbase, so we take a special care
+        * of it, saving it in the original _spill_registers frame across
+        * the exception handler call.
+        */
+
+       xsr     a3, excsave1    # get spill-mask
+       slli    a3, a3, 1       # shift left by one
+       addi    a3, a3, 1       # set the bit for the current window frame
+
+       slli    a2, a3, 32-WSBITS
+       src     a2, a3, a2      # a2 = xxwww1yyxxxwww1yy......
+       wsr     a2, windowstart # set corrected windowstart
+
+       srli    a3, a3, 1
+       rsr     a2, excsave1
+       l32i    a2, a2, EXC_TABLE_DOUBLE_SAVE   # restore a2
+       xsr     a2, excsave1
+       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE   # save a3
+       l32i    a3, a2, EXC_TABLE_PARAM # original WB (in user task)
+       xsr     a2, excsave1
+
+       /* Return to the original (user task) WINDOWBASE.
+        * We leave the following frame behind:
+        * a0, a1, a2   same
+        * a3:          trashed (saved in EXC_TABLE_DOUBLE_SAVE)
+        * depc:        depc (we have to return to that address)
+        * excsave_1:   exctable
+        */
+
+       wsr     a3, windowbase
+       rsync
+
+       /* We are now in the original frame when we entered _spill_registers:
+        *  a0: return address
+        *  a1: used, stack pointer
+        *  a2: kernel stack pointer
+        *  a3: available
+        *  depc: exception address
+        *  excsave: exctable
+        * Note: This frame might be the same as above.
+        */
+
+       /* Setup stack pointer. */
+
+       addi    a2, a2, -PT_USER_SIZE
+       s32i    a0, a2, PT_AREG0
+
+       /* Make sure we return to this fixup handler. */
+
+       movi    a3, fast_syscall_spill_registers_fixup_return
+       s32i    a3, a2, PT_DEPC         # setup depc
+
+       /* Jump to the exception handler. */
+
+       rsr     a3, excsave1
+       rsr     a0, exccause
+       addx4   a0, a0, a3                      # find entry in table
+       l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
+       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
+       jx      a0
+
+ENDPROC(fast_syscall_spill_registers_fixup)
+
+ENTRY(fast_syscall_spill_registers_fixup_return)
+
+       /* When we return here, all registers have been restored (a2: DEPC) */
+
+       wsr     a2, depc                # exception address
+
+       /* Restore fixup handler. */
+
+       rsr     a2, excsave1
+       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE
+       movi    a3, fast_syscall_spill_registers_fixup
+       s32i    a3, a2, EXC_TABLE_FIXUP
+       rsr     a3, windowbase
+       s32i    a3, a2, EXC_TABLE_PARAM
+       l32i    a2, a2, EXC_TABLE_KSTK
+
+       /* Load WB at the time the exception occurred. */
+
+       rsr     a3, sar                 # WB is still in SAR
+       neg     a3, a3
+       wsr     a3, windowbase
+       rsync
+
+       rsr     a3, excsave1
+       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
+
+       rfde
+
+ENDPROC(fast_syscall_spill_registers_fixup_return)
 
 #ifdef CONFIG_MMU
 /*
@@ -1794,6 +1771,43 @@ ENTRY(system_call)
 
 ENDPROC(system_call)
 
+/*
+ * Spill live registers on the kernel stack macro.
+ *
+ * Entry condition: ps.woe is set, ps.excm is cleared
+ * Exit condition: windowstart has single bit set
+ * May clobber: a12, a13
+ */
+       .macro  spill_registers_kernel
+
+#if XCHAL_NUM_AREGS > 16
+       call12  1f
+       _j      2f
+       retw
+       .align  4
+1:
+       _entry  a1, 48
+       addi    a12, a0, 3
+#if XCHAL_NUM_AREGS > 32
+       .rept   (XCHAL_NUM_AREGS - 32) / 12
+       _entry  a1, 48
+       mov     a12, a0
+       .endr
+#endif
+       _entry  a1, 48
+#if XCHAL_NUM_AREGS % 12 == 0
+       mov     a8, a8
+#elif XCHAL_NUM_AREGS % 12 == 4
+       mov     a12, a12
+#elif XCHAL_NUM_AREGS % 12 == 8
+       mov     a4, a4
+#endif
+       retw
+2:
+#else
+       mov     a12, a12
+#endif
+       .endm
 
 /*
  * Task switch.
@@ -1806,21 +1820,20 @@ ENTRY(_switch_to)
 
        entry   a1, 16
 
-       mov     a12, a2                 # preserve 'prev' (a2)
-       mov     a13, a3                 # and 'next' (a3)
+       mov     a10, a2                 # preserve 'prev' (a2)
+       mov     a11, a3                 # and 'next' (a3)
 
        l32i    a4, a2, TASK_THREAD_INFO
        l32i    a5, a3, TASK_THREAD_INFO
 
-       save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+       save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
-       s32i    a0, a12, THREAD_RA      # save return address
-       s32i    a1, a12, THREAD_SP      # save stack pointer
+       s32i    a0, a10, THREAD_RA      # save return address
+       s32i    a1, a10, THREAD_SP      # save stack pointer
 
        /* Disable ints while we manipulate the stack pointer. */
 
-       movi    a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
-       xsr     a14, ps
+       rsil    a14, LOCKLEVEL
        rsr     a3, excsave1
        rsync
        s32i    a3, a3, EXC_TABLE_FIXUP /* enter critical section */
@@ -1835,7 +1848,7 @@ ENTRY(_switch_to)
 
        /* Flush register file. */
 
-       call0   _spill_registers        # destroys a3, a4, and SAR
+       spill_registers_kernel
 
        /* Set kernel stack (and leave critical section)
         * Note: It's save to set it here. The stack will not be overwritten
@@ -1851,13 +1864,13 @@ ENTRY(_switch_to)
 
        /* restore context of the task 'next' */
 
-       l32i    a0, a13, THREAD_RA      # restore return address
-       l32i    a1, a13, THREAD_SP      # restore stack pointer
+       l32i    a0, a11, THREAD_RA      # restore return address
+       l32i    a1, a11, THREAD_SP      # restore stack pointer
 
-       load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+       load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
        wsr     a14, ps
-       mov     a2, a12                 # return 'prev'
+       mov     a2, a10                 # return 'prev'
        rsync
 
        retw
index 7d12af1317f183d9af4b813ba4fd11bc94450924..84fe931bb60e1f012417d202d002813b12cf68aa 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
+#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
@@ -276,6 +277,7 @@ void __init early_init_devtree(void *params)
 
 static int __init xtensa_device_probe(void)
 {
+       of_clk_init(NULL);
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
        return 0;
 }
index 08b769d3b3a1c48482179eac8c68c562f61321c4..2a1823de69ccf621b6ea63e2ad815bbe118fa2f9 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/platform.h>
 
 unsigned long ccount_freq;             /* ccount Hz */
+EXPORT_SYMBOL(ccount_freq);
 
 static cycle_t ccount_read(struct clocksource *cs)
 {
index cb8fd44caabc6d246ce7975dfc0f370d87052fc2..f9e1ec346e359c7410482c5d8dfd5a9de88bfafc 100644 (file)
@@ -235,7 +235,7 @@ ENTRY(_DoubleExceptionVector)
 
        /* Check for overflow/underflow exception, jump if overflow. */
 
-       _bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow
+       bbci.l  a0, 6, _DoubleExceptionVector_WindowOverflow
 
        /*
         * Restart window underflow exception.
index 74a60c7e085ea40349336089889de2d52f9d142c..80b33ed51f31174fd41a53bebd957c140517d8f9 100644 (file)
@@ -122,9 +122,7 @@ EXPORT_SYMBOL(insw);
 EXPORT_SYMBOL(insl);
 
 extern long common_exception_return;
-extern long _spill_registers;
 EXPORT_SYMBOL(common_exception_return);
-EXPORT_SYMBOL(_spill_registers);
 
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
index 479d7537a32a4f8039ae02581f8644d53eb80dda..aff108df92d3a301e8ba0ccaf7e13a5fb26c9038 100644 (file)
@@ -90,7 +90,7 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
 
 
 /*
- * Initialize the bootmem system and give it all the memory we have available.
+ * Initialize the bootmem system and give it all low memory we have available.
  */
 
 void __init bootmem_init(void)
@@ -142,9 +142,14 @@ void __init bootmem_init(void)
 
        /* Add all remaining memory pieces into the bootmem map */
 
-       for (i=0; i<sysmem.nr_banks; i++)
-               free_bootmem(sysmem.bank[i].start,
-                            sysmem.bank[i].end - sysmem.bank[i].start);
+       for (i = 0; i < sysmem.nr_banks; i++) {
+               if (sysmem.bank[i].start >> PAGE_SHIFT < max_low_pfn) {
+                       unsigned long end = min(max_low_pfn << PAGE_SHIFT,
+                                               sysmem.bank[i].end);
+                       free_bootmem(sysmem.bank[i].start,
+                                    end - sysmem.bank[i].start);
+               }
+       }
 
 }
 
index 36ec171698b833ddbebb6c9e51e9f18d4c53f278..861203e958da828deb140122752e95b47ddbf35f 100644 (file)
@@ -39,7 +39,7 @@ void init_mmu(void)
        set_itlbcfg_register(0);
        set_dtlbcfg_register(0);
 #endif
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
        /*
         * Update the IO area mapping in case xtensa_kio_paddr has changed
         */
index 800227862fe8b91d561e8b318b757675a1e21f68..57fd08b36f51a151a389794bf4e8af7c9b64fd13 100644 (file)
@@ -135,11 +135,11 @@ static void __init update_local_mac(struct device_node *node)
 
 static int __init machine_setup(void)
 {
-       struct device_node *serial;
+       struct device_node *clock;
        struct device_node *eth = NULL;
 
-       for_each_compatible_node(serial, NULL, "ns16550a")
-               update_clock_frequency(serial);
+       for_each_node_by_name(clock, "main-oscillator")
+               update_clock_frequency(clock);
 
        if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc")))
                update_local_mac(eth);
@@ -290,6 +290,7 @@ static int __init xtavnet_init(void)
         * knows whether they set it correctly on the DIP switches.
         */
        pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr);
+       ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR;
 
        return 0;
 }
index bf4020116df521d18e1891d33a1815154b6046e9..244cdea4dee50252a06e41799badfb1c5c2e61a1 100644 (file)
 #define XCHAL_CP_MASK                  0x00    /* bitmask of all CPs by ID */
 #define XCHAL_CP_PORT_MASK             0x00    /* bitmask of only port CPs */
 
-/*  Basic parameters of each coprocessor:  */
-#define XCHAL_CP7_NAME                 "XTIOP"
-#define XCHAL_CP7_IDENT                        XTIOP
-#define XCHAL_CP7_SA_SIZE              0       /* size of state save area */
-#define XCHAL_CP7_SA_ALIGN             1       /* min alignment of save area */
-#define XCHAL_CP_ID_XTIOP              7       /* coprocessor ID (0..7) */
-
 /*  Filler info for unassigned coprocessors, to simplify arrays etc:  */
 #define XCHAL_NCP_SA_SIZE              0
 #define XCHAL_NCP_SA_ALIGN             1
@@ -42,6 +35,8 @@
 #define XCHAL_CP5_SA_ALIGN             1
 #define XCHAL_CP6_SA_SIZE              0
 #define XCHAL_CP6_SA_ALIGN             1
+#define XCHAL_CP7_SA_SIZE              0
+#define XCHAL_CP7_SA_ALIGN             1
 
 /*  Save area for non-coprocessor optional and custom (TIE) state:  */
 #define XCHAL_NCP_SA_SIZE              0
index e7515aa43d6bd62c3ec0e33fb6781d2a9f2f27a7..6f190bc2b8b784bf7e09425b77c560fa60f04b90 100644 (file)
@@ -243,6 +243,8 @@ static int acpi_ac_resume(struct device *dev)
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
        return 0;
 }
+#else
+#define acpi_ac_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
 
index 018a4288370630cb40203ecd43cc2809851288ae..797a6938d0515edb7ce7e5ce3f4f1648c538e515 100644 (file)
@@ -841,6 +841,8 @@ static int acpi_battery_resume(struct device *dev)
        acpi_battery_update(battery);
        return 0;
 }
+#else
+#define acpi_battery_resume NULL
 #endif
 
 static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
index 10e4964d051a9c295e6185db1cfebe20b0ce5a9d..afec4526c48aa04e2921a199396e8fb2ea7489be 100644 (file)
@@ -260,14 +260,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
        },
        {
        .callback = dmi_disable_osi_win8,
-       .ident = "Dell Inspiron 15R SE",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
        .ident = "ThinkPad Edge E530",
        .matches = {
                     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -322,56 +314,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
                },
        },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ProBook 2013 models",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
-                    DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP EliteBook 2013 models",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
-                    DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ZBook 14",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ZBook 15",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ZBook 17",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP EliteBook 8780w",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
-               },
-       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index 11c11f6b8fa1453a4a28c3931f0cf8618750fecc..714e957a871a8034ed18be2104b8c107d0b4ced9 100644 (file)
@@ -80,6 +80,8 @@ static void acpi_button_notify(struct acpi_device *device, u32 event);
 
 #ifdef CONFIG_PM_SLEEP
 static int acpi_button_resume(struct device *dev);
+#else
+#define acpi_button_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
 
index e9b3081c4fe994bdfd7dcba5b54ae0533cf8f110..5bfd769fc91fa5bfd0890a146a4eed13ac342ff0 100644 (file)
@@ -713,13 +713,11 @@ static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl,
 static ssize_t show_docked(struct device *dev,
                           struct device_attribute *attr, char *buf)
 {
-       struct acpi_device *tmp;
-
        struct dock_station *dock_station = dev->platform_data;
+       struct acpi_device *adev = NULL;
 
-       if (!acpi_bus_get_device(dock_station->handle, &tmp))
-               return snprintf(buf, PAGE_SIZE, "1\n");
-       return snprintf(buf, PAGE_SIZE, "0\n");
+       acpi_bus_get_device(dock_station->handle, &adev);
+       return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
 }
 static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
 
index 1fb62900f32a9c57d329fd3e5480bc0dc7c305b8..09e423f3d8ad30fbd16d2d2b2e2766e69e64de82 100644 (file)
@@ -55,6 +55,9 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev);
 static int acpi_fan_resume(struct device *dev);
+#else
+#define acpi_fan_suspend NULL
+#define acpi_fan_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
 
index 52d45ea2bc4f63efcfb7e8912b087b1a568d49cc..361b40c10c3f522e28e2b334dd5f8976109bc772 100644 (file)
@@ -430,6 +430,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                                 pin_name(pin));
                }
 
+               kfree(entry);
                return 0;
        }
 
index 28baa05b8018dd6c6e6e1db93c1a5ceed74d4d74..84243c32e29c515381634b6e7b2cc6f4d219635b 100644 (file)
@@ -56,6 +56,12 @@ struct throttling_tstate {
        int target_state;               /* target T-state */
 };
 
+struct acpi_processor_throttling_arg {
+       struct acpi_processor *pr;
+       int target_state;
+       bool force;
+};
+
 #define THROTTLING_PRECHANGE       (1)
 #define THROTTLING_POSTCHANGE      (2)
 
@@ -1060,16 +1066,24 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
        return 0;
 }
 
+static long acpi_processor_throttling_fn(void *data)
+{
+       struct acpi_processor_throttling_arg *arg = data;
+       struct acpi_processor *pr = arg->pr;
+
+       return pr->throttling.acpi_processor_set_throttling(pr,
+                       arg->target_state, arg->force);
+}
+
 int acpi_processor_set_throttling(struct acpi_processor *pr,
                                                int state, bool force)
 {
-       cpumask_var_t saved_mask;
        int ret = 0;
        unsigned int i;
        struct acpi_processor *match_pr;
        struct acpi_processor_throttling *p_throttling;
+       struct acpi_processor_throttling_arg arg;
        struct throttling_tstate t_state;
-       cpumask_var_t online_throttling_cpus;
 
        if (!pr)
                return -EINVAL;
@@ -1080,14 +1094,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
        if ((state < 0) || (state > (pr->throttling.state_count - 1)))
                return -EINVAL;
 
-       if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
-               return -ENOMEM;
-
-       if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
-               free_cpumask_var(saved_mask);
-               return -ENOMEM;
-       }
-
        if (cpu_is_offline(pr->id)) {
                /*
                 * the cpu pointed by pr->id is offline. Unnecessary to change
@@ -1096,17 +1102,15 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
                return -ENODEV;
        }
 
-       cpumask_copy(saved_mask, &current->cpus_allowed);
        t_state.target_state = state;
        p_throttling = &(pr->throttling);
-       cpumask_and(online_throttling_cpus, cpu_online_mask,
-                   p_throttling->shared_cpu_map);
+
        /*
         * The throttling notifier will be called for every
         * affected cpu in order to get one proper T-state.
         * The notifier event is THROTTLING_PRECHANGE.
         */
-       for_each_cpu(i, online_throttling_cpus) {
+       for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
                t_state.cpu = i;
                acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
                                                        &t_state);
@@ -1118,21 +1122,18 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
         * it can be called only for the cpu pointed by pr.
         */
        if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
-               /* FIXME: use work_on_cpu() */
-               if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
-                       /* Can't migrate to the pr->id CPU. Exit */
-                       ret = -ENODEV;
-                       goto exit;
-               }
-               ret = p_throttling->acpi_processor_set_throttling(pr,
-                                               t_state.target_state, force);
+               arg.pr = pr;
+               arg.target_state = state;
+               arg.force = force;
+               ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg);
        } else {
                /*
                 * When the T-state coordination is SW_ALL or HW_ALL,
                 * it is necessary to set T-state for every affected
                 * cpus.
                 */
-               for_each_cpu(i, online_throttling_cpus) {
+               for_each_cpu_and(i, cpu_online_mask,
+                   p_throttling->shared_cpu_map) {
                        match_pr = per_cpu(processors, i);
                        /*
                         * If the pointer is invalid, we will report the
@@ -1153,13 +1154,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
                                        "on CPU %d\n", i));
                                continue;
                        }
-                       t_state.cpu = i;
-                       /* FIXME: use work_on_cpu() */
-                       if (set_cpus_allowed_ptr(current, cpumask_of(i)))
-                               continue;
-                       ret = match_pr->throttling.
-                               acpi_processor_set_throttling(
-                               match_pr, t_state.target_state, force);
+
+                       arg.pr = match_pr;
+                       arg.target_state = state;
+                       arg.force = force;
+                       ret = work_on_cpu(pr->id, acpi_processor_throttling_fn,
+                               &arg);
                }
        }
        /*
@@ -1168,17 +1168,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
         * affected cpu to update the T-states.
         * The notifier event is THROTTLING_POSTCHANGE
         */
-       for_each_cpu(i, online_throttling_cpus) {
+       for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
                t_state.cpu = i;
                acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
                                                        &t_state);
        }
-       /* restore the previous state */
-       /* FIXME: use work_on_cpu() */
-       set_cpus_allowed_ptr(current, saved_mask);
-exit:
-       free_cpumask_var(online_throttling_cpus);
-       free_cpumask_var(saved_mask);
+
        return ret;
 }
 
index d465ae6cdd004b9813cc333529c54ef29abcb16f..dbd48498b93863a1fa37ab0b23706f2dae89345d 100644 (file)
@@ -450,7 +450,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
 {
        unsigned long x;
        struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
-       if (sscanf(buf, "%ld\n", &x) == 1)
+       if (sscanf(buf, "%lu\n", &x) == 1)
                battery->alarm_capacity = x /
                        (1000 * acpi_battery_scale(battery));
        if (battery->present)
@@ -668,6 +668,8 @@ static int acpi_sbs_resume(struct device *dev)
        acpi_sbs_callback(sbs);
        return 0;
 }
+#else
+#define acpi_sbs_resume NULL
 #endif
 
 static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
index 8349a555b92b8aa6d6584f9c2c5c9ccf7a27737f..08626c851be7eef72c5a639522b708586736adc5 100644 (file)
@@ -102,6 +102,8 @@ MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
 
 #ifdef CONFIG_PM_SLEEP
 static int acpi_thermal_resume(struct device *dev);
+#else
+#define acpi_thermal_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
 
index b727d105046d234ae8ef2a5669e53e61b82e7123..b6ba88ed31aeeb1854e48bb73b95fc59a4d58706 100644 (file)
@@ -81,11 +81,12 @@ static bool allow_duplicates;
 module_param(allow_duplicates, bool, 0644);
 
 /*
- * For Windows 8 systems: if set ture and the GPU driver has
- * registered a backlight interface, skip registering ACPI video's.
+ * For Windows 8 systems: used to decide if video module
+ * should skip registering backlight interface of its own.
  */
-static bool use_native_backlight = false;
-module_param(use_native_backlight, bool, 0644);
+static int use_native_backlight_param = -1;
+module_param_named(use_native_backlight, use_native_backlight_param, int, 0444);
+static bool use_native_backlight_dmi = false;
 
 static int register_count;
 static struct mutex video_list_lock;
@@ -231,9 +232,17 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
                                         int event);
 
+static bool acpi_video_use_native_backlight(void)
+{
+       if (use_native_backlight_param != -1)
+               return use_native_backlight_param;
+       else
+               return use_native_backlight_dmi;
+}
+
 static bool acpi_video_verify_backlight_support(void)
 {
-       if (acpi_osi_is_win8() && use_native_backlight &&
+       if (acpi_osi_is_win8() && acpi_video_use_native_backlight() &&
            backlight_device_registered(BACKLIGHT_RAW))
                return false;
        return acpi_video_backlight_support();
@@ -398,6 +407,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d)
        return 0;
 }
 
+static int __init video_set_use_native_backlight(const struct dmi_system_id *d)
+{
+       use_native_backlight_dmi = true;
+       return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] __initdata = {
        /*
         * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -442,6 +457,120 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
                },
        },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "ThinkPad T430s",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "ThinkPad X230",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "ThinkPad X1 Carbon",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Lenovo Yoga 13",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Dell Inspiron 7520",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Acer Aspire 5733Z",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Acer Aspire V5-431",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ProBook 4340s",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ProBook 2013 models",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
+               DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP EliteBook 2013 models",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
+               DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ZBook 14",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ZBook 15",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ZBook 17",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP EliteBook 8780w",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
+               },
+       },
        {}
 };
 
@@ -685,6 +814,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
        union acpi_object *o;
        struct acpi_video_device_brightness *br = NULL;
        int result = -EINVAL;
+       u32 value;
 
        if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -715,7 +845,12 @@ acpi_video_init_brightness(struct acpi_video_device *device)
                        printk(KERN_ERR PREFIX "Invalid data\n");
                        continue;
                }
-               br->levels[count] = (u32) o->integer.value;
+               value = (u32) o->integer.value;
+               /* Skip duplicate entries */
+               if (count > 2 && br->levels[count - 1] == value)
+                       continue;
+
+               br->levels[count] = value;
 
                if (br->levels[count] > max_level)
                        max_level = br->levels[count];
index a697b77b8865a163cd23fe591db0242631ca742f..19080c8e2f2a9c6d5df7f5475d581f5348ed9e8e 100644 (file)
@@ -168,22 +168,6 @@ static struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
                },
        },
-       {
-       .callback = video_detect_force_vendor,
-       .ident = "HP EliteBook Revolve 810",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Revolve 810 G1"),
-               },
-       },
-       {
-       .callback = video_detect_force_vendor,
-       .ident = "Lenovo Yoga 13",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-               DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
-               },
-       },
        { },
 };
 
index 4e737728aee207a5d644d6fa0d39b0e3c402bd47..868429a47be41a2c50ff146389df25dfcb8f5b30 100644 (file)
@@ -247,6 +247,7 @@ config SATA_HIGHBANK
 
 config SATA_MV
        tristate "Marvell SATA support"
+       select GENERIC_PHY
        help
          This option enables support for the Marvell Serial ATA family.
          Currently supports 88SX[56]0[48][01] PCI(-X) chips,
index dc2756fb6f3369b95cdb015fb8b32f97ff64d887..c81d809c111b238e72f65d185add59f5bef4fade 100644 (file)
@@ -61,6 +61,7 @@ enum board_ids {
        /* board IDs by feature in alphabetical order */
        board_ahci,
        board_ahci_ign_iferr,
+       board_ahci_noncq,
        board_ahci_nosntf,
        board_ahci_yes_fbs,
 
@@ -121,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
+       [board_ahci_noncq] = {
+               AHCI_HFLAGS     (AHCI_HFLAG_NO_NCQ),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
        [board_ahci_nosntf] = {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_SNTF),
                .flags          = AHCI_FLAG_COMMON,
@@ -452,6 +460,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },   /* ASM1061 */
        { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
+       /*
+        * Samsung SSDs found on some macbooks.  NCQ times out.
+        * https://bugzilla.kernel.org/show_bug.cgi?id=60731
+        */
+       { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq },
+
        /* Enmotus */
        { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
 
@@ -1170,8 +1184,10 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
 
        nvec = rc;
        rc = pci_enable_msi_block(pdev, nvec);
-       if (rc)
+       if (rc < 0)
                goto intx;
+       else if (rc > 0)
+               goto single_msi;
 
        return nvec;
 
index 20fd337a57314a2928c9208bf706ffabed0c4dd5..7ccc084bf1dfb8f7b979f5e7ae777e030303d1b8 100644 (file)
@@ -447,8 +447,11 @@ static void sata_pmp_quirks(struct ata_port *ap)
                 * otherwise.  Don't try hard to recover it.
                 */
                ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
-       } else if (vendor == 0x197b && devid == 0x2352) {
-               /* chip found in Thermaltake BlackX Duet, jmicron JMB350? */
+       } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
+               /*
+                * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
+                * 0x0325: jmicron JMB394.
+                */
                ata_for_each_link(link, ap, EDGE) {
                        /* SRST breaks detection and disks get misclassified
                         * LPM disabled to avoid potential problems
index 26386f0b89a8f4583c397ca9da154a9c499c6d2f..b0b18ec5465ffe32bae62d11f97d1b0cba8c313c 100644 (file)
@@ -119,7 +119,9 @@ static int pata_imx_probe(struct platform_device *pdev)
                return PTR_ERR(priv->clk);
        }
 
-       clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        host = ata_host_alloc(&pdev->dev, 1);
        if (!host) {
@@ -212,7 +214,9 @@ static int pata_imx_resume(struct device *dev)
        struct ata_host *host = dev_get_drvdata(dev);
        struct pata_imx_priv *priv = host->private_data;
 
-       clk_prepare_enable(priv->clk);
+       int ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        __raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL);
 
index 52b8181ddafd98cbfb550b3f082062280feec6d2..05c8a44adf8edea590ec983a7f843c1f5b6b1b55 100644 (file)
@@ -4104,7 +4104,6 @@ static int mv_platform_probe(struct platform_device *pdev)
        if (!hpriv->port_phys)
                return -ENOMEM;
        host->private_data = hpriv;
-       hpriv->n_ports = n_ports;
        hpriv->board_idx = chip_soc;
 
        host->iomap = NULL;
@@ -4132,13 +4131,18 @@ static int mv_platform_probe(struct platform_device *pdev)
                        rc = PTR_ERR(hpriv->port_phys[port]);
                        hpriv->port_phys[port] = NULL;
                        if (rc != -EPROBE_DEFER)
-                               dev_warn(&pdev->dev, "error getting phy %d",
-                                       rc);
+                               dev_warn(&pdev->dev, "error getting phy %d", rc);
+
+                       /* Cleanup only the initialized ports */
+                       hpriv->n_ports = port;
                        goto err;
                } else
                        phy_power_on(hpriv->port_phys[port]);
        }
 
+       /* All the ports have been initialized */
+       hpriv->n_ports = n_ports;
+
        /*
         * (Re-)program MBUS remapping windows if we are asked to.
         */
@@ -4176,7 +4180,7 @@ err:
                clk_disable_unprepare(hpriv->clk);
                clk_put(hpriv->clk);
        }
-       for (port = 0; port < n_ports; port++) {
+       for (port = 0; port < hpriv->n_ports; port++) {
                if (!IS_ERR(hpriv->port_clks[port])) {
                        clk_disable_unprepare(hpriv->port_clks[port]);
                        clk_put(hpriv->port_clks[port]);
index d67fc351343ca841f7ea95b68e401f52f58953c2..b7695e804635b87c0d7c787be1d900facaa68963 100644 (file)
@@ -157,6 +157,7 @@ static const struct sil_drivelist {
        { "ST380011ASL",        SIL_QUIRK_MOD15WRITE },
        { "ST3120022ASL",       SIL_QUIRK_MOD15WRITE },
        { "ST3160021ASL",       SIL_QUIRK_MOD15WRITE },
+       { "TOSHIBA MK2561GSYN", SIL_QUIRK_MOD15WRITE },
        { "Maxtor 4D060H3",     SIL_QUIRK_UDMA5MAX },
        { }
 };
index 1e16cbd61da27877bf372cc90f1323d950676db2..61d6d62cc0d35ff17d6e9736d9704ad3848e22a1 100644 (file)
@@ -616,36 +616,35 @@ static int dma_buf_describe(struct seq_file *s)
        if (ret)
                return ret;
 
-       seq_printf(s, "\nDma-buf Objects:\n");
-       seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n");
+       seq_puts(s, "\nDma-buf Objects:\n");
+       seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
 
        list_for_each_entry(buf_obj, &db_list.head, list_node) {
                ret = mutex_lock_interruptible(&buf_obj->lock);
 
                if (ret) {
-                       seq_printf(s,
-                                 "\tERROR locking buffer object: skipping\n");
+                       seq_puts(s,
+                                "\tERROR locking buffer object: skipping\n");
                        continue;
                }
 
-               seq_printf(s, "\t");
-
-               seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n",
-                               buf_obj->exp_name, buf_obj->size,
+               seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n",
+                               buf_obj->size,
                                buf_obj->file->f_flags, buf_obj->file->f_mode,
-                               (long)(buf_obj->file->f_count.counter));
+                               (long)(buf_obj->file->f_count.counter),
+                               buf_obj->exp_name);
 
-               seq_printf(s, "\t\tAttached Devices:\n");
+               seq_puts(s, "\tAttached Devices:\n");
                attach_count = 0;
 
                list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
-                       seq_printf(s, "\t\t");
+                       seq_puts(s, "\t");
 
-                       seq_printf(s, "%s\n", attach_obj->dev->init_name);
+                       seq_printf(s, "%s\n", dev_name(attach_obj->dev));
                        attach_count++;
                }
 
-               seq_printf(s, "\n\t\tTotal %d devices attached\n",
+               seq_printf(s, "Total %d devices attached\n\n",
                                attach_count);
 
                count++;
index 8a97ddfa61222db79506dcecebc619ab5a333865..c30df50e4440c3af5639af58dd567c37e8bf40e6 100644 (file)
@@ -1580,6 +1580,7 @@ static int fw_pm_notify(struct notifier_block *notify_block,
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
+       case PM_RESTORE_PREPARE:
                kill_requests_without_uevent();
                device_cache_fw_images();
                break;
index 08ca8c9f41cdeb27f6e4bb4879b2912798e1a72e..cb003a6b72c86f10f31afd0d7b3c156308f95acc 100644 (file)
@@ -1323,8 +1323,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
        up_read(&policy->rwsem);
 
        if (cpu != policy->cpu) {
-               if (!frozen)
-                       sysfs_remove_link(&dev->kobj, "cpufreq");
+               sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
                new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
                if (new_cpu >= 0) {
index c788abf1c457cea63c1b60b7bbff637e5b303228..2cd36b9297f3de01a4b5f2ed246d738e123d7991 100644 (file)
 
 #define SAMPLE_COUNT           3
 
-#define BYT_RATIOS     0x66a
-#define BYT_VIDS        0x66b
+#define BYT_RATIOS             0x66a
+#define BYT_VIDS               0x66b
+#define BYT_TURBO_RATIOS       0x66c
 
-#define FRAC_BITS 8
+
+#define FRAC_BITS 6
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
+#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS)
 
 static inline int32_t mul_fp(int32_t x, int32_t y)
 {
@@ -357,7 +360,7 @@ static int byt_get_min_pstate(void)
 {
        u64 value;
        rdmsrl(BYT_RATIOS, value);
-       return value & 0xFF;
+       return (value >> 8) & 0xFF;
 }
 
 static int byt_get_max_pstate(void)
@@ -367,6 +370,13 @@ static int byt_get_max_pstate(void)
        return (value >> 16) & 0xFF;
 }
 
+static int byt_get_turbo_pstate(void)
+{
+       u64 value;
+       rdmsrl(BYT_TURBO_RATIOS, value);
+       return value & 0x3F;
+}
+
 static void byt_set_pstate(struct cpudata *cpudata, int pstate)
 {
        u64 val;
@@ -469,7 +479,7 @@ static struct cpu_defaults byt_params = {
        .funcs = {
                .get_max = byt_get_max_pstate,
                .get_min = byt_get_min_pstate,
-               .get_turbo = byt_get_max_pstate,
+               .get_turbo = byt_get_turbo_pstate,
                .set = byt_set_pstate,
                .get_vid = byt_get_vid,
        },
@@ -547,18 +557,20 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 static inline void intel_pstate_calc_busy(struct cpudata *cpu,
                                        struct sample *sample)
 {
-       u64 core_pct;
-       u64 c0_pct;
+       int32_t core_pct;
+       int32_t c0_pct;
 
-       core_pct = div64_u64(sample->aperf * 100, sample->mperf);
+       core_pct = div_fp(int_tofp((sample->aperf)),
+                       int_tofp((sample->mperf)));
+       core_pct = mul_fp(core_pct, int_tofp(100));
+       FP_ROUNDUP(core_pct);
+
+       c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc));
 
-       c0_pct = div64_u64(sample->mperf * 100, sample->tsc);
        sample->freq = fp_toint(
-               mul_fp(int_tofp(cpu->pstate.max_pstate),
-                       int_tofp(core_pct * 1000)));
+               mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
 
-       sample->core_pct_busy = mul_fp(int_tofp(core_pct),
-                               div_fp(int_tofp(c0_pct + 1), int_tofp(100)));
+       sample->core_pct_busy = mul_fp(core_pct, c0_pct);
 }
 
 static inline void intel_pstate_sample(struct cpudata *cpu)
@@ -570,6 +582,10 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
        rdmsrl(MSR_IA32_MPERF, mperf);
        tsc = native_read_tsc();
 
+       aperf = aperf >> FRAC_BITS;
+       mperf = mperf >> FRAC_BITS;
+       tsc = tsc >> FRAC_BITS;
+
        cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
        cpu->samples[cpu->sample_ptr].aperf = aperf;
        cpu->samples[cpu->sample_ptr].mperf = mperf;
@@ -601,7 +617,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
        core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy;
        max_pstate = int_tofp(cpu->pstate.max_pstate);
        current_pstate = int_tofp(cpu->pstate.current_pstate);
-       return mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+       core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+       return FP_ROUNDUP(core_busy);
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
index e10b646634d77ff3a4bcf0c54d154a91c7c35805..6684e0342792517577fde32d56542b3ad84d15af 100644 (file)
@@ -1076,7 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
        struct powernow_k8_data *data;
        struct init_on_cpu init_on_cpu;
-       int rc;
+       int rc, cpu;
 
        smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
        if (rc)
@@ -1140,7 +1140,9 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
        pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
                 data->currfid, data->currvid);
 
-       per_cpu(powernow_data, pol->cpu) = data;
+       /* Point all the CPUs in this policy to the same data */
+       for_each_cpu(cpu, pol->cpus)
+               per_cpu(powernow_data, cpu) = data;
 
        return 0;
 
@@ -1155,6 +1157,7 @@ err_out:
 static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 {
        struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+       int cpu;
 
        if (!data)
                return -EINVAL;
@@ -1165,7 +1168,8 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 
        kfree(data->powernow_table);
        kfree(data);
-       per_cpu(powernow_data, pol->cpu) = NULL;
+       for_each_cpu(cpu, pol->cpus)
+               per_cpu(powernow_data, cpu) = NULL;
 
        return 0;
 }
index 4e7918339b1263a2720c3da11d271714dd9669ad..19041cefabb1c0ce8649ed8cf5ea41707fa7824f 100644 (file)
@@ -449,6 +449,7 @@ static const struct of_device_id sdma_dt_ids[] = {
        { .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, },
        { .compatible = "fsl,imx35-sdma", .data = &sdma_imx35, },
        { .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, },
+       { .compatible = "fsl,imx25-sdma", .data = &sdma_imx25, },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sdma_dt_ids);
index 87529181efccb9851467cc04be04bd91fecb15b3..4e3549a161324f29159775312b3c9d8075914359 100644 (file)
@@ -77,7 +77,8 @@ static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)
        attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
        for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
                chan = ioat_chan_by_index(instance, bit);
-               tasklet_schedule(&chan->cleanup_task);
+               if (test_bit(IOAT_RUN, &chan->state))
+                       tasklet_schedule(&chan->cleanup_task);
        }
 
        writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
@@ -93,7 +94,8 @@ static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data)
 {
        struct ioat_chan_common *chan = data;
 
-       tasklet_schedule(&chan->cleanup_task);
+       if (test_bit(IOAT_RUN, &chan->state))
+               tasklet_schedule(&chan->cleanup_task);
 
        return IRQ_HANDLED;
 }
@@ -116,7 +118,6 @@ void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *c
        chan->timer.function = device->timer_fn;
        chan->timer.data = data;
        tasklet_init(&chan->cleanup_task, device->cleanup_fn, data);
-       tasklet_disable(&chan->cleanup_task);
 }
 
 /**
@@ -354,13 +355,49 @@ static int ioat1_dma_alloc_chan_resources(struct dma_chan *c)
        writel(((u64) chan->completion_dma) >> 32,
               chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
-       tasklet_enable(&chan->cleanup_task);
+       set_bit(IOAT_RUN, &chan->state);
        ioat1_dma_start_null_desc(ioat);  /* give chain to dma device */
        dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n",
                __func__, ioat->desccount);
        return ioat->desccount;
 }
 
+void ioat_stop(struct ioat_chan_common *chan)
+{
+       struct ioatdma_device *device = chan->device;
+       struct pci_dev *pdev = device->pdev;
+       int chan_id = chan_num(chan);
+       struct msix_entry *msix;
+
+       /* 1/ stop irq from firing tasklets
+        * 2/ stop the tasklet from re-arming irqs
+        */
+       clear_bit(IOAT_RUN, &chan->state);
+
+       /* flush inflight interrupts */
+       switch (device->irq_mode) {
+       case IOAT_MSIX:
+               msix = &device->msix_entries[chan_id];
+               synchronize_irq(msix->vector);
+               break;
+       case IOAT_MSI:
+       case IOAT_INTX:
+               synchronize_irq(pdev->irq);
+               break;
+       default:
+               break;
+       }
+
+       /* flush inflight timers */
+       del_timer_sync(&chan->timer);
+
+       /* flush inflight tasklet runs */
+       tasklet_kill(&chan->cleanup_task);
+
+       /* final cleanup now that everything is quiesced and can't re-arm */
+       device->cleanup_fn((unsigned long) &chan->common);
+}
+
 /**
  * ioat1_dma_free_chan_resources - release all the descriptors
  * @chan: the channel to be cleaned
@@ -379,9 +416,7 @@ static void ioat1_dma_free_chan_resources(struct dma_chan *c)
        if (ioat->desccount == 0)
                return;
 
-       tasklet_disable(&chan->cleanup_task);
-       del_timer_sync(&chan->timer);
-       ioat1_cleanup(ioat);
+       ioat_stop(chan);
 
        /* Delay 100ms after reset to allow internal DMA logic to quiesce
         * before removing DMA descriptor resources.
@@ -526,8 +561,11 @@ ioat1_dma_prep_memcpy(struct dma_chan *c, dma_addr_t dma_dest,
 static void ioat1_cleanup_event(unsigned long data)
 {
        struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
+       struct ioat_chan_common *chan = &ioat->base;
 
        ioat1_cleanup(ioat);
+       if (!test_bit(IOAT_RUN, &chan->state))
+               return;
        writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
index 11fb877ddca9a9b0888d23952dea8fb48245b617..e982f00a984399a3838f7b47ef2e21a2aab84495 100644 (file)
@@ -356,6 +356,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
 int ioat_dma_setup_interrupts(struct ioatdma_device *device);
+void ioat_stop(struct ioat_chan_common *chan);
 extern const struct sysfs_ops ioat_sysfs_ops;
 extern struct ioat_sysfs_entry ioat_version_attr;
 extern struct ioat_sysfs_entry ioat_cap_attr;
index 5d3affe7e976165ec5576ac8c6551dd438af7786..8d1058085eeb85beb3fb2d6ab88c57160ef0cf15 100644 (file)
@@ -190,8 +190,11 @@ static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
 void ioat2_cleanup_event(unsigned long data)
 {
        struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+       struct ioat_chan_common *chan = &ioat->base;
 
        ioat2_cleanup(ioat);
+       if (!test_bit(IOAT_RUN, &chan->state))
+               return;
        writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
@@ -553,10 +556,10 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
        ioat->issued = 0;
        ioat->tail = 0;
        ioat->alloc_order = order;
+       set_bit(IOAT_RUN, &chan->state);
        spin_unlock_bh(&ioat->prep_lock);
        spin_unlock_bh(&chan->cleanup_lock);
 
-       tasklet_enable(&chan->cleanup_task);
        ioat2_start_null_desc(ioat);
 
        /* check that we got off the ground */
@@ -566,7 +569,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
        } while (i++ < 20 && !is_ioat_active(status) && !is_ioat_idle(status));
 
        if (is_ioat_active(status) || is_ioat_idle(status)) {
-               set_bit(IOAT_RUN, &chan->state);
                return 1 << ioat->alloc_order;
        } else {
                u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
@@ -809,11 +811,8 @@ void ioat2_free_chan_resources(struct dma_chan *c)
        if (!ioat->ring)
                return;
 
-       tasklet_disable(&chan->cleanup_task);
-       del_timer_sync(&chan->timer);
-       device->cleanup_fn((unsigned long) c);
+       ioat_stop(chan);
        device->reset_hw(chan);
-       clear_bit(IOAT_RUN, &chan->state);
 
        spin_lock_bh(&chan->cleanup_lock);
        spin_lock_bh(&ioat->prep_lock);
index 820817e97e626a498561a9e5f0f3a61f22ffc9fa..b9b38a1cf92fbdc4147e70af93508f0d9caf6867 100644 (file)
@@ -464,8 +464,11 @@ static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
 static void ioat3_cleanup_event(unsigned long data)
 {
        struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+       struct ioat_chan_common *chan = &ioat->base;
 
        ioat3_cleanup(ioat);
+       if (!test_bit(IOAT_RUN, &chan->state))
+               return;
        writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
index 00a2de957b234da060fe5e03592b171f50fa53d1..bf18c786ed40fbaae2a487246df5da85457fbec1 100644 (file)
@@ -1641,6 +1641,7 @@ static void dma_tasklet(unsigned long data)
        struct d40_chan *d40c = (struct d40_chan *) data;
        struct d40_desc *d40d;
        unsigned long flags;
+       bool callback_active;
        dma_async_tx_callback callback;
        void *callback_param;
 
@@ -1668,6 +1669,7 @@ static void dma_tasklet(unsigned long data)
        }
 
        /* Callback to client */
+       callback_active = !!(d40d->txd.flags & DMA_PREP_INTERRUPT);
        callback = d40d->txd.callback;
        callback_param = d40d->txd.callback_param;
 
@@ -1690,7 +1692,7 @@ static void dma_tasklet(unsigned long data)
 
        spin_unlock_irqrestore(&d40c->lock, flags);
 
-       if (callback && (d40d->txd.flags & DMA_PREP_INTERRUPT))
+       if (callback_active && callback)
                callback(callback_param);
 
        return;
index d63f4798f7d09127872f97ed925a5af64a75f81f..57e96a3350f0595ab002a5ff1285d85b44dd6e3f 100644 (file)
@@ -943,33 +943,35 @@ static int i7300_get_devices(struct mem_ctl_info *mci)
 
        /* Attempt to 'get' the MCH register we want */
        pdev = NULL;
-       while (!pvt->pci_dev_16_1_fsb_addr_map ||
-              !pvt->pci_dev_16_2_fsb_err_regs) {
-               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                     PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev);
-               if (!pdev) {
-                       /* End of list, leave */
-                       i7300_printk(KERN_ERR,
-                               "'system address,Process Bus' "
-                               "device not found:"
-                               "vendor 0x%x device 0x%x ERR funcs "
-                               "(broken BIOS?)\n",
-                               PCI_VENDOR_ID_INTEL,
-                               PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
-                       goto error;
-               }
-
+       while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_I7300_MCH_ERR,
+                                     pdev))) {
                /* Store device 16 funcs 1 and 2 */
                switch (PCI_FUNC(pdev->devfn)) {
                case 1:
-                       pvt->pci_dev_16_1_fsb_addr_map = pdev;
+                       if (!pvt->pci_dev_16_1_fsb_addr_map)
+                               pvt->pci_dev_16_1_fsb_addr_map =
+                                                       pci_dev_get(pdev);
                        break;
                case 2:
-                       pvt->pci_dev_16_2_fsb_err_regs = pdev;
+                       if (!pvt->pci_dev_16_2_fsb_err_regs)
+                               pvt->pci_dev_16_2_fsb_err_regs =
+                                                       pci_dev_get(pdev);
                        break;
                }
        }
 
+       if (!pvt->pci_dev_16_1_fsb_addr_map ||
+           !pvt->pci_dev_16_2_fsb_err_regs) {
+               /* At least one device was not found */
+               i7300_printk(KERN_ERR,
+                       "'system address,Process Bus' device not found:"
+                       "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n",
+                       PCI_VENDOR_ID_INTEL,
+                       PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
+               goto error;
+       }
+
        edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
                 pci_name(pvt->pci_dev_16_0_fsb_ctlr),
                 pvt->pci_dev_16_0_fsb_ctlr->vendor,
index 87533ca7752e0105683210913f83731a9b988aab..d871275196f6f04b6542e4941ee433e41fcfdf64 100644 (file)
@@ -1334,14 +1334,19 @@ static int i7core_get_onedevice(struct pci_dev **prev,
         * is at addr 8086:2c40, instead of 8086:2c41. So, we need
         * to probe for the alternate address in case of failure
         */
-       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) {
+               pci_dev_get(*prev);     /* pci_get_device will put it */
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+       }
 
-       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE &&
+           !pdev) {
+               pci_dev_get(*prev);     /* pci_get_device will put it */
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
                                      *prev);
+       }
 
        if (!pdev) {
                if (*prev) {
index c20602f601ee22732635aa3fa04fe94e44ed6020..98a14f6143a7087accee9c5d2b127c99c300b81d 100644 (file)
@@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
        struct snd_soc_dapm_context *dapm = arizona->dapm;
        int ret;
 
-       mutex_lock(&dapm->card->dapm_mutex);
-
        ret = snd_soc_dapm_force_enable_pin(dapm, widget);
        if (ret != 0)
                dev_warn(arizona->dev, "Failed to enable %s: %d\n",
                         widget, ret);
 
-       mutex_unlock(&dapm->card->dapm_mutex);
-
        snd_soc_dapm_sync(dapm);
 
        if (!arizona->pdata.micd_force_micbias) {
-               mutex_lock(&dapm->card->dapm_mutex);
-
                ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
                if (ret != 0)
                        dev_warn(arizona->dev, "Failed to disable %s: %d\n",
                                 widget, ret);
 
-               mutex_unlock(&dapm->card->dapm_mutex);
-
                snd_soc_dapm_sync(dapm);
        }
 }
@@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
                                 ARIZONA_MICD_ENA, 0,
                                 &change);
 
-       mutex_lock(&dapm->card->dapm_mutex);
-
        ret = snd_soc_dapm_disable_pin(dapm, widget);
        if (ret != 0)
                dev_warn(arizona->dev,
                         "Failed to disable %s: %d\n",
                         widget, ret);
 
-       mutex_unlock(&dapm->card->dapm_mutex);
-
        snd_soc_dapm_sync(dapm);
 
        if (info->micd_reva) {
index ee5b47904130bdaab802fb3ddb6bce0f5f73c215..9bb2cbd5c9f265e421ded04a69b72f37141a2663 100644 (file)
@@ -27,7 +27,7 @@ FMC_PARAM_BUSID(fwe_drv);
 /* The "file=" is like the generic "gateware=" used elsewhere */
 static char *fwe_file[FMC_MAX_CARDS];
 static int fwe_file_n;
-module_param_array_named(file, fwe_file, charp, &fwe_file_n, 444);
+module_param_array_named(file, fwe_file, charp, &fwe_file_n, 0444);
 
 static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw,
        int write)
index dffc836144cc96266a616902aa457b46c0ef1b33..f4dc9b7a3831f32d43f0e53cd8ed9791cac665ad 100644 (file)
@@ -296,6 +296,18 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
        case DRM_CAP_ASYNC_PAGE_FLIP:
                req->value = dev->mode_config.async_page_flip;
                break;
+       case DRM_CAP_CURSOR_WIDTH:
+               if (dev->mode_config.cursor_width)
+                       req->value = dev->mode_config.cursor_width;
+               else
+                       req->value = 64;
+               break;
+       case DRM_CAP_CURSOR_HEIGHT:
+               if (dev->mode_config.cursor_height)
+                       req->value = dev->mode_config.cursor_height;
+               else
+                       req->value = 64;
+               break;
        default:
                return -EINVAL;
        }
index fa18cf37447037fc8545719880a2abd91a2c9248..faa77f543a077da2c624e47638693b6566b146ff 100644 (file)
@@ -1151,8 +1151,10 @@ tda998x_encoder_init(struct i2c_client *client,
 
        priv->current_page = 0xff;
        priv->cec = i2c_new_dummy(client->adapter, 0x34);
-       if (!priv->cec)
+       if (!priv->cec) {
+               kfree(priv);
                return -ENODEV;
+       }
        priv->dpms = DRM_MODE_DPMS_OFF;
 
        encoder_slave->slave_priv = priv;
index 9fa24347963a38d360e365cfa20bf7cefed8beaa..4c1672809493c795714bc3eddaa1238c258451ed 100644 (file)
@@ -8586,6 +8586,20 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
        if (ring->id == RCS)
                len += 6;
 
+       /*
+        * BSpec MI_DISPLAY_FLIP for IVB:
+        * "The full packet must be contained within the same cache line."
+        *
+        * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
+        * cacheline, if we ever start emitting more commands before
+        * the MI_DISPLAY_FLIP we may need to first emit everything else,
+        * then do the cacheline alignment, and finally emit the
+        * MI_DISPLAY_FLIP.
+        */
+       ret = intel_ring_cacheline_align(ring);
+       if (ret)
+               goto err_unpin;
+
        ret = intel_ring_begin(ring, len);
        if (ret)
                goto err_unpin;
index 2f517b85b3f491b4eee244c0cf0a3e4e7679a18c..57552eb386b0b1b6d735a7fb0f9b770405e5f411 100644 (file)
@@ -537,6 +537,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
        uint8_t msg[20];
        int msg_bytes;
        uint8_t ack;
+       int retry;
 
        if (WARN_ON(send_bytes > 16))
                return -E2BIG;
@@ -548,19 +549,21 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
        msg[3] = send_bytes - 1;
        memcpy(&msg[4], send, send_bytes);
        msg_bytes = send_bytes + 4;
-       for (;;) {
+       for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
                ack >>= 4;
                if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-                       break;
+                       return send_bytes;
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(100);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
-       return send_bytes;
+
+       DRM_ERROR("too many retries, giving up\n");
+       return -EIO;
 }
 
 /* Write a single byte to the aux channel in native mode */
@@ -582,6 +585,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
        int reply_bytes;
        uint8_t ack;
        int ret;
+       int retry;
 
        if (WARN_ON(recv_bytes > 19))
                return -E2BIG;
@@ -595,7 +599,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
        msg_bytes = 4;
        reply_bytes = recv_bytes + 1;
 
-       for (;;) {
+       for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
                                      reply, reply_bytes);
                if (ret == 0)
@@ -608,10 +612,13 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
                        return ret - 1;
                }
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(100);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
+
+       DRM_ERROR("too many retries, giving up\n");
+       return -EIO;
 }
 
 static int
index b7f1742caf878250c3fb6dc98b5bdbe63ae4a601..31b36c5ac8941e844cd9f995b0c4e575219fc8ea 100644 (file)
@@ -1653,6 +1653,27 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
        return 0;
 }
 
+/* Align the ring tail to a cacheline boundary */
+int intel_ring_cacheline_align(struct intel_ring_buffer *ring)
+{
+       int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t);
+       int ret;
+
+       if (num_dwords == 0)
+               return 0;
+
+       ret = intel_ring_begin(ring, num_dwords);
+       if (ret)
+               return ret;
+
+       while (num_dwords--)
+               intel_ring_emit(ring, MI_NOOP);
+
+       intel_ring_advance(ring);
+
+       return 0;
+}
+
 void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
 {
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
index 71a73f4fe252fdb90b4c24d8947e936b37ad0f5b..0b243ce337147d51f7e9cb4b09d774f4cc33e856 100644 (file)
@@ -233,6 +233,7 @@ intel_write_status_page(struct intel_ring_buffer *ring,
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 
 int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
+int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring);
 static inline void intel_ring_emit(struct intel_ring_buffer *ring,
                                   u32 data)
 {
index e88145ba1bf515429a3b85753bde5df7d28bde70..d310c195bdfed1d467abbd1f5933da703e207e13 100644 (file)
@@ -141,6 +141,7 @@ nouveau-y += core/subdev/mc/base.o
 nouveau-y += core/subdev/mc/nv04.o
 nouveau-y += core/subdev/mc/nv40.o
 nouveau-y += core/subdev/mc/nv44.o
+nouveau-y += core/subdev/mc/nv4c.o
 nouveau-y += core/subdev/mc/nv50.o
 nouveau-y += core/subdev/mc/nv94.o
 nouveau-y += core/subdev/mc/nv98.o
index 1b653dd74a7046ceaae41bca181f3097827dcccd..08b88591ed6036924c76d51efcf0d1d32c91210e 100644 (file)
@@ -311,7 +311,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -334,7 +334,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
@@ -357,7 +357,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -380,7 +380,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -403,7 +403,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
index 940eaa5d8b9a4bb0e3ea224cfe2ced8ec8585b44..9ad722e4e087007df76e77473c5a5f98ce24be74 100644 (file)
@@ -1142,7 +1142,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
        if (conf != ~0) {
                if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
                        u32 soff = (ffs(outp.or) - 1) * 0x08;
-                       u32 ctrl = nv_rd32(priv, 0x610798 + soff);
+                       u32 ctrl = nv_rd32(priv, 0x610794 + soff);
                        u32 datarate;
 
                        switch ((ctrl & 0x000f0000) >> 16) {
index 9a850fe19515fe2ddcd513c3497c7d87c86cba8a..54c1b5b471cdfa5682a83587a1d490455d6828c1 100644 (file)
@@ -112,7 +112,7 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
 
        nv_wr32(priv, 0x002270, cur->addr >> 12);
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
-       if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
+       if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000))
                nv_error(priv, "runlist %d update timeout\n", engine);
        mutex_unlock(&nv_subdev(priv)->mutex);
 }
index 30ed19c52e05ca0cd6a1e759a8fc426f61f246a7..7a367c4029786f9d3b0941b62d697902b3681e93 100644 (file)
@@ -539,7 +539,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
                                ustatus &= ~0x04030000;
                        }
                        if (ustatus && display) {
-                               nv_error("%s - TP%d:", name, i);
+                               nv_error(priv, "%s - TP%d:", name, i);
                                nouveau_bitfield_print(nv50_mpc_traps, ustatus);
                                pr_cont("\n");
                                ustatus = 0;
index adc88b73d9118e4b7d50ed21209675fbc47a8820..3c6738edd127040337ff8fc53b6125a47e812ad7 100644 (file)
@@ -47,6 +47,7 @@ struct nouveau_mc_oclass {
 extern struct nouveau_oclass *nv04_mc_oclass;
 extern struct nouveau_oclass *nv40_mc_oclass;
 extern struct nouveau_oclass *nv44_mc_oclass;
+extern struct nouveau_oclass *nv4c_mc_oclass;
 extern struct nouveau_oclass *nv50_mc_oclass;
 extern struct nouveau_oclass *nv94_mc_oclass;
 extern struct nouveau_oclass *nv98_mc_oclass;
index aa0fbbec7f08212cd8b3106ecb57ec4ff491403b..ef0c9c4a8cc3925f9f8df1279417fc028a39f2f9 100644 (file)
@@ -130,6 +130,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
        u16 pcir;
        int i;
 
+       /* there is no prom on nv4x IGP's */
+       if (device->card_type == NV_40 && device->chipset >= 0x4c)
+               return;
+
        /* enable access to rom */
        if (device->card_type >= NV_50)
                pcireg = 0x088050;
index 9159a5ccee930d21172884bf9f23972c222669b5..265d1253624a337d7ebf8604a9ca1207113ee1cf 100644 (file)
@@ -36,7 +36,7 @@ nv1a_fb_oclass = &(struct nv04_fb_impl) {
                .fini = _nouveau_fb_fini,
        },
        .base.memtype = nv04_fb_memtype_valid,
-       .base.ram = &nv10_ram_oclass,
+       .base.ram = &nv1a_ram_oclass,
        .tile.regions = 8,
        .tile.init = nv10_fb_tile_init,
        .tile.fini = nv10_fb_tile_fini,
index b0d5c31606c1c50e0686f1aa000c8dc2876062c2..81a408e7d034636f6b940107839394b9a03b0cab 100644 (file)
@@ -14,6 +14,7 @@ int  nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *,
 extern const struct nouveau_mc_intr nv04_mc_intr[];
 int  nv04_mc_init(struct nouveau_object *);
 void nv40_mc_msi_rearm(struct nouveau_mc *);
+int  nv44_mc_init(struct nouveau_object *object);
 int  nv50_mc_init(struct nouveau_object *);
 extern const struct nouveau_mc_intr nv50_mc_intr[];
 extern const struct nouveau_mc_intr nvc0_mc_intr[];
index 3bfee5c6c4f21e3bd25430bb693e5d634c86773a..cc4d0d2d886e679612ca269459b4cc756cc5ab31 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "nv04.h"
 
-static int
+int
 nv44_mc_init(struct nouveau_object *object)
 {
        struct nv04_mc_priv *priv = (void *)object;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
new file mode 100644 (file)
index 0000000..a75c35c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Ilia Mirkin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ilia Mirkin
+ */
+
+#include "nv04.h"
+
+static void
+nv4c_mc_msi_rearm(struct nouveau_mc *pmc)
+{
+       struct nv04_mc_priv *priv = (void *)pmc;
+       nv_wr08(priv, 0x088050, 0xff);
+}
+
+struct nouveau_oclass *
+nv4c_mc_oclass = &(struct nouveau_mc_oclass) {
+       .base.handle = NV_SUBDEV(MC, 0x4c),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_mc_ctor,
+               .dtor = _nouveau_mc_dtor,
+               .init = nv44_mc_init,
+               .fini = _nouveau_mc_fini,
+       },
+       .intr = nv04_mc_intr,
+       .msi_rearm = nv4c_mc_msi_rearm,
+}.base;
index 4ef83df2b246fb335dc8ce05bafead80ed7ac180..83face3f608f020f70d7d11dda363c5817102238 100644 (file)
@@ -106,6 +106,29 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *
        return 0;
 }
 
+/*
+ * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special
+ * requirements on the fourth parameter, so a private implementation
+ * instead of using acpi_check_dsm().
+ */
+static int nouveau_check_optimus_dsm(acpi_handle handle)
+{
+       int result;
+
+       /*
+        * Function 0 returns a Buffer containing available functions.
+        * The args parameter is ignored for function 0, so just put 0 in it
+        */
+       if (nouveau_optimus_dsm(handle, 0, 0, &result))
+               return 0;
+
+       /*
+        * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported.
+        * If the n-th bit is enabled, function n is supported
+        */
+       return result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS);
+}
+
 static int nouveau_dsm(acpi_handle handle, int func, int arg)
 {
        int ret = 0;
@@ -207,8 +230,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
                           1 << NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
-       if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100,
-                          1 << NOUVEAU_DSM_OPTIMUS_CAPS))
+       if (nouveau_check_optimus_dsm(dhandle))
                retval |= NOUVEAU_DSM_HAS_OPT;
 
        if (retval & NOUVEAU_DSM_HAS_OPT) {
index 488686d490c0c7a96ba016e0f55a4beffcda6e4f..4aed1714b9ab7d289bbadc867f9af40b046825f2 100644 (file)
@@ -1249,7 +1249,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
                        mem->bus.is_iomem = !dev->agp->cant_use_aperture;
                }
 #endif
-               if (!node->memtype)
+               if (nv_device(drm->device)->card_type < NV_50 || !node->memtype)
                        /* untiled */
                        break;
                /* fallthrough, tiled memory */
index 78c8e7146d56b2c5f7d189e372e542f4d9b43717..89c484d8ac2666d8b3c04bb818cb5eec2665bb38 100644 (file)
@@ -376,6 +376,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto fail_device;
 
+       dev->irq_enabled = true;
+
        /* workaround an odd issue on nvc1 by disabling the device's
         * nosnoop capability.  hopefully won't cause issues until a
         * better fix is found - assuming there is one...
@@ -475,6 +477,7 @@ nouveau_drm_remove(struct pci_dev *pdev)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_object *device;
 
+       dev->irq_enabled = false;
        device = drm->client.base.device;
        drm_put_dev(dev);
 
index 81638d7f2efff69cdce86ac515aac2c19191aefe..471347edc27eb869816e5d5cfed1ccd01f4c7b6f 100644 (file)
@@ -14,7 +14,9 @@ nouveau_vga_set_decode(void *priv, bool state)
 {
        struct nouveau_device *device = nouveau_dev(priv);
 
-       if (device->chipset >= 0x40)
+       if (device->card_type == NV_40 && device->chipset >= 0x4c)
+               nv_wr32(device, 0x088060, state);
+       else if (device->chipset >= 0x40)
                nv_wr32(device, 0x088054, state);
        else
                nv_wr32(device, 0x001854, state);
index a9338c85630fe0548336e8c8c492361ce797dd5a..daa4dd375ab15367266d6f0041af84386d6699bb 100644 (file)
@@ -559,7 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
        u32 adjusted_clock = mode->clock;
        int encoder_mode = atombios_get_encoder_mode(encoder);
        u32 dp_clock = mode->clock;
-       int bpc = radeon_get_monitor_bpc(connector);
+       int bpc = radeon_crtc->bpc;
        bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
 
        /* reset the pll flags */
@@ -1176,7 +1176,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
                /* Set NUM_BANKS. */
-               if (rdev->family >= CHIP_BONAIRE) {
+               if (rdev->family >= CHIP_TAHITI) {
                        unsigned tileb, index, num_banks, tile_split_bytes;
 
                        /* Calculate the macrotile mode index. */
@@ -1194,13 +1194,14 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                                return -EINVAL;
                        }
 
-                       num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       if (rdev->family >= CHIP_BONAIRE)
+                               num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       else
+                               num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;
                        fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
                } else {
-                       /* SI and older. */
-                       if (rdev->family >= CHIP_TAHITI)
-                               tmp = rdev->config.si.tile_config;
-                       else if (rdev->family >= CHIP_CAYMAN)
+                       /* NI and older. */
+                       if (rdev->family >= CHIP_CAYMAN)
                                tmp = rdev->config.cayman.tile_config;
                        else
                                tmp = rdev->config.evergreen.tile_config;
@@ -1773,6 +1774,20 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                        return ATOM_PPLL1;
                DRM_ERROR("unable to allocate a PPLL\n");
                return ATOM_PPLL_INVALID;
+       } else if (ASIC_IS_DCE41(rdev)) {
+               /* Don't share PLLs on DCE4.1 chips */
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+                       if (rdev->clock.dp_extclk)
+                               /* skip PPLL programming if using ext clock */
+                               return ATOM_PPLL_INVALID;
+               }
+               pll_in_use = radeon_get_pll_use_mask(crtc);
+               if (!(pll_in_use & (1 << ATOM_PPLL1)))
+                       return ATOM_PPLL1;
+               if (!(pll_in_use & (1 << ATOM_PPLL2)))
+                       return ATOM_PPLL2;
+               DRM_ERROR("unable to allocate a PPLL\n");
+               return ATOM_PPLL_INVALID;
        } else if (ASIC_IS_DCE4(rdev)) {
                /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
                 * depending on the asic:
@@ -1800,7 +1815,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                                if (pll != ATOM_PPLL_INVALID)
                                        return pll;
                        }
-               } else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */
+               } else {
                        /* use the same PPLL for all monitors with the same clock */
                        pll = radeon_get_shared_nondp_ppll(crtc);
                        if (pll != ATOM_PPLL_INVALID)
index a42d61571f49fa877e6c42564b7edeb9b1e2ef5b..2cec2ab02f80c193ce929393cd3d0c86bdd3d7c9 100644 (file)
@@ -464,11 +464,12 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)
 
 static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
 {
-       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        int bpc = 8;
 
-       if (connector)
-               bpc = radeon_get_monitor_bpc(connector);
+       if (encoder->crtc) {
+               struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+               bpc = radeon_crtc->bpc;
+       }
 
        switch (bpc) {
        case 0:
index 713a5d35990102ea315fa078a93c11d6c1aae1f5..94e85875199481ca46e3c84cef453aaec3970356 100644 (file)
@@ -278,13 +278,15 @@ static int dce6_audio_chipset_supported(struct radeon_device *rdev)
        return !ASIC_IS_NODCE(rdev);
 }
 
-static void dce6_audio_enable(struct radeon_device *rdev,
-                             struct r600_audio_pin *pin,
-                             bool enable)
+void dce6_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable)
 {
+       if (!pin)
+               return;
+
        WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL,
-                       AUDIO_ENABLED);
-       DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
+                       enable ? AUDIO_ENABLED : 0);
 }
 
 static const u32 pin_offsets[7] =
@@ -323,7 +325,8 @@ int dce6_audio_init(struct radeon_device *rdev)
                rdev->audio.pin[i].connected = false;
                rdev->audio.pin[i].offset = pin_offsets[i];
                rdev->audio.pin[i].id = i;
-               dce6_audio_enable(rdev, &rdev->audio.pin[i], true);
+               /* disable audio.  it will be set up later */
+               dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
        }
 
        return 0;
index f2b9e21ce4da063a03004c4705a3662b2e78c437..8a2c010b7dc53b22f0c6ead8dec361c66538a041 100644 (file)
@@ -1680,7 +1680,7 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
        case RADEON_HPD_6:
                if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
                        connected = true;
-                       break;
+               break;
        default:
                break;
        }
@@ -5475,9 +5475,9 @@ void evergreen_fini(struct radeon_device *rdev)
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       evergreen_pcie_gart_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_fini(rdev);
+       evergreen_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
index 0c6d5cef4cf121770c63fcb559bf6cc187640292..05b0c95813fd79ff4c31ade3a90c0ad1880d028d 100644 (file)
@@ -306,6 +306,15 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
                return;
        offset = dig->afmt->offset;
 
+       /* disable audio prior to setting up hw */
+       if (ASIC_IS_DCE6(rdev)) {
+               dig->afmt->pin = dce6_audio_get_pin(rdev);
+               dce6_audio_enable(rdev, dig->afmt->pin, false);
+       } else {
+               dig->afmt->pin = r600_audio_get_pin(rdev);
+               r600_audio_enable(rdev, dig->afmt->pin, false);
+       }
+
        evergreen_audio_set_dto(encoder, mode->clock);
 
        WREG32(HDMI_VBI_PACKET_CONTROL + offset,
@@ -409,12 +418,16 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
        WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
        WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
        WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
+
+       /* enable audio after to setting up hw */
+       if (ASIC_IS_DCE6(rdev))
+               dce6_audio_enable(rdev, dig->afmt->pin, true);
+       else
+               r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
 void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
 {
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
@@ -427,15 +440,6 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!enable && !dig->afmt->enabled)
                return;
 
-       if (enable) {
-               if (ASIC_IS_DCE6(rdev))
-                       dig->afmt->pin = dce6_audio_get_pin(rdev);
-               else
-                       dig->afmt->pin = r600_audio_get_pin(rdev);
-       } else {
-               dig->afmt->pin = NULL;
-       }
-
        dig->afmt->enabled = enable;
 
        DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
index 1217fbcbdcca1521a81a3cf57ff844f743210347..ca814276b07539741b53c167abc1a0bd5105173a 100644 (file)
@@ -2588,7 +2588,7 @@ static int ni_populate_sq_ramping_values(struct radeon_device *rdev,
        if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
                enable_sq_ramping = false;
 
-       if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+       if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
                enable_sq_ramping = false;
 
        for (i = 0; i < state->performance_level_count; i++) {
index 47fc2b88697928b4272a0878927d189762a82000..bffac10c4296b3b4c28d9f7a52322fe51e9ae7c5 100644 (file)
@@ -142,12 +142,15 @@ void r600_audio_update_hdmi(struct work_struct *work)
 }
 
 /* enable the audio stream */
-static void r600_audio_enable(struct radeon_device *rdev,
-                             struct r600_audio_pin *pin,
-                             bool enable)
+void r600_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable)
 {
        u32 value = 0;
 
+       if (!pin)
+               return;
+
        if (ASIC_IS_DCE4(rdev)) {
                if (enable) {
                        value |= 0x81000000; /* Required to enable audio */
@@ -158,7 +161,6 @@ static void r600_audio_enable(struct radeon_device *rdev,
                WREG32_P(R600_AUDIO_ENABLE,
                         enable ? 0x81000000 : 0x0, ~0x81000000);
        }
-       DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
 }
 
 /*
@@ -178,8 +180,8 @@ int r600_audio_init(struct radeon_device *rdev)
        rdev->audio.pin[0].status_bits = 0;
        rdev->audio.pin[0].category_code = 0;
        rdev->audio.pin[0].id = 0;
-
-       r600_audio_enable(rdev, &rdev->audio.pin[0], true);
+       /* disable audio.  it will be set up later */
+       r600_audio_enable(rdev, &rdev->audio.pin[0], false);
 
        return 0;
 }
index 3016fc14f502c49a61c2343c3b2ca877d2590109..85a2bb28aed27699e464edc54a8573c8d1d41b39 100644 (file)
@@ -329,9 +329,6 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
-       /* XXX: setting this register causes hangs on some asics */
-       return;
-
        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
                if (connector->encoder == encoder) {
                        radeon_connector = to_radeon_connector(connector);
@@ -460,6 +457,10 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
                return;
        offset = dig->afmt->offset;
 
+       /* disable audio prior to setting up hw */
+       dig->afmt->pin = r600_audio_get_pin(rdev);
+       r600_audio_enable(rdev, dig->afmt->pin, false);
+
        r600_audio_set_dto(encoder, mode->clock);
 
        WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
@@ -531,6 +532,9 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
        WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
 
        r600_hdmi_audio_workaround(encoder);
+
+       /* enable audio after to setting up hw */
+       r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
 /*
@@ -651,11 +655,6 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!enable && !dig->afmt->enabled)
                return;
 
-       if (enable)
-               dig->afmt->pin = r600_audio_get_pin(rdev);
-       else
-               dig->afmt->pin = NULL;
-
        /* Older chipsets require setting HDMI and routing manually */
        if (!ASIC_IS_DCE3(rdev)) {
                if (enable)
index 4a8ac1cd6b4c65582690e035e026aa6f1b125e00..e887d027b6d01fda8082305d11ff1b27bad06db9 100644 (file)
@@ -135,6 +135,9 @@ extern int radeon_hard_reset;
 /* R600+ */
 #define R600_RING_TYPE_UVD_INDEX       5
 
+/* number of hw syncs before falling back on blocking */
+#define RADEON_NUM_SYNCS                       4
+
 /* hardcode those limit for now */
 #define RADEON_VA_IB_OFFSET                    (1 << 20)
 #define RADEON_VA_RESERVED_SIZE                        (8 << 20)
@@ -554,7 +557,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
 /*
  * Semaphores.
  */
-/* everything here is constant */
 struct radeon_semaphore {
        struct radeon_sa_bo             *sa_bo;
        signed                          waiters;
@@ -2745,6 +2747,12 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
 void r600_audio_update_hdmi(struct work_struct *work);
 struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev);
 struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev);
+void r600_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable);
+void dce6_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable);
 
 /*
  * R600 vram scratch functions
index 485848f889f55c9f4b86bf61bd8c019e2ad96a27..fa9a9c02751ea865251f7854665c3757caa48e00 100644 (file)
@@ -219,7 +219,8 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
        memcpy(&output, info->buffer.pointer, size);
 
        /* TODO: check version? */
-       printk("ATPX version %u\n", output.version);
+       printk("ATPX version %u, functions 0x%08x\n",
+              output.version, output.function_bits);
 
        radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
 
index d680608f6f5bc9a80e879b4f24769f8a9ffb1e8c..fbd8b930f2bec75276a5baf781653e658a023eaa 100644 (file)
@@ -571,6 +571,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
                radeon_crtc->max_cursor_width = CURSOR_WIDTH;
                radeon_crtc->max_cursor_height = CURSOR_HEIGHT;
        }
+       dev->mode_config.cursor_width = radeon_crtc->max_cursor_width;
+       dev->mode_config.cursor_height = radeon_crtc->max_cursor_height;
 
 #if 0
        radeon_crtc->mode_set.crtc = &radeon_crtc->base;
index 114d1672d616d0b5d7b85ab5d739da66f2db823e..2aecd6dc26109653741bc3671ea4b82136106954 100644 (file)
@@ -537,6 +537,10 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
 
                radeon_vm_init(rdev, &fpriv->vm);
 
+               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+               if (r)
+                       return r;
+
                /* map the ib pool buffer read only into
                 * virtual address space */
                bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
@@ -544,6 +548,8 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
                                          RADEON_VM_PAGE_READABLE |
                                          RADEON_VM_PAGE_SNOOPED);
+
+               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
                if (r) {
                        radeon_vm_fini(rdev, &fpriv->vm);
                        kfree(fpriv);
index 1b783f0e6d3ad084b0a62629a4b5d67c9e92453f..15e44a7281ab96f6b14592ed2e4e840ddae0b74f 100644 (file)
@@ -139,7 +139,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
        }
 
        /* 64 dwords should be enough for fence too */
-       r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8);
+       r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
        if (r) {
                dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
                return r;
index 2b42aa1914f2006dabddee990cd14fc919668d59..9006b32d5eed0433d336ef56e1bfb17c6fffa0de 100644 (file)
 int radeon_semaphore_create(struct radeon_device *rdev,
                            struct radeon_semaphore **semaphore)
 {
+       uint32_t *cpu_addr;
        int i, r;
 
        *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
        if (*semaphore == NULL) {
                return -ENOMEM;
        }
-       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo,
-                            &(*semaphore)->sa_bo, 8, 8, true);
+       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo,
+                            8 * RADEON_NUM_SYNCS, 8, true);
        if (r) {
                kfree(*semaphore);
                *semaphore = NULL;
@@ -49,7 +50,10 @@ int radeon_semaphore_create(struct radeon_device *rdev,
        }
        (*semaphore)->waiters = 0;
        (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo);
-       *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0;
+
+       cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo);
+       for (i = 0; i < RADEON_NUM_SYNCS; ++i)
+               cpu_addr[i] = 0;
 
        for (i = 0; i < RADEON_NUM_RINGS; ++i)
                (*semaphore)->sync_to[i] = NULL;
@@ -125,6 +129,7 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
                                struct radeon_semaphore *semaphore,
                                int ring)
 {
+       unsigned count = 0;
        int i, r;
 
         for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -140,6 +145,12 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
                        return -EINVAL;
                }
 
+               if (++count > RADEON_NUM_SYNCS) {
+                       /* not enough room, wait manually */
+                       radeon_fence_wait_locked(fence);
+                       continue;
+               }
+
                /* allocate enough space for sync command */
                r = radeon_ring_alloc(rdev, &rdev->ring[i], 16);
                if (r) {
@@ -164,6 +175,8 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
 
                radeon_ring_commit(rdev, &rdev->ring[i]);
                radeon_fence_note_sync(fence, ring);
+
+               semaphore->gpu_addr += 8;
        }
 
        return 0;
index 6781fee1eaadc21a68e50de696dd353be0a3e9e5..3e6804b2b2ef748e9727e34817243aa31e7f9210 100644 (file)
@@ -171,6 +171,8 @@ void radeon_uvd_fini(struct radeon_device *rdev)
 
        radeon_bo_unref(&rdev->uvd.vcpu_bo);
 
+       radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
+
        release_firmware(rdev->uvd_fw);
 }
 
index 6c772e58c7845e7d4170287d3e583afd64c5a3e8..4e37a42305d83be2df8b3853bdff0e13b7b0f46f 100644 (file)
@@ -1955,9 +1955,9 @@ void rv770_fini(struct radeon_device *rdev)
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       rv770_pcie_gart_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_fini(rdev);
+       rv770_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
index 5b2ea8ac07312c8380b563b85b885b5f90ad8edb..b5f63f5e22a324dd6b2714834d58c339359ab918 100644 (file)
@@ -2526,14 +2526,7 @@ u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low)
 bool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
 {
        u32 vblank_time = r600_dpm_get_vblank_time(rdev);
-       u32 switch_limit = 300;
-
-       /* quirks */
-       /* ASUS K70AF */
-       if ((rdev->pdev->device == 0x9553) &&
-           (rdev->pdev->subsystem_vendor == 0x1043) &&
-           (rdev->pdev->subsystem_device == 0x1c42))
-               switch_limit = 200;
+       u32 switch_limit = 200; /* 300 */
 
        /* RV770 */
        /* mclk switching doesn't seem to work reliably on desktop RV770s */
index eafb0e6bc67ec5c7207d087ef0abc0e087c2f3a1..0a2f5b4bca430bf94a8d1e49dd9f786437772186 100644 (file)
@@ -2395,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev,
        if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
                enable_sq_ramping = false;
 
-       if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+       if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
                enable_sq_ramping = false;
 
        for (i = 0; i < state->performance_level_count; i++) {
index 88a529008ce0e59210e917422b2cfe07570a0d7d..c71594754f46fa18810d5b654d2c2d31288f6c3a 100644 (file)
@@ -104,7 +104,7 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
 
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
-#ifdef CONFIG_TEGRA_DRM_FBDEV
+#ifdef CONFIG_DRM_TEGRA_FBDEV
        struct tegra_drm *tegra = drm->dev_private;
 
        tegra_fbdev_restore_mode(tegra->fbdev);
index 338f7f6561d701d601a92b2f6362782536d03e2e..0266fb40479eae05f5176e9835d7c2a1ede75519 100644 (file)
@@ -15,6 +15,7 @@
 struct tegra_rgb {
        struct tegra_output output;
        struct tegra_dc *dc;
+       bool enabled;
 
        struct clk *clk_parent;
        struct clk *clk;
@@ -89,6 +90,9 @@ static int tegra_output_rgb_enable(struct tegra_output *output)
        struct tegra_rgb *rgb = to_rgb(output);
        unsigned long value;
 
+       if (rgb->enabled)
+               return 0;
+
        tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
        value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
@@ -122,6 +126,8 @@ static int tegra_output_rgb_enable(struct tegra_output *output)
        tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
        tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
+       rgb->enabled = true;
+
        return 0;
 }
 
@@ -130,6 +136,9 @@ static int tegra_output_rgb_disable(struct tegra_output *output)
        struct tegra_rgb *rgb = to_rgb(output);
        unsigned long value;
 
+       if (!rgb->enabled)
+               return 0;
+
        value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
        value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
                   PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
@@ -144,6 +153,8 @@ static int tegra_output_rgb_disable(struct tegra_output *output)
 
        tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
+       rgb->enabled = false;
+
        return 0;
 }
 
index 3302f99e7497002edf15f842d1b0abcebb71fbe4..764be36397fd2363d7bf9039574af51a6557136c 100644 (file)
@@ -126,6 +126,7 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev,
        agp_be->ttm.func = &ttm_agp_func;
 
        if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) {
+               kfree(agp_be);
                return NULL;
        }
 
index b645647b77764f47ccc1f294696579d1ba6d9cf7..f58dc7dd15c576ad2e4e0a702ee6aea1bffb01ce 100644 (file)
@@ -261,12 +261,7 @@ typedef enum SVGA3dSurfaceFormat {
    /* Planar video formats. */
    SVGA3D_YV12                         = 121,
 
-   /* Shader constant formats. */
-   SVGA3D_SURFACE_SHADERCONST_FLOAT    = 122,
-   SVGA3D_SURFACE_SHADERCONST_INT      = 123,
-   SVGA3D_SURFACE_SHADERCONST_BOOL     = 124,
-
-   SVGA3D_FORMAT_MAX                   = 125,
+   SVGA3D_FORMAT_MAX                   = 122,
 } SVGA3dSurfaceFormat;
 
 typedef uint32 SVGA3dColor; /* a, r, g, b */
@@ -1223,9 +1218,19 @@ typedef enum {
 #define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129
 
 #define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE  1130
-
+#define SVGA_3D_CMD_GB_SCREEN_DMA               1131
+#define SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH  1132
+#define SVGA_3D_CMD_GB_MOB_FENCE                1133
+#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V2        1134
 #define SVGA_3D_CMD_DEFINE_GB_MOB64          1135
 #define SVGA_3D_CMD_REDEFINE_GB_MOB64        1136
+#define SVGA_3D_CMD_NOP_ERROR                1137
+
+#define SVGA_3D_CMD_RESERVED1                1138
+#define SVGA_3D_CMD_RESERVED2                1139
+#define SVGA_3D_CMD_RESERVED3                1140
+#define SVGA_3D_CMD_RESERVED4                1141
+#define SVGA_3D_CMD_RESERVED5                1142
 
 #define SVGA_3D_CMD_MAX                      1142
 #define SVGA_3D_CMD_FUTURE_MAX               3000
@@ -1973,8 +1978,7 @@ struct {
    uint32 sizeInBytes;
    uint32 validSizeInBytes;
    SVGAMobFormat ptDepth;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdSetOTableBase;  /* SVGA_3D_CMD_SET_OTABLE_BASE */
 
 typedef
@@ -1984,15 +1988,13 @@ struct {
    uint32 sizeInBytes;
    uint32 validSizeInBytes;
    SVGAMobFormat ptDepth;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdSetOTableBase64;  /* SVGA_3D_CMD_SET_OTABLE_BASE64 */
 
 typedef
 struct {
    SVGAOTableType type;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdReadbackOTable;  /* SVGA_3D_CMD_READBACK_OTABLE */
 
 /*
@@ -2005,8 +2007,7 @@ struct SVGA3dCmdDefineGBMob {
    SVGAMobFormat ptDepth;
    PPN base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
 
 
@@ -2017,8 +2018,7 @@ SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
 typedef
 struct SVGA3dCmdDestroyGBMob {
    SVGAMobId mobid;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDestroyGBMob;   /* SVGA_3D_CMD_DESTROY_GB_MOB */
 
 /*
@@ -2031,8 +2031,7 @@ struct SVGA3dCmdRedefineGBMob {
    SVGAMobFormat ptDepth;
    PPN base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdRedefineGBMob;   /* SVGA_3D_CMD_REDEFINE_GB_MOB */
 
 /*
@@ -2045,8 +2044,7 @@ struct SVGA3dCmdDefineGBMob64 {
    SVGAMobFormat ptDepth;
    PPN64 base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDefineGBMob64;   /* SVGA_3D_CMD_DEFINE_GB_MOB64 */
 
 /*
@@ -2059,8 +2057,7 @@ struct SVGA3dCmdRedefineGBMob64 {
    SVGAMobFormat ptDepth;
    PPN64 base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
 
 /*
@@ -2070,8 +2067,7 @@ SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
 typedef
 struct SVGA3dCmdUpdateGBMobMapping {
    SVGAMobId mobid;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdUpdateGBMobMapping;   /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */
 
 /*
@@ -2087,7 +2083,8 @@ struct SVGA3dCmdDefineGBSurface {
    uint32 multisampleCount;
    SVGA3dTextureFilter autogenFilter;
    SVGA3dSize size;
-} SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
+} __packed
+SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
 
 /*
  * Destroy a guest-backed surface.
@@ -2096,7 +2093,8 @@ struct SVGA3dCmdDefineGBSurface {
 typedef
 struct SVGA3dCmdDestroyGBSurface {
    uint32 sid;
-} SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
+} __packed
+SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
 
 /*
  * Bind a guest-backed surface to an object.
@@ -2106,7 +2104,8 @@ typedef
 struct SVGA3dCmdBindGBSurface {
    uint32 sid;
    SVGAMobId mobid;
-} SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
+} __packed
+SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
 
 /*
  * Conditionally bind a mob to a guest backed surface if testMobid
@@ -2123,7 +2122,7 @@ struct{
    SVGAMobId testMobid;
    SVGAMobId mobid;
    uint32 flags;
-}
+} __packed
 SVGA3dCmdCondBindGBSurface;          /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */
 
 /*
@@ -2135,7 +2134,8 @@ typedef
 struct SVGA3dCmdUpdateGBImage {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
-} SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
+} __packed
+SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
 
 /*
  * Update an entire guest-backed surface.
@@ -2145,7 +2145,8 @@ struct SVGA3dCmdUpdateGBImage {
 typedef
 struct SVGA3dCmdUpdateGBSurface {
    uint32 sid;
-} SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
+} __packed
+SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
 
 /*
  * Readback an image in a guest-backed surface.
@@ -2155,7 +2156,8 @@ struct SVGA3dCmdUpdateGBSurface {
 typedef
 struct SVGA3dCmdReadbackGBImage {
    SVGA3dSurfaceImageId image;
-} SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
+} __packed
+SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
 
 /*
  * Readback an entire guest-backed surface.
@@ -2165,7 +2167,8 @@ struct SVGA3dCmdReadbackGBImage {
 typedef
 struct SVGA3dCmdReadbackGBSurface {
    uint32 sid;
-} SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
+} __packed
+SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
 
 /*
  * Readback a sub rect of an image in a guest-backed surface.  After
@@ -2179,7 +2182,7 @@ struct SVGA3dCmdReadbackGBImagePartial {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
    uint32 invertBox;
-}
+} __packed
 SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
 
 /*
@@ -2190,7 +2193,8 @@ SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
 typedef
 struct SVGA3dCmdInvalidateGBImage {
    SVGA3dSurfaceImageId image;
-} SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
+} __packed
+SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
 
 /*
  * Invalidate an entire guest-backed surface.
@@ -2200,7 +2204,8 @@ struct SVGA3dCmdInvalidateGBImage {
 typedef
 struct SVGA3dCmdInvalidateGBSurface {
    uint32 sid;
-} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
+} __packed
+SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
 
 /*
  * Invalidate a sub rect of an image in a guest-backed surface.  After
@@ -2214,7 +2219,7 @@ struct SVGA3dCmdInvalidateGBImagePartial {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
    uint32 invertBox;
-}
+} __packed
 SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
 
 /*
@@ -2224,7 +2229,8 @@ SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
 typedef
 struct SVGA3dCmdDefineGBContext {
    uint32 cid;
-} SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
+} __packed
+SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
 
 /*
  * Destroy a guest-backed context.
@@ -2233,7 +2239,8 @@ struct SVGA3dCmdDefineGBContext {
 typedef
 struct SVGA3dCmdDestroyGBContext {
    uint32 cid;
-} SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
+} __packed
+SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
 
 /*
  * Bind a guest-backed context.
@@ -2252,7 +2259,8 @@ struct SVGA3dCmdBindGBContext {
    uint32 cid;
    SVGAMobId mobid;
    uint32 validContents;
-} SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
+} __packed
+SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
 
 /*
  * Readback a guest-backed context.
@@ -2262,7 +2270,8 @@ struct SVGA3dCmdBindGBContext {
 typedef
 struct SVGA3dCmdReadbackGBContext {
    uint32 cid;
-} SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
+} __packed
+SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
 
 /*
  * Invalidate a guest-backed context.
@@ -2270,7 +2279,8 @@ struct SVGA3dCmdReadbackGBContext {
 typedef
 struct SVGA3dCmdInvalidateGBContext {
    uint32 cid;
-} SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
+} __packed
+SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
 
 /*
  * Define a guest-backed shader.
@@ -2281,7 +2291,8 @@ struct SVGA3dCmdDefineGBShader {
    uint32 shid;
    SVGA3dShaderType type;
    uint32 sizeInBytes;
-} SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
+} __packed
+SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
 
 /*
  * Bind a guest-backed shader.
@@ -2291,7 +2302,8 @@ typedef struct SVGA3dCmdBindGBShader {
    uint32 shid;
    SVGAMobId mobid;
    uint32 offsetInBytes;
-} SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
+} __packed
+SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
 
 /*
  * Destroy a guest-backed shader.
@@ -2299,7 +2311,8 @@ typedef struct SVGA3dCmdBindGBShader {
 
 typedef struct SVGA3dCmdDestroyGBShader {
    uint32 shid;
-} SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
+} __packed
+SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
 
 typedef
 struct {
@@ -2314,14 +2327,16 @@ struct {
     * Note that FLOAT and INT constants are 4-dwords in length, while
     * BOOL constants are 1-dword in length.
     */
-} SVGA3dCmdSetGBShaderConstInline;
+} __packed
+SVGA3dCmdSetGBShaderConstInline;
 /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */
 
 typedef
 struct {
    uint32               cid;
    SVGA3dQueryType      type;
-} SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
+} __packed
+SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
 
 typedef
 struct {
@@ -2329,7 +2344,8 @@ struct {
    SVGA3dQueryType      type;
    SVGAMobId mobid;
    uint32 offset;
-} SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
+} __packed
+SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
 
 
 /*
@@ -2346,21 +2362,22 @@ struct {
    SVGA3dQueryType      type;
    SVGAMobId mobid;
    uint32 offset;
-} SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
+} __packed
+SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
 
 typedef
 struct {
    SVGAMobId mobid;
    uint32 fbOffset;
    uint32 initalized;
-}
+} __packed
 SVGA3dCmdEnableGart;              /* SVGA_3D_CMD_ENABLE_GART */
 
 typedef
 struct {
    SVGAMobId mobid;
    uint32 gartOffset;
-}
+} __packed
 SVGA3dCmdMapMobIntoGart;          /* SVGA_3D_CMD_MAP_MOB_INTO_GART */
 
 
@@ -2368,7 +2385,7 @@ typedef
 struct {
    uint32 gartOffset;
    uint32 numPages;
-}
+} __packed
 SVGA3dCmdUnmapGartRange;          /* SVGA_3D_CMD_UNMAP_GART_RANGE */
 
 
@@ -2385,27 +2402,27 @@ struct {
    int32 xRoot;
    int32 yRoot;
    uint32 flags;
-}
+} __packed
 SVGA3dCmdDefineGBScreenTarget;    /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
-}
+} __packed
 SVGA3dCmdDestroyGBScreenTarget;  /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
    SVGA3dSurfaceImageId image;
-}
+} __packed
 SVGA3dCmdBindGBScreenTarget;  /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
    SVGA3dBox box;
-}
+} __packed
 SVGA3dCmdUpdateGBScreenTarget;  /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */
 
 /*
index 8369c3ba10fe5119ea09ba713f6bd1e5cb81f9cf..ef3385096145586fa7f148944b518b93e61d2974 100644 (file)
 
 #define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
 #define max_t(type, x, y)  ((x) > (y) ? (x) : (y))
+#define min_t(type, x, y)  ((x) < (y) ? (x) : (y))
 #define surf_size_struct SVGA3dSize
 #define u32 uint32
+#define u64 uint64_t
+#define U32_MAX ((u32)~0U)
 
 #endif /* __KERNEL__ */
 
@@ -704,8 +707,8 @@ static const struct svga3d_surface_desc svga3d_surface_descs[] = {
 
 static inline u32 clamped_umul32(u32 a, u32 b)
 {
-       uint64_t tmp = (uint64_t) a*b;
-       return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
+       u64 tmp = (u64) a*b;
+       return (tmp > (u64) U32_MAX) ? U32_MAX : tmp;
 }
 
 static inline const struct svga3d_surface_desc *
@@ -834,7 +837,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
                                  bool cubemap)
 {
        const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
-       u32 total_size = 0;
+       u64 total_size = 0;
        u32 mip;
 
        for (mip = 0; mip < num_mip_levels; mip++) {
@@ -847,7 +850,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
        if (cubemap)
                total_size *= SVGA3D_MAX_SURFACE_FACES;
 
-       return total_size;
+       return (u32) min_t(u64, total_size, (u64) U32_MAX);
 }
 
 
index 71defa4d2d7528a247b8e985a7b14cd1197e2a58..11323dd5196f495e5f2dd24b388c1720f3b6c1ce 100644 (file)
@@ -169,10 +169,17 @@ enum {
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
    SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
    SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
+   SVGA_REG_COMMAND_LOW = 48,       /* Lower 32 bits and submits commands */
+   SVGA_REG_COMMAND_HIGH = 49,      /* Upper 32 bits of command buffer PA */
    SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50,   /* Max primary memory */
    SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */
    SVGA_REG_DEV_CAP = 52,           /* Write dev cap index, read value */
-   SVGA_REG_TOP = 53,               /* Must be 1 more than the last register */
+   SVGA_REG_CMD_PREPEND_LOW = 53,
+   SVGA_REG_CMD_PREPEND_HIGH = 54,
+   SVGA_REG_SCREENTARGET_MAX_WIDTH = 55,
+   SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56,
+   SVGA_REG_MOB_MAX_SIZE = 57,
+   SVGA_REG_TOP = 58,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
index 9426c53fb4834cdcb5e4ab98e1912419f9369b5b..1e80152674b50ed62a73e3544c19855de29af070 100644 (file)
@@ -551,8 +551,7 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
        cmd->header.size = sizeof(cmd->body);
        cmd->body.cid = bi->ctx->id;
        cmd->body.type = bi->i1.shader_type;
-       cmd->body.shid =
-               cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
+       cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
        return 0;
@@ -585,8 +584,7 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
        cmd->header.size = sizeof(cmd->body);
        cmd->body.cid = bi->ctx->id;
        cmd->body.type = bi->i1.rt_type;
-       cmd->body.target.sid =
-               cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
+       cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
        cmd->body.target.face = 0;
        cmd->body.target.mipmap = 0;
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
@@ -628,8 +626,7 @@ static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi,
        cmd->body.c.cid = bi->ctx->id;
        cmd->body.s1.stage = bi->i1.texture_stage;
        cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
-       cmd->body.s1.value =
-               cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
+       cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
        return 0;
index 3bdc0adc656d002a22e1b95b28c4ba6f3a7d7747..0083cbf99edfd33bdfac9ad819ff4b12b1e7b5d8 100644 (file)
@@ -667,6 +667,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                dev_priv->memory_size = 512*1024*1024;
        }
        dev_priv->max_mob_pages = 0;
+       dev_priv->max_mob_size = 0;
        if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
                uint64_t mem_size =
                        vmw_read(dev_priv,
@@ -676,6 +677,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                dev_priv->prim_bb_mem =
                        vmw_read(dev_priv,
                                 SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+               dev_priv->max_mob_size =
+                       vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
        } else
                dev_priv->prim_bb_mem = dev_priv->vram_size;
 
index ecaa302a61546277cf52f787e385b9b233ca6a3c..07831554dad7acc3dae34f36e3a96e7b7f5299af 100644 (file)
@@ -40,7 +40,7 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20121114"
+#define VMWGFX_DRIVER_DATE "20140228"
 #define VMWGFX_DRIVER_MAJOR 2
 #define VMWGFX_DRIVER_MINOR 5
 #define VMWGFX_DRIVER_PATCHLEVEL 0
@@ -386,6 +386,7 @@ struct vmw_private {
        uint32_t max_gmr_ids;
        uint32_t max_gmr_pages;
        uint32_t max_mob_pages;
+       uint32_t max_mob_size;
        uint32_t memory_size;
        bool has_gmr;
        bool has_mob;
index 269b85cc875aa2108381eea88b70affd5f26757c..efb575a7996c2aed35e7046a47fd61acdbc167a0 100644 (file)
@@ -602,7 +602,7 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
 {
        struct vmw_cid_cmd {
                SVGA3dCmdHeader header;
-               __le32 cid;
+               uint32_t cid;
        } *cmd;
 
        cmd = container_of(header, struct vmw_cid_cmd, header);
@@ -1835,7 +1835,7 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
        return 0;
 }
 
-static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
+static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
        VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid,
                    false, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid,
@@ -2032,6 +2032,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
                goto out_invalid;
 
        entry = &vmw_cmd_entries[cmd_id];
+       if (unlikely(!entry->func))
+               goto out_invalid;
+
        if (unlikely(!entry->user_allow && !sw_context->kernel))
                goto out_privileged;
 
@@ -2469,7 +2472,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        if (dev_priv->has_mob) {
                ret = vmw_rebind_contexts(sw_context);
                if (unlikely(ret != 0))
-                       goto out_err;
+                       goto out_unlock_binding;
        }
 
        cmd = vmw_fifo_reserve(dev_priv, command_size);
index f9881f9e62bd401dbb8b25ad63414c0acdc51efb..47b70949bf3af6683bb74552c0b91fa7b06d7a82 100644 (file)
@@ -102,6 +102,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                vmw_fp->gb_aware = true;
                param->value = dev_priv->max_mob_pages * PAGE_SIZE;
                break;
+       case DRM_VMW_PARAM_MAX_MOB_SIZE:
+               param->value = dev_priv->max_mob_size;
+               break;
        default:
                DRM_ERROR("Illegal vmwgfx get param request: %d\n",
                          param->param);
index d4a5a19cb8c3ca1bd9db9424aad745ecfea5f868..04a64b8cd3cd4f17e00765efe2769e502c4b8240 100644 (file)
@@ -188,18 +188,20 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv,
 
        bo = otable->page_table->pt_bo;
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-       if (unlikely(cmd == NULL))
-               DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
-
-       memset(cmd, 0, sizeof(*cmd));
-       cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
-       cmd->header.size = sizeof(cmd->body);
-       cmd->body.type = type;
-       cmd->body.baseAddress = 0;
-       cmd->body.sizeInBytes = 0;
-       cmd->body.validSizeInBytes = 0;
-       cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
-       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for OTable "
+                         "takedown.\n");
+       } else {
+               memset(cmd, 0, sizeof(*cmd));
+               cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
+               cmd->header.size = sizeof(cmd->body);
+               cmd->body.type = type;
+               cmd->body.baseAddress = 0;
+               cmd->body.sizeInBytes = 0;
+               cmd->body.validSizeInBytes = 0;
+               cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
+               vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       }
 
        if (bo) {
                int ret;
@@ -562,11 +564,12 @@ void vmw_mob_unbind(struct vmw_private *dev_priv,
        if (unlikely(cmd == NULL)) {
                DRM_ERROR("Failed reserving FIFO space for Memory "
                          "Object unbinding.\n");
+       } else {
+               cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
+               cmd->header.size = sizeof(cmd->body);
+               cmd->body.mobid = mob->id;
+               vmw_fifo_commit(dev_priv, sizeof(*cmd));
        }
-       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
-       cmd->header.size = sizeof(cmd->body);
-       cmd->body.mobid = mob->id;
-       vmw_fifo_commit(dev_priv, sizeof(*cmd));
        if (bo) {
                vmw_fence_single_bo(bo, NULL);
                ttm_bo_unreserve(bo);
index 2aa4bc6a4d601578c294c3003b15985de9b28385..9757b57f8388d7a29fa51d04f61f5076fd149793 100644 (file)
@@ -427,8 +427,7 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
        INIT_LIST_HEAD(&vmw_bo->res_list);
 
        ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-                         (user) ? ttm_bo_type_device :
-                         ttm_bo_type_kernel, placement,
+                         ttm_bo_type_device, placement,
                          0, interruptible,
                          NULL, acc_size, NULL, bo_free);
        return ret;
index 217d941b81766187012b6747ae54752f2825d7e5..ee3856578a12589d8b12e4133666d04134ad729a 100644 (file)
@@ -371,13 +371,13 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
                                         TTM_REF_USAGE);
 }
 
-int vmw_shader_alloc(struct vmw_private *dev_priv,
-                    struct vmw_dma_buffer *buffer,
-                    size_t shader_size,
-                    size_t offset,
-                    SVGA3dShaderType shader_type,
-                    struct ttm_object_file *tfile,
-                    u32 *handle)
+static int vmw_shader_alloc(struct vmw_private *dev_priv,
+                           struct vmw_dma_buffer *buffer,
+                           size_t shader_size,
+                           size_t offset,
+                           SVGA3dShaderType shader_type,
+                           struct ttm_object_file *tfile,
+                           u32 *handle)
 {
        struct vmw_user_shader *ushader;
        struct vmw_resource *res, *tmp;
@@ -779,6 +779,8 @@ vmw_compat_shader_man_create(struct vmw_private *dev_priv)
        int ret;
 
        man = kzalloc(sizeof(*man), GFP_KERNEL);
+       if (man == NULL)
+               return ERR_PTR(-ENOMEM);
 
        man->dev_priv = dev_priv;
        INIT_LIST_HEAD(&man->list);
index 1146e3bba6e19bb69cd7f866c149b4aa7202ae46..112f27e51bc7df81b45efcb58f7c11fc46f097e0 100644 (file)
@@ -538,7 +538,7 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
 
                g->base = job->gather_addr_phys[i];
 
-               for (j = 0; j < job->num_gathers; j++)
+               for (j = i + 1; j < job->num_gathers; j++)
                        if (job->gathers[j].bo == g->bo)
                                job->gathers[j].handled = true;
 
index 497558127bb3e63609af2b5e1f75265f9e7b1423..f822fd2a1adabc4b3e53d86155c2d9e50d3d241e 100644 (file)
@@ -469,6 +469,9 @@ static const struct hid_device_id apple_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                                USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+                               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
index 3bfac3accd22fa6dc8a9be7a31cf9fd2814d2443..cc32a6f96c64804d8a1fc936f0fd22244eb51e83 100644 (file)
@@ -1679,6 +1679,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
@@ -1779,6 +1780,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
index 8fae6d1414cca83bc7af2386b7db5dc4cbd3f27b..c24908f14934f4d788263d3a768ae69797913769 100644 (file)
@@ -157,6 +157,7 @@ struct mousevsc_dev {
        u32                     report_desc_size;
        struct hv_input_dev_info hid_dev_info;
        struct hid_device       *hid_device;
+       u8                      input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 
@@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device *device,
        struct synthhid_msg *hid_msg;
        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
        struct synthhid_input_report *input_report;
+       size_t len;
 
        pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
                                                (packet->offset8 << 3));
@@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device *device,
                        (struct synthhid_input_report *)pipe_msg->data;
                if (!input_dev->init_complete)
                        break;
-               hid_input_report(input_dev->hid_device,
-                               HID_INPUT_REPORT, input_report->buffer,
-                               input_report->header.size, 1);
+
+               len = min(input_report->header.size,
+                         (u32)sizeof(input_dev->input_buf));
+               memcpy(input_dev->input_buf, input_report->buffer, len);
+               hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
+                                input_dev->input_buf, len, 1);
                break;
        default:
                pr_err("unsupported hid msg type - type %d len %d",
index 5a5248f2cc075b73ca68250866bddbc2b46f9bb1..22f28d6b33a845f0c728b3d4423b6c6fd848ff78 100644 (file)
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI  0x0255
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS   0x0257
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI   0x0290
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO    0x0291
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS    0x0292
 
 #define USB_VENDOR_ID_CYGNAL           0x10c4
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X      0x818a
+#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH      0x81b9
 
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI4713       0x8244
 
 #define USB_VENDOR_ID_INTEL_1          0x8087
 #define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa
 
+#define USB_VENDOR_ID_STM_0             0x0483
+#define USB_DEVICE_ID_STM_HID_SENSOR    0x91d1
+
 #define USB_VENDOR_ID_ION              0x15e4
 #define USB_DEVICE_ID_ICADE            0x0132
 
 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB      0x0713
 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K      0x0730
 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500    0x076c
+#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
+#define USB_DEVICE_ID_MS_TYPE_COVER_2  0x07a9
 
 #define USB_VENDOR_ID_MOJO             0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER    0x3201
 
 #define USB_VENDOR_ID_NEXIO            0x1870
 #define USB_DEVICE_ID_NEXIO_MULTITOUCH_420     0x010d
+#define USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750 0x0110
 
 #define USB_VENDOR_ID_NEXTWINDOW       0x1926
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN   0x0003
index d50e7313b171e4e9bd732cbee40a1a5cd5e501b5..a713e6211419c880ddd0a39597b78f16ad84919a 100644 (file)
@@ -1178,7 +1178,7 @@ static void hidinput_led_worker(struct work_struct *work)
 
        /* fall back to generic raw-output-report */
        len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       buf = kmalloc(len, GFP_KERNEL);
+       buf = hid_alloc_report_buf(report, GFP_KERNEL);
        if (!buf)
                return;
 
index c6ef6eed30915e272edf7249001d3005b9e1b667..404a3a8a82f123c40bca4c38ee84a0505aa404f6 100644 (file)
@@ -208,6 +208,10 @@ static const struct hid_device_id ms_devices[] = {
                .driver_data = MS_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
                .driver_data = MS_DUPLICATE_USAGES },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2),
+               .driver_data = 0 },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2),
+               .driver_data = 0 },
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
                .driver_data = MS_PRESENTER },
index f134d73beca16b72ddce5716d36e4d7ca949e61d..221d503f1c24fa7b1bbbc0c5871c3cbe742d1a5b 100644 (file)
@@ -1166,6 +1166,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
                        USB_DEVICE_ID_MULTITOUCH_3200) },
 
+       /* FocalTech Panels */
+       { .driver_data = MT_CLS_SERIAL,
+               MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
+                       USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
+
        /* GeneralTouch panel */
        { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
                MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
index 46f4480035bca14642c43618eb17bfd6729dfb0f..9c22e14c57f079622f297f6d5287919b8c5e2e31 100644 (file)
@@ -665,6 +665,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
                        USB_DEVICE_ID_INTEL_HID_SENSOR),
                        .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
+                       USB_DEVICE_ID_STM_HID_SENSOR),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
                     HID_ANY_ID) },
        { }
index d1f81f52481a40bf7a0521eca0033da057d15641..42eebd14de1f2e41ed932335e729bfb448b7f3f1 100644 (file)
@@ -582,7 +582,7 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
        int ret;
        int len = i2c_hid_get_report_length(rep) - 2;
 
-       buf = kzalloc(len, GFP_KERNEL);
+       buf = hid_alloc_report_buf(rep, GFP_KERNEL);
        if (!buf)
                return;
 
index 175ec0afb70cff7770fe4460e18e3d1480546cec..dbd83878ff99ec029a1cda07b265ddcd27418710 100644 (file)
@@ -74,6 +74,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
index a7626358c95df29c2ccb62fa89ed23251acfb979..029b65e6c58914d36061914e35738bda0c1e385c 100644 (file)
@@ -243,7 +243,7 @@ static ssize_t set_temp_min(struct device *dev,
        data->temp_min[index] = clamp_val(temp/1000, -128, 127);
        if (i2c_smbus_write_byte_data(client,
                                        MAX1668_REG_LIML_WR(index),
-                                       data->temp_max[index]))
+                                       data->temp_min[index]))
                count = -EIO;
        mutex_unlock(&data->update_lock);
 
index 41c64a43bcab163a1b08d70ce1433ee1e941b86a..ac2d69e34c8ceb60661c5f3b433d415939e607f9 100644 (file)
@@ -70,7 +70,7 @@ config IIO_ST_GYRO_3AXIS
        select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
        help
          Say yes here to build support for STMicroelectronics gyroscopes:
-         L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
+         L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330.
 
          This driver can also be built as a module. If so, these modules
          will be created:
index f8f2bf84a5a281f9d9cff04eeb4af3d81de6c5be..c197360c450bd8549a980a24941b322df4fca88f 100644 (file)
@@ -19,7 +19,6 @@
 #define LSM330DL_GYRO_DEV_NAME         "lsm330dl_gyro"
 #define LSM330DLC_GYRO_DEV_NAME                "lsm330dlc_gyro"
 #define L3GD20_GYRO_DEV_NAME           "l3gd20"
-#define L3GD20H_GYRO_DEV_NAME          "l3gd20h"
 #define L3G4IS_GYRO_DEV_NAME           "l3g4is_ui"
 #define LSM330_GYRO_DEV_NAME           "lsm330_gyro"
 
index d53d91adfb557b0e575a17030221c6e01b2b7d38..a8e174a47bc409cc22ece45c5a971ca3fe14f37d 100644 (file)
@@ -167,11 +167,10 @@ static const struct st_sensors st_gyro_sensors[] = {
                .wai = ST_GYRO_2_WAI_EXP,
                .sensors_supported = {
                        [0] = L3GD20_GYRO_DEV_NAME,
-                       [1] = L3GD20H_GYRO_DEV_NAME,
-                       [2] = LSM330D_GYRO_DEV_NAME,
-                       [3] = LSM330DLC_GYRO_DEV_NAME,
-                       [4] = L3G4IS_GYRO_DEV_NAME,
-                       [5] = LSM330_GYRO_DEV_NAME,
+                       [1] = LSM330D_GYRO_DEV_NAME,
+                       [2] = LSM330DLC_GYRO_DEV_NAME,
+                       [3] = L3G4IS_GYRO_DEV_NAME,
+                       [4] = LSM330_GYRO_DEV_NAME,
                },
                .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
                .odr = {
index 16b8b8d70bf127973b43f819999c3876f7a8683d..23c12f361b05b13f37430df0958f02a406b8812d 100644 (file)
@@ -55,7 +55,6 @@ static const struct i2c_device_id st_gyro_id_table[] = {
        { LSM330DL_GYRO_DEV_NAME },
        { LSM330DLC_GYRO_DEV_NAME },
        { L3GD20_GYRO_DEV_NAME },
-       { L3GD20H_GYRO_DEV_NAME },
        { L3G4IS_GYRO_DEV_NAME },
        { LSM330_GYRO_DEV_NAME },
        {},
index 94763e25caf999c22f2237fa3a5783d063512173..b4ad3be2668768e7a4ef35979478ed033933007f 100644 (file)
@@ -54,7 +54,6 @@ static const struct spi_device_id st_gyro_id_table[] = {
        { LSM330DL_GYRO_DEV_NAME },
        { LSM330DLC_GYRO_DEV_NAME },
        { L3GD20_GYRO_DEV_NAME },
-       { L3GD20H_GYRO_DEV_NAME },
        { L3G4IS_GYRO_DEV_NAME },
        { LSM330_GYRO_DEV_NAME },
        {},
index f17b4e6183c6bae6f36ee8acfaac897f76dfd8d9..47a6dbac2d0ca8b23dcea31158b43d3c3df3d2f0 100644 (file)
@@ -103,13 +103,13 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
 /**
  *  cm32181_read_als_it() - Get sensor integration time (ms)
  *  @cm32181:  pointer of struct cm32181
- *  @val     pointer of int to load the als_it value.
+ *  @val2:     pointer of int to load the als_it value.
  *
  *  Report the current integartion time by millisecond.
  *
- *  Return: IIO_VAL_INT for success, otherwise -EINVAL.
+ *  Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL.
  */
-static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val)
+static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
 {
        u16 als_it;
        int i;
@@ -119,8 +119,8 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val)
        als_it >>= CM32181_CMD_ALS_IT_SHIFT;
        for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
                if (als_it == als_it_bits[i]) {
-                       *val = als_it_value[i];
-                       return IIO_VAL_INT;
+                       *val2 = als_it_value[i];
+                       return IIO_VAL_INT_PLUS_MICRO;
                }
        }
 
@@ -221,7 +221,7 @@ static int cm32181_read_raw(struct iio_dev *indio_dev,
                *val = cm32181->calibscale;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = cm32181_read_als_it(cm32181, val);
+               ret = cm32181_read_als_it(cm32181, val2);
                return ret;
        }
 
@@ -240,7 +240,7 @@ static int cm32181_write_raw(struct iio_dev *indio_dev,
                cm32181->calibscale = val;
                return val;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = cm32181_write_als_it(cm32181, val);
+               ret = cm32181_write_als_it(cm32181, val2);
                return ret;
        }
 
@@ -264,7 +264,7 @@ static ssize_t cm32181_get_it_available(struct device *dev,
 
        n = ARRAY_SIZE(als_it_value);
        for (i = 0, len = 0; i < n; i++)
-               len += sprintf(buf + len, "%d ", als_it_value[i]);
+               len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
        return len + sprintf(buf + len, "\n");
 }
 
index 0a142af83e25dbb112809f04a048fd581f9a7d96..a45e07492db318a22171546291d2b590e0d0668f 100644 (file)
 #define CM36651_CS_CONF2_DEFAULT_BIT   0x08
 
 /* CS_CONF3 channel integration time */
-#define CM36651_CS_IT1                 0x00 /* Integration time 80000 usec */
-#define CM36651_CS_IT2                 0x40 /* Integration time 160000 usec */
-#define CM36651_CS_IT3                 0x80 /* Integration time 320000 usec */
-#define CM36651_CS_IT4                 0xC0 /* Integration time 640000 usec */
+#define CM36651_CS_IT1                 0x00 /* Integration time 80 msec */
+#define CM36651_CS_IT2                 0x40 /* Integration time 160 msec */
+#define CM36651_CS_IT3                 0x80 /* Integration time 320 msec */
+#define CM36651_CS_IT4                 0xC0 /* Integration time 640 msec */
 
 /* PS_CONF1 command code */
 #define CM36651_PS_ENABLE              0x00
 #define CM36651_PS_PERS4               0x0C
 
 /* PS_CONF1 command code: integration time */
-#define CM36651_PS_IT1                 0x00 /* Integration time 320 usec */
-#define CM36651_PS_IT2                 0x10 /* Integration time 420 usec */
-#define CM36651_PS_IT3                 0x20 /* Integration time 520 usec */
-#define CM36651_PS_IT4                 0x30 /* Integration time 640 usec */
+#define CM36651_PS_IT1                 0x00 /* Integration time 0.32 msec */
+#define CM36651_PS_IT2                 0x10 /* Integration time 0.42 msec */
+#define CM36651_PS_IT3                 0x20 /* Integration time 0.52 msec */
+#define CM36651_PS_IT4                 0x30 /* Integration time 0.64 msec */
 
 /* PS_CONF1 command code: duty ratio */
 #define CM36651_PS_DR1                 0x00 /* Duty ratio 1/80 */
@@ -93,8 +93,8 @@
 #define CM36651_CLOSE_PROXIMITY                0x32
 #define CM36651_FAR_PROXIMITY                  0x33
 
-#define CM36651_CS_INT_TIME_AVAIL      "80000 160000 320000 640000"
-#define CM36651_PS_INT_TIME_AVAIL      "320 420 520 640"
+#define CM36651_CS_INT_TIME_AVAIL      "0.08 0.16 0.32 0.64"
+#define CM36651_PS_INT_TIME_AVAIL      "0.000320 0.000420 0.000520 0.000640"
 
 enum cm36651_operation_mode {
        CM36651_LIGHT_EN,
@@ -356,30 +356,30 @@ static int cm36651_read_channel(struct cm36651_data *cm36651,
 }
 
 static int cm36651_read_int_time(struct cm36651_data *cm36651,
-                               struct iio_chan_spec const *chan, int *val)
+                               struct iio_chan_spec const *chan, int *val2)
 {
        switch (chan->type) {
        case IIO_LIGHT:
                if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT1)
-                       *val = 80000;
+                       *val2 = 80000;
                else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT2)
-                       *val = 160000;
+                       *val2 = 160000;
                else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT3)
-                       *val = 320000;
+                       *val2 = 320000;
                else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT4)
-                       *val = 640000;
+                       *val2 = 640000;
                else
                        return -EINVAL;
                break;
        case IIO_PROXIMITY:
                if (cm36651->ps_int_time == CM36651_PS_IT1)
-                       *val = 320;
+                       *val2 = 320;
                else if (cm36651->ps_int_time == CM36651_PS_IT2)
-                       *val = 420;
+                       *val2 = 420;
                else if (cm36651->ps_int_time == CM36651_PS_IT3)
-                       *val = 520;
+                       *val2 = 520;
                else if (cm36651->ps_int_time == CM36651_PS_IT4)
-                       *val = 640;
+                       *val2 = 640;
                else
                        return -EINVAL;
                break;
@@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651,
                return -EINVAL;
        }
 
-       return IIO_VAL_INT;
+       return IIO_VAL_INT_PLUS_MICRO;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
@@ -459,7 +459,8 @@ static int cm36651_read_raw(struct iio_dev *indio_dev,
                ret = cm36651_read_channel(cm36651, chan, val);
                break;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = cm36651_read_int_time(cm36651, chan, val);
+               *val = 0;
+               ret = cm36651_read_int_time(cm36651, chan, val2);
                break;
        default:
                ret = -EINVAL;
@@ -479,7 +480,7 @@ static int cm36651_write_raw(struct iio_dev *indio_dev,
        int ret = -EINVAL;
 
        if (mask == IIO_CHAN_INFO_INT_TIME) {
-               ret = cm36651_write_int_time(cm36651, chan, val);
+               ret = cm36651_write_int_time(cm36651, chan, val2);
                if (ret < 0)
                        dev_err(&client->dev, "Integration time write failed\n");
        }
index 7a04f54ef961fda20385251413fdee4490669ef6..ef2e281b0a43b641a1dbc6f5dd7fcb9190477d24 100644 (file)
@@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work)
                                                       struct arizona_haptics,
                                                       work);
        struct arizona *arizona = haptics->arizona;
-       struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
        int ret;
 
        if (!haptics->arizona->dapm) {
@@ -67,13 +66,10 @@ static void arizona_haptics_work(struct work_struct *work)
                        return;
                }
 
-               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
                ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
                                ret);
-                       mutex_unlock(dapm_mutex);
                        return;
                }
 
@@ -81,21 +77,14 @@ static void arizona_haptics_work(struct work_struct *work)
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
                                ret);
-                       mutex_unlock(dapm_mutex);
                        return;
                }
-
-               mutex_unlock(dapm_mutex);
-
        } else {
                /* This disable sequence will be a noop if already enabled */
-               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
                ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
                                ret);
-                       mutex_unlock(dapm_mutex);
                        return;
                }
 
@@ -103,12 +92,9 @@ static void arizona_haptics_work(struct work_struct *work)
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
                                ret);
-                       mutex_unlock(dapm_mutex);
                        return;
                }
 
-               mutex_unlock(dapm_mutex);
-
                ret = regmap_update_bits(arizona->regmap,
                                         ARIZONA_HAPTICS_CONTROL_1,
                                         ARIZONA_HAP_CTRL_MASK,
@@ -155,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data,
 static void arizona_haptics_close(struct input_dev *input)
 {
        struct arizona_haptics *haptics = input_get_drvdata(input);
-       struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
 
        cancel_work_sync(&haptics->work);
 
-       mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
        if (haptics->arizona->dapm)
                snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
-
-       mutex_unlock(dapm_mutex);
 }
 
 static int arizona_haptics_probe(struct platform_device *pdev)
index 8911850c94445fa5adf3b41de168293e5adf7721..1d9ab39af29f7c5d6ab2504fd2403ff725358a5d 100644 (file)
@@ -79,7 +79,6 @@
 
 #define ARM_SMMU_PTE_CONT_SIZE         (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES)
 #define ARM_SMMU_PTE_CONT_MASK         (~(ARM_SMMU_PTE_CONT_SIZE - 1))
-#define ARM_SMMU_PTE_HWTABLE_SIZE      (PTRS_PER_PTE * sizeof(pte_t))
 
 /* Stage-1 PTE */
 #define ARM_SMMU_PTE_AP_UNPRIV         (((pteval_t)1) << 6)
 #define ARM_SMMU_GR1_CBAR(n)           (0x0 + ((n) << 2))
 #define CBAR_VMID_SHIFT                        0
 #define CBAR_VMID_MASK                 0xff
+#define CBAR_S1_BPSHCFG_SHIFT          8
+#define CBAR_S1_BPSHCFG_MASK           3
+#define CBAR_S1_BPSHCFG_NSH            3
 #define CBAR_S1_MEMATTR_SHIFT          12
 #define CBAR_S1_MEMATTR_MASK           0xf
 #define CBAR_S1_MEMATTR_WB             0xf
@@ -393,7 +395,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             root_cfg;
        phys_addr_t                     output_mask;
 
-       struct mutex                    lock;
+       spinlock_t                      lock;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -632,6 +634,28 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
+                                  size_t size)
+{
+       unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+
+       /* Ensure new page tables are visible to the hardware walker */
+       if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) {
+               dsb();
+       } else {
+               /*
+                * If the SMMU can't walk tables in the CPU caches, treat them
+                * like non-coherent DMA since we need to flush the new entries
+                * all the way out to memory. There's no possibility of
+                * recursion here as the SMMU table walker will not be wired
+                * through another SMMU.
+                */
+               dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
+                               DMA_TO_DEVICE);
+       }
+}
+
 static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
 {
        u32 reg;
@@ -650,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
        if (smmu->version == 1)
              reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
 
-       /* Use the weakest memory type, so it is overridden by the pte */
-       if (stage1)
-               reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
-       else
+       /*
+        * Use the weakest shareability/memory types, so they are
+        * overridden by the ttbcr/pte.
+        */
+       if (stage1) {
+               reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+                       (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+       } else {
                reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
+       }
        writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
 
        if (smmu->version > 1) {
@@ -715,6 +744,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
        }
 
        /* TTBR0 */
+       arm_smmu_flush_pgtable(smmu, root_cfg->pgd,
+                              PTRS_PER_PGD * sizeof(pgd_t));
        reg = __pa(root_cfg->pgd);
        writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
        reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32;
@@ -901,7 +932,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
                goto out_free_domain;
        smmu_domain->root_cfg.pgd = pgd;
 
-       mutex_init(&smmu_domain->lock);
+       spin_lock_init(&smmu_domain->lock);
        domain->priv = smmu_domain;
        return 0;
 
@@ -1128,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        struct arm_smmu_domain *smmu_domain = domain->priv;
        struct arm_smmu_device *device_smmu = dev->archdata.iommu;
        struct arm_smmu_master *master;
+       unsigned long flags;
 
        if (!device_smmu) {
                dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
@@ -1138,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
         * Sanity check the domain. We don't currently support domains
         * that cross between different SMMU chains.
         */
-       mutex_lock(&smmu_domain->lock);
+       spin_lock_irqsave(&smmu_domain->lock, flags);
        if (!smmu_domain->leaf_smmu) {
                /* Now that we have a master, we can finalise the domain */
                ret = arm_smmu_init_domain_context(domain, dev);
@@ -1153,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                        dev_name(device_smmu->dev));
                goto err_unlock;
        }
-       mutex_unlock(&smmu_domain->lock);
+       spin_unlock_irqrestore(&smmu_domain->lock, flags);
 
        /* Looks ok, so add the device to the domain */
        master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1163,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        return arm_smmu_domain_add_master(smmu_domain, master);
 
 err_unlock:
-       mutex_unlock(&smmu_domain->lock);
+       spin_unlock_irqrestore(&smmu_domain->lock, flags);
        return ret;
 }
 
@@ -1177,23 +1209,6 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
                arm_smmu_domain_remove_master(smmu_domain, master);
 }
 
-static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
-                                  size_t size)
-{
-       unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
-
-       /*
-        * If the SMMU can't walk tables in the CPU caches, treat them
-        * like non-coherent DMA since we need to flush the new entries
-        * all the way out to memory. There's no possibility of recursion
-        * here as the SMMU table walker will not be wired through another
-        * SMMU.
-        */
-       if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK))
-               dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
-                            DMA_TO_DEVICE);
-}
-
 static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
                                             unsigned long end)
 {
@@ -1210,12 +1225,11 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
 
        if (pmd_none(*pmd)) {
                /* Allocate a new set of tables */
-               pgtable_t table = alloc_page(PGALLOC_GFP);
+               pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
                if (!table)
                        return -ENOMEM;
 
-               arm_smmu_flush_pgtable(smmu, page_address(table),
-                                      ARM_SMMU_PTE_HWTABLE_SIZE);
+               arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
                if (!pgtable_page_ctor(table)) {
                        __free_page(table);
                        return -ENOMEM;
@@ -1317,9 +1331,15 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
 
 #ifndef __PAGETABLE_PMD_FOLDED
        if (pud_none(*pud)) {
-               pmd = pmd_alloc_one(NULL, addr);
+               pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
                if (!pmd)
                        return -ENOMEM;
+
+               arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE);
+               pud_populate(NULL, pud, pmd);
+               arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
+
+               pmd += pmd_index(addr);
        } else
 #endif
                pmd = pmd_offset(pud, addr);
@@ -1328,8 +1348,6 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
                next = pmd_addr_end(addr, end);
                ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn,
                                              flags, stage);
-               pud_populate(NULL, pud, pmd);
-               arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
                phys += next - addr;
        } while (pmd++, addr = next, addr < end);
 
@@ -1346,9 +1364,15 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
 
 #ifndef __PAGETABLE_PUD_FOLDED
        if (pgd_none(*pgd)) {
-               pud = pud_alloc_one(NULL, addr);
+               pud = (pud_t *)get_zeroed_page(GFP_ATOMIC);
                if (!pud)
                        return -ENOMEM;
+
+               arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE);
+               pgd_populate(NULL, pgd, pud);
+               arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
+
+               pud += pud_index(addr);
        } else
 #endif
                pud = pud_offset(pgd, addr);
@@ -1357,8 +1381,6 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
                next = pud_addr_end(addr, end);
                ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys,
                                              flags, stage);
-               pgd_populate(NULL, pud, pgd);
-               arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
                phys += next - addr;
        } while (pud++, addr = next, addr < end);
 
@@ -1375,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
        pgd_t *pgd = root_cfg->pgd;
        struct arm_smmu_device *smmu = root_cfg->smmu;
+       unsigned long irqflags;
 
        if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
                stage = 2;
@@ -1397,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        if (paddr & ~output_mask)
                return -ERANGE;
 
-       mutex_lock(&smmu_domain->lock);
+       spin_lock_irqsave(&smmu_domain->lock, irqflags);
        pgd += pgd_index(iova);
        end = iova + size;
        do {
@@ -1413,11 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        } while (pgd++, iova != end);
 
 out_unlock:
-       mutex_unlock(&smmu_domain->lock);
-
-       /* Ensure new page tables are visible to the hardware walker */
-       if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
-               dsb();
+       spin_unlock_irqrestore(&smmu_domain->lock, irqflags);
 
        return ret;
 }
@@ -1987,8 +2006,10 @@ static int __init arm_smmu_init(void)
        if (!iommu_present(&platform_bus_type))
                bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
 
+#ifdef CONFIG_ARM_AMBA
        if (!iommu_present(&amba_bustype))
                bus_set_iommu(&amba_bustype, &arm_smmu_ops);
+#endif
 
        return 0;
 }
index d97fbe4fb9b1358f0f7bea574edd6c8cd73502df..80fffba7f12dfd77dcff90d06a9783613d131827 100644 (file)
@@ -354,8 +354,8 @@ DEBUG_FOPS(mem);
                        return -ENOMEM;                                 \
        }
 
-#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
-#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
+#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 0600)
+#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 0400)
 
 static int iommu_debug_register(struct device *dev, void *data)
 {
index 92c41ab4dbfd619b5458338c3e6b6563019b150c..2cb474ad8809faa2fadaf5b08a7b06b087e73794 100644 (file)
@@ -515,7 +515,7 @@ static int meta_intc_set_affinity(struct irq_data *data,
         * one cpu (the interrupt code doesn't support it), so we just
         * pick the first cpu we find in 'cpumask'.
         */
-       cpu = cpumask_any(cpumask);
+       cpu = cpumask_any_and(cpumask, cpu_online_mask);
        thread = cpu_2_hwthread_id[cpu];
 
        metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr);
index 8e94d7a3b20d277d127adf15441ea0b53879c606..c16c186d97d35f4246fa2acbd17942789922d6d7 100644 (file)
@@ -201,7 +201,7 @@ static int metag_internal_irq_set_affinity(struct irq_data *data,
         * one cpu (the interrupt code doesn't support it), so we just
         * pick the first cpu we find in 'cpumask'.
         */
-       cpu = cpumask_any(cpumask);
+       cpu = cpumask_any_and(cpumask, cpu_online_mask);
        thread = cpu_2_hwthread_id[cpu];
 
        metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)),
index e51d40031884b1d75f12d659e2f040f391a7ad73..8e41be62812e1663df05b58f75c52ecfdc7b844f 100644 (file)
@@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init);
 static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_domain *d = irq_get_handler_data(irq);
-       struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq);
+
+       struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
        u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
                   gc->mask_cache;
 
@@ -123,6 +124,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
        }
 }
 
+/*
+ * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register.
+ * To avoid interrupt events on stale irqs, we clear them before unmask.
+ */
+static unsigned int orion_bridge_irq_startup(struct irq_data *d)
+{
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
+       ct->chip.irq_ack(d);
+       ct->chip.irq_unmask(d);
+       return 0;
+}
+
 static int __init orion_bridge_irq_init(struct device_node *np,
                                        struct device_node *parent)
 {
@@ -143,7 +157,7 @@ static int __init orion_bridge_irq_init(struct device_node *np,
        }
 
        ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
-                            handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
+                            handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
        if (ret) {
                pr_err("%s: unable to alloc irq domain gc\n", np->name);
                return ret;
@@ -176,12 +190,14 @@ static int __init orion_bridge_irq_init(struct device_node *np,
 
        gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
        gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
+       gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup;
        gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit;
        gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
        gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
 
-       /* mask all interrupts */
+       /* mask and clear all interrupts */
        writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
+       writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
 
        irq_set_handler_data(irq, domain);
        irq_set_chained_handler(irq, orion_bridge_irq_handler);
index ffd472e015caa918facaed4f65a621c0f61e58a9..1af70145fab9bcee990dd54c08224f9e16924851 100644 (file)
@@ -289,6 +289,7 @@ struct per_bio_data {
        bool tick:1;
        unsigned req_nr:2;
        struct dm_deferred_entry *all_io_entry;
+       struct dm_hook_info hook_info;
 
        /*
         * writethrough fields.  These MUST remain at the end of this
@@ -297,7 +298,6 @@ struct per_bio_data {
         */
        struct cache *cache;
        dm_cblock_t cblock;
-       struct dm_hook_info hook_info;
        struct dm_bio_details bio_details;
 };
 
@@ -671,15 +671,16 @@ static void remap_to_cache(struct cache *cache, struct bio *bio,
                           dm_cblock_t cblock)
 {
        sector_t bi_sector = bio->bi_iter.bi_sector;
+       sector_t block = from_cblock(cblock);
 
        bio->bi_bdev = cache->cache_dev->bdev;
        if (!block_size_is_power_of_two(cache))
                bio->bi_iter.bi_sector =
-                       (from_cblock(cblock) * cache->sectors_per_block) +
+                       (block * cache->sectors_per_block) +
                        sector_div(bi_sector, cache->sectors_per_block);
        else
                bio->bi_iter.bi_sector =
-                       (from_cblock(cblock) << cache->sectors_per_block_shift) |
+                       (block << cache->sectors_per_block_shift) |
                        (bi_sector & (cache->sectors_per_block - 1));
 }
 
@@ -1010,13 +1011,15 @@ static void overwrite_endio(struct bio *bio, int err)
        struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
        unsigned long flags;
 
+       dm_unhook_bio(&pb->hook_info, bio);
+
        if (err)
                mg->err = true;
 
+       mg->requeue_holder = false;
+
        spin_lock_irqsave(&cache->lock, flags);
        list_add_tail(&mg->list, &cache->completed_migrations);
-       dm_unhook_bio(&pb->hook_info, bio);
-       mg->requeue_holder = false;
        spin_unlock_irqrestore(&cache->lock, flags);
 
        wake_worker(cache);
index b2b8a10e842784de5454e2639474f1a208b4b3f1..3842ac738f98ff324f5e1152f08fb546a5bb47fa 100644 (file)
@@ -201,29 +201,28 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse
 /*
  * Functions for getting the pages from a bvec.
  */
-static void bio_get_page(struct dpages *dp,
-                 struct page **p, unsigned long *len, unsigned *offset)
+static void bio_get_page(struct dpages *dp, struct page **p,
+                        unsigned long *len, unsigned *offset)
 {
-       struct bio *bio = dp->context_ptr;
-       struct bio_vec bvec = bio_iovec(bio);
-       *p = bvec.bv_page;
-       *len = bvec.bv_len;
-       *offset = bvec.bv_offset;
+       struct bio_vec *bvec = dp->context_ptr;
+       *p = bvec->bv_page;
+       *len = bvec->bv_len - dp->context_u;
+       *offset = bvec->bv_offset + dp->context_u;
 }
 
 static void bio_next_page(struct dpages *dp)
 {
-       struct bio *bio = dp->context_ptr;
-       struct bio_vec bvec = bio_iovec(bio);
-
-       bio_advance(bio, bvec.bv_len);
+       struct bio_vec *bvec = dp->context_ptr;
+       dp->context_ptr = bvec + 1;
+       dp->context_u = 0;
 }
 
 static void bio_dp_init(struct dpages *dp, struct bio *bio)
 {
        dp->get_page = bio_get_page;
        dp->next_page = bio_next_page;
-       dp->context_ptr = bio;
+       dp->context_ptr = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
+       dp->context_u = bio->bi_iter.bi_bvec_done;
 }
 
 /*
index 6eb9dc9ef8f36c4b709df6f3b46170598964e88d..422a9fdeb53e641d97acec4793ab00747dde9b1d 100644 (file)
@@ -1626,8 +1626,11 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
        /*
         * Only pass ioctls through if the device sizes match exactly.
         */
-       if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
+       if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) {
+               int err = scsi_verify_blk_ioctl(NULL, cmd);
+               if (err)
+                       r = err;
+       }
 
        if (r == -ENOTCONN && !fatal_signal_pending(current))
                queue_work(kmultipathd, &m->process_queued_ios);
index f284e0bfb25fca869855f390f2d8d7a5519a0864..7dfdb5c746d6f31960902350c33b7457485caadb 100644 (file)
@@ -1244,6 +1244,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
 
                        dm_bio_restore(bd, bio);
                        bio_record->details.bi_bdev = NULL;
+
+                       atomic_inc(&bio->bi_remaining);
+
                        queue_bio(ms, bio, rw);
                        return DM_ENDIO_INCOMPLETE;
                }
index 7da34766555284486e39a08306f88a876deeefc3..baa87ff12816382245c520a9a29ed2171d3d4d6a 100644 (file)
@@ -483,7 +483,7 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
 
        disk_super->data_mapping_root = cpu_to_le64(pmd->root);
        disk_super->device_details_root = cpu_to_le64(pmd->details_root);
-       disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+       disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE);
        disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
        disk_super->data_block_size = cpu_to_le32(pmd->data_block_size);
 
@@ -651,7 +651,7 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f
 {
        int r;
 
-       pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE,
+       pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
                                          THIN_METADATA_CACHE_SIZE,
                                          THIN_MAX_CONCURRENT_LOCKS);
        if (IS_ERR(pmd->bm)) {
@@ -1489,6 +1489,23 @@ bool dm_thin_changed_this_transaction(struct dm_thin_device *td)
        return r;
 }
 
+bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd)
+{
+       bool r = false;
+       struct dm_thin_device *td, *tmp;
+
+       down_read(&pmd->root_lock);
+       list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+               if (td->changed) {
+                       r = td->changed;
+                       break;
+               }
+       }
+       up_read(&pmd->root_lock);
+
+       return r;
+}
+
 bool dm_thin_aborted_changes(struct dm_thin_device *td)
 {
        bool r;
index 9a368567632f9733f04bc0a1aebfbc3d871f13df..82ea384d36ff9869b10864bc7e7d7f89d2bf3a4f 100644 (file)
@@ -9,16 +9,14 @@
 
 #include "persistent-data/dm-block-manager.h"
 #include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-metadata.h"
 
-#define THIN_METADATA_BLOCK_SIZE 4096
+#define THIN_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE
 
 /*
  * The metadata device is currently limited in size.
- *
- * We have one block of index, which can hold 255 index entries.  Each
- * index entry contains allocation info about 16k metadata blocks.
  */
-#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+#define THIN_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS
 
 /*
  * A metadata device larger than 16GB triggers a warning.
@@ -161,6 +159,8 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
  */
 bool dm_thin_changed_this_transaction(struct dm_thin_device *td);
 
+bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd);
+
 bool dm_thin_aborted_changes(struct dm_thin_device *td);
 
 int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
index faaf944597ab7669b90f3ecb85152fbcd16cbe33..7e84baccf0ad6c90f7a3f62ec084007003319b21 100644 (file)
@@ -1357,7 +1357,8 @@ static void process_deferred_bios(struct pool *pool)
        bio_list_init(&pool->deferred_flush_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
+       if (bio_list_empty(&bios) &&
+           !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
                return;
 
        if (commit(pool)) {
@@ -1999,16 +2000,27 @@ static void metadata_low_callback(void *context)
        dm_table_event(pool->ti->table);
 }
 
-static sector_t get_metadata_dev_size(struct block_device *bdev)
+static sector_t get_dev_size(struct block_device *bdev)
+{
+       return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+}
+
+static void warn_if_metadata_device_too_big(struct block_device *bdev)
 {
-       sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+       sector_t metadata_dev_size = get_dev_size(bdev);
        char buffer[BDEVNAME_SIZE];
 
-       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) {
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
                DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
                       bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS);
-               metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING;
-       }
+}
+
+static sector_t get_metadata_dev_size(struct block_device *bdev)
+{
+       sector_t metadata_dev_size = get_dev_size(bdev);
+
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS)
+               metadata_dev_size = THIN_METADATA_MAX_SECTORS;
 
        return metadata_dev_size;
 }
@@ -2017,7 +2029,7 @@ static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
 {
        sector_t metadata_dev_size = get_metadata_dev_size(bdev);
 
-       sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+       sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE);
 
        return metadata_dev_size;
 }
@@ -2095,12 +2107,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                ti->error = "Error opening metadata block device";
                goto out_unlock;
        }
-
-       /*
-        * Run for the side-effect of possibly issuing a warning if the
-        * device is too big.
-        */
-       (void) get_metadata_dev_size(metadata_dev->bdev);
+       warn_if_metadata_device_too_big(metadata_dev->bdev);
 
        r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
        if (r) {
@@ -2287,6 +2294,7 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
                return -EINVAL;
 
        } else if (metadata_dev_size > sb_metadata_dev_size) {
+               warn_if_metadata_device_too_big(pool->md_dev);
                DMINFO("%s: growing the metadata device from %llu to %llu blocks",
                       dm_device_name(pool->pool_md),
                       sb_metadata_dev_size, metadata_dev_size);
@@ -2894,6 +2902,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        if (get_pool_mode(tc->pool) == PM_FAIL) {
                ti->error = "Couldn't open thin device, Pool is in fail mode";
+               r = -EINVAL;
                goto bad_thin_open;
        }
 
@@ -2905,7 +2914,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        r = dm_set_target_max_io_len(ti, tc->pool->sectors_per_block);
        if (r)
-               goto bad_thin_open;
+               goto bad_target_max_io_len;
 
        ti->num_flush_bios = 1;
        ti->flush_supported = true;
@@ -2926,6 +2935,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        return 0;
 
+bad_target_max_io_len:
+       dm_pool_close_thin_device(tc->td);
 bad_thin_open:
        __pool_dec(tc->pool);
 bad_pool_lookup:
index 536782e3bcb757427763868fbf86fcb0bd92e273..e9bdd462f4f51a7cdcf917c6abbac85a80f58eaf 100644 (file)
@@ -680,6 +680,8 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
        if (r)
                return r;
 
+       if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
+               nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
        r = sm_ll_extend(&smm->ll, nr_blocks);
        if (r)
                return r;
index 39bba0801cf2ff092a593e6ccb283f949918cc89..64df923974d86a0ad4d22d59ebdb7fd7f6ecee3f 100644 (file)
@@ -9,6 +9,17 @@
 
 #include "dm-transaction-manager.h"
 
+#define DM_SM_METADATA_BLOCK_SIZE (4096 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about ~16k metadata blocks.
+ */
+#define DM_SM_METADATA_MAX_BLOCKS (255 * ((1 << 14) - 64))
+#define DM_SM_METADATA_MAX_SECTORS (DM_SM_METADATA_MAX_BLOCKS * DM_SM_METADATA_BLOCK_SIZE)
+
 /*
  * Unfortunately we have to use two-phase construction due to the cycle
  * between the tm and sm.
index 13af7e50021eedd5767aa296cfe46118f55f49ac..8103e4362132a24486961bf3ac6fd80980210107 100644 (file)
@@ -53,17 +53,25 @@ static int da9055_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the PMIC and CODEC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 ids for PMIC
+ * and CODEC, which must be different to operate together.
+ */
 static struct i2c_device_id da9055_i2c_id[] = {
-       {"da9055", 0},
+       {"da9055-pmic", 0},
        { }
 };
+MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
 
 static struct i2c_driver da9055_i2c_driver = {
        .probe = da9055_i2c_probe,
        .remove = da9055_i2c_remove,
        .id_table = da9055_i2c_id,
        .driver = {
-               .name = "da9055",
+               .name = "da9055-pmic",
                .owner = THIS_MODULE,
        },
 };
index ac514fb2b8779ef6a1b7395bcd6c26cc45aefdc2..71aa14a6bfbbb4ffd061aeb91df739fc70684446 100644 (file)
@@ -173,6 +173,7 @@ static const struct i2c_device_id max14577_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
 
+#ifdef CONFIG_PM_SLEEP
 static int max14577_suspend(struct device *dev)
 {
        struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -208,6 +209,7 @@ static int max14577_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static struct of_device_id max14577_dt_match[] = {
        { .compatible = "maxim,max14577", },
index be88a3bf7b857a5b19f7e9d95b1be42c7e58b2d3..5adede0fb04c8c5a82f7804d3138ab1f7a74f334 100644 (file)
@@ -164,15 +164,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
        return pd;
 }
 
-static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c,
                                                const struct i2c_device_id *id)
 {
        if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
                const struct of_device_id *match;
                match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
-               return (int)match->data;
+               return (unsigned long)match->data;
        }
-       return (int)id->driver_data;
+       return id->driver_data;
 }
 
 static int max8997_i2c_probe(struct i2c_client *i2c,
index 612ca404e1502d6c736eaf239d9b721e522664f9..5d5e186b5d8bbbfed035725480fb85dc52a0fdb4 100644 (file)
@@ -169,16 +169,16 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
        return pd;
 }
 
-static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
+static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c,
                                                const struct i2c_device_id *id)
 {
        if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
                const struct of_device_id *match;
                match = of_match_node(max8998_dt_match, i2c->dev.of_node);
-               return (int)(long)match->data;
+               return (unsigned long)match->data;
        }
 
-       return (int)id->driver_data;
+       return id->driver_data;
 }
 
 static int max8998_i2c_probe(struct i2c_client *i2c,
index a139798b806546b751b37f22e4d3e8044f3e2422..714e2135210ec2ddc989efcd44f3e800b80f5bcf 100644 (file)
@@ -315,6 +315,7 @@ static int sec_pmic_remove(struct i2c_client *i2c)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int sec_pmic_suspend(struct device *dev)
 {
        struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -349,6 +350,7 @@ static int sec_pmic_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
 
index 966cf65c5c363f63d907048fe4bb31b3d30bbbac..3cc4c7084b9244dcc18dd42a7ab77a3550e59ddb 100644 (file)
@@ -158,7 +158,7 @@ static int tps65217_probe(struct i2c_client *client,
 {
        struct tps65217 *tps;
        unsigned int version;
-       unsigned int chip_id = ids->driver_data;
+       unsigned long chip_id = ids->driver_data;
        const struct of_device_id *match;
        bool status_off = false;
        int ret;
@@ -170,7 +170,7 @@ static int tps65217_probe(struct i2c_client *client,
                                "Failed to find matching dt id\n");
                        return -EINVAL;
                }
-               chip_id = (unsigned int)(unsigned long)match->data;
+               chip_id = (unsigned long)match->data;
                status_off = of_property_read_bool(client->dev.of_node,
                                        "ti,pmic-shutdown-controller");
        }
index ba04f1bc70eb52988ce27b5f4e45195e8b216b82..e6fab94e2c8a0fb1eed8df339833e36f2dd7c38b 100644 (file)
@@ -636,7 +636,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
        if (i2c->dev.of_node) {
                of_id = of_match_device(wm8994_of_match, &i2c->dev);
                if (of_id)
-                       wm8994->type = (int)of_id->data;
+                       wm8994->type = (enum wm8994_type)of_id->data;
        } else {
                wm8994->type = id->driver_data;
        }
index 6cb388e8fb7d5ae9fa6783f5b2fad8337ddfef22..3816b59d3e1e2b3f7abad31aca700c67421adb37 100644 (file)
@@ -526,4 +526,5 @@ source "drivers/misc/mei/Kconfig"
 source "drivers/misc/vmw_vmci/Kconfig"
 source "drivers/misc/mic/Kconfig"
 source "drivers/misc/genwqe/Kconfig"
+source "drivers/misc/echo/Kconfig"
 endmenu
index 99b9424ce31d809fac0f55928c70b1a9c875d6a1..7eb4b69580c093993a75d877f17def36726196c8 100644 (file)
@@ -54,3 +54,4 @@ obj-$(CONFIG_LATTICE_ECP3_CONFIG)     += lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)             += sram.o
 obj-y                          += mic/
 obj-$(CONFIG_GENWQE)           += genwqe/
+obj-$(CONFIG_ECHO)             += echo/
index 9b809cfc289924912b92a00d826831fbb46433ec..89a557972d1b926abe915760366d6602c1efa0cf 100644 (file)
@@ -666,7 +666,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
                goto err;
 
        cb->fop_type = MEI_FOP_READ;
-       cl->read_cb = cb;
        if (dev->hbuf_is_ready) {
                dev->hbuf_is_ready = false;
                if (mei_hbm_cl_flow_control_req(dev, cl)) {
@@ -678,6 +677,9 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
        } else {
                list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
        }
+
+       cl->read_cb = cb;
+
        return rets;
 err:
        mei_io_cb_free(cb);
index 357bbc54fe4b6f423aa2dcc86ca3a23624748a6b..3e049c13429cfbe730179724053796cc65ba62de 100644 (file)
@@ -197,7 +197,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
 
        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-               limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
+               limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
        mq->card = card;
        mq->queue = blk_init_queue(mmc_request_fn, lock);
index 59eba5d2c68574fae787d36d2bd9e5ed29eb9f25..9715a7ba164a042abbba49fd842e9400a677d6fe 100644 (file)
@@ -1584,7 +1584,7 @@ read_retry:
                        }
 
                        if (mtd->ecc_stats.failed - ecc_failures) {
-                               if (retry_mode + 1 <= chip->read_retries) {
+                               if (retry_mode + 1 < chip->read_retries) {
                                        retry_mode++;
                                        ret = nand_setup_read_retry(mtd,
                                                        retry_mode);
index ef4190a02b7bd591af7c97be8ee1e3caecf6f83c..bf642ceef68172b4575d8e9d3263320e0fc7095a 100644 (file)
@@ -1633,6 +1633,7 @@ static int omap_nand_probe(struct platform_device *pdev)
        int                             i;
        dma_cap_mask_t                  mask;
        unsigned                        sig;
+       unsigned                        oob_index;
        struct resource                 *res;
        struct mtd_part_parser_data     ppdata = {};
 
@@ -1826,11 +1827,14 @@ static int omap_nand_probe(struct platform_device *pdev)
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
                if (nand_chip->options & NAND_BUSWIDTH_16)
-                       ecclayout->eccpos[0]    = BADBLOCK_MARKER_LENGTH;
+                       oob_index               = BADBLOCK_MARKER_LENGTH;
                else
-                       ecclayout->eccpos[0]    = 1;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+                       oob_index               = 1;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+                       ecclayout->eccpos[i]    = oob_index;
+               /* no reserved-marker in ecclayout for this ecc-scheme */
+               ecclayout->oobfree->offset      =
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                break;
 
        case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
@@ -1847,9 +1851,15 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+                       ecclayout->eccpos[i] = oob_index;
+                       if (((i + 1) % nand_chip->ecc.bytes) == 0)
+                               oob_index++;
+               }
+               /* include reserved-marker in ecclayout->oobfree calculation */
+               ecclayout->oobfree->offset      = 1 +
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                /* software bch library is used for locating errors */
                nand_chip->ecc.priv             = nand_bch_init(mtd,
                                                        nand_chip->ecc.size,
@@ -1883,9 +1893,12 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+                       ecclayout->eccpos[i]    = oob_index;
+               /* reserved marker already included in ecclayout->eccbytes */
+               ecclayout->oobfree->offset      =
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                /* This ECC scheme requires ELM H/W block */
                if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
                        pr_err("nand: error: could not initialize ELM\n");
@@ -1913,9 +1926,15 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+                       ecclayout->eccpos[i] = oob_index;
+                       if (((i + 1) % nand_chip->ecc.bytes) == 0)
+                               oob_index++;
+               }
+               /* include reserved-marker in ecclayout->oobfree calculation */
+               ecclayout->oobfree->offset      = 1 +
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                /* software bch library is used for locating errors */
                nand_chip->ecc.priv             = nand_bch_init(mtd,
                                                        nand_chip->ecc.size,
@@ -1956,9 +1975,12 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+                       ecclayout->eccpos[i]    = oob_index;
+               /* reserved marker already included in ecclayout->eccbytes */
+               ecclayout->oobfree->offset      =
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                break;
 #else
                pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
@@ -1972,11 +1994,8 @@ static int omap_nand_probe(struct platform_device *pdev)
                goto return_error;
        }
 
-       /* populate remaining ECC layout data */
-       ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
-                                                       ecclayout->eccbytes);
-       for (i = 1; i < ecclayout->eccbytes; i++)
-               ecclayout->eccpos[i] = ecclayout->eccpos[0] + i;
+       /* all OOB bytes from oobfree->offset till end off OOB are free */
+       ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
        /* check if NAND device's OOB is enough to store ECC signatures */
        if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
                pr_err("not enough OOB bytes required = %d, available=%d\n",
index ead861307b3c57aac13bbb187a958a8910062904..c5dad652614d747df33477dbd414c472572aefe5 100644 (file)
@@ -463,8 +463,8 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
                                }
                        }
                        if (found_orphan) {
-                               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                                list_del(&tmp_aeb->u.list);
+                               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                        }
 
                        new_aeb = kmem_cache_alloc(ai->aeb_slab_cache,
@@ -846,16 +846,16 @@ fail_bad:
        ret = UBI_BAD_FASTMAP;
 fail:
        list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
-               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                list_del(&tmp_aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
        }
        list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) {
-               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                list_del(&tmp_aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
        }
        list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                list_del(&tmp_aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
        }
 
        return ret;
index f342278539d50cfb58b0cfea45894bb1c63babd2..494b888a65681bde29911f13bea5ab02ed1c32d2 100644 (file)
@@ -139,7 +139,7 @@ config MACVTAP
          This adds a specialized tap character device driver that is based
          on the MAC-VLAN network interface, called macvtap. A macvtap device
          can be added in the same way as a macvlan device, using 'type
-         macvlan', and then be accessed through the tap user space interface.
+         macvtap', and then be accessed through the tap user space interface.
 
          To compile this driver as a module, choose M here: the module
          will be called macvtap.
index cce1f1bf90b4324e6e2f20e5da6ef53a307bd296..6d20fbde8d43502ca6a211c2cd0b83615ea051a0 100644 (file)
@@ -1796,8 +1796,6 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
        BOND_AD_INFO(bond).agg_select_timer = timeout;
 }
 
-static u16 aggregator_identifier;
-
 /**
  * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
  * @bond: bonding struct to work on
@@ -1811,7 +1809,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
        if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
                                bond->dev->dev_addr)) {
 
-               aggregator_identifier = 0;
+               BOND_AD_INFO(bond).aggregator_identifier = 0;
 
                BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
                BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@ -1880,7 +1878,7 @@ void bond_3ad_bind_slave(struct slave *slave)
                ad_initialize_agg(aggregator);
 
                aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
-               aggregator->aggregator_identifier = (++aggregator_identifier);
+               aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier;
                aggregator->slave = slave;
                aggregator->is_active = 0;
                aggregator->num_of_ports = 0;
index 13dc9d3c5e3460e2e0e4f01e2ab1df2a962d60e2..f4dd9592ac62561fb8967843446d6a9c0463b7e7 100644 (file)
@@ -253,6 +253,7 @@ struct ad_system {
 struct ad_bond_info {
        struct ad_system system;            /* 802.3ad system structure */
        u32 agg_select_timer;       // Timer to select aggregator after all adapter's hand shakes
+       u16 aggregator_identifier;
 };
 
 struct ad_slave_info {
index 71ba18efa15b545f029655003388ab1da8c19017..1c6104d3501d4df22e95beab7b60be63548dcc53 100644 (file)
@@ -1543,9 +1543,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        bond_set_carrier(bond);
 
        if (USES_PRIMARY(bond->params.mode)) {
+               block_netpoll_tx();
                write_lock_bh(&bond->curr_slave_lock);
                bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
+               unblock_netpoll_tx();
        }
 
        pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
@@ -1571,10 +1573,12 @@ err_detach:
        if (bond->primary_slave == new_slave)
                bond->primary_slave = NULL;
        if (bond->curr_active_slave == new_slave) {
+               block_netpoll_tx();
                write_lock_bh(&bond->curr_slave_lock);
                bond_change_active_slave(bond, NULL);
                bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
+               unblock_netpoll_tx();
        }
        slave_disable_netpoll(new_slave);
 
@@ -2864,9 +2868,12 @@ static int bond_slave_netdev_event(unsigned long event,
                pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
                        bond->dev->name, bond->primary_slave ? slave_dev->name :
                                                               "none");
+
+               block_netpoll_tx();
                write_lock_bh(&bond->curr_slave_lock);
                bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
+               unblock_netpoll_tx();
                break;
        case NETDEV_FEAT_CHANGE:
                bond_compute_features(bond);
@@ -3700,7 +3707,7 @@ static inline int bond_slave_override(struct bonding *bond,
 
 
 static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
-                            void *accel_priv)
+                            void *accel_priv, select_queue_fallback_t fallback)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 11cb943222d5c839ed363715db445351e6b3da56..c378784327172a327bfc55a8cc4ee8737db93b43 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
-#include <linux/rwlock.h>
+#include <linux/spinlock.h>
 #include <linux/rcupdate.h>
 #include <linux/ctype.h>
 #include <linux/inet.h>
index 6c859bba8b650852663a6ac538a0744a44135296..e77d11049747047a3824d7e9a1dc32fc004f552d 100644 (file)
@@ -473,6 +473,8 @@ static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
                return err;
 
        dev->nchannels = msg.u.cardinfo.nchannels;
+       if (dev->nchannels > MAX_NET_DEVICES)
+               return -EINVAL;
 
        return 0;
 }
index 9d7419e0390bd526d52e850f0d54c3863c920ffd..66c0df78c3ff9685c495626c6301fc85c6aac345 100644 (file)
@@ -1873,7 +1873,7 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
 }
 
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
-                      void *accel_priv)
+                      void *accel_priv, select_queue_fallback_t fallback)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
@@ -1895,7 +1895,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
        }
 
        /* select a non-FCoE queue */
-       return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+       return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
index bfc58d488bb52fde01d82ceb60647df083534bd8..a89a40f88c25779ded7f3e9357f765f191dbd55f 100644 (file)
@@ -496,7 +496,7 @@ int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
-                      void *accel_priv);
+                      void *accel_priv, select_queue_fallback_t fallback);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
                                        struct bnx2x_fastpath *fp,
index add05f14b38be17311f3344bd23860064fac8ce1..1642de78aac84c86b51cbae27c16d9748d70fb19 100644 (file)
@@ -1939,6 +1939,7 @@ static void tulip_remove_one(struct pci_dev *pdev)
        pci_iounmap(pdev, tp->base_addr);
        free_netdev (dev);
        pci_release_regions (pdev);
+       pci_disable_device(pdev);
 
        /* pci_power_off (pdev, -1); */
 }
index d4782b42401b0159b6375891db99bfc9999b0ecd..903362a7b58435878d790b06d9bb2dadbcdede35 100644 (file)
@@ -1778,8 +1778,6 @@ fec_enet_open(struct net_device *ndev)
        struct fec_enet_private *fep = netdev_priv(ndev);
        int ret;
 
-       napi_enable(&fep->napi);
-
        /* I should reset the ring buffers here, but I don't yet know
         * a simple way to do that.
         */
@@ -1794,6 +1792,8 @@ fec_enet_open(struct net_device *ndev)
                fec_enet_free_buffers(ndev);
                return ret;
        }
+
+       napi_enable(&fep->napi);
        phy_start(fep->phy_dev);
        netif_start_queue(ndev);
        fep->opened = 1;
index 6d4ada72dfd0a79f1111ff5c48f91ba3e2c862f1..18076c4178b4ff7762a117ef00595ab71173a10d 100644 (file)
@@ -6881,7 +6881,7 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
 }
 
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
-                             void *accel_priv)
+                             void *accel_priv, select_queue_fallback_t fallback)
 {
        struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
 #ifdef IXGBE_FCOE
@@ -6907,7 +6907,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
                if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
                        break;
        default:
-               return __netdev_pick_tx(dev, skb);
+               return fallback(dev, skb);
        }
 
        f = &adapter->ring_feature[RING_F_FCOE];
@@ -6920,7 +6920,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
 
        return txq + f->offset;
 #else
-       return __netdev_pick_tx(dev, skb);
+       return fallback(dev, skb);
 #endif
 }
 
index 8f9266c64c7589902c62443f79cc65a00895785f..fd4b6aecf6ee85d8f135cd6491582b417e1f3f1a 100644 (file)
@@ -619,7 +619,7 @@ ltq_etop_set_multicast_list(struct net_device *dev)
 
 static u16
 ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
-                     void *accel_priv)
+                     void *accel_priv, select_queue_fallback_t fallback)
 {
        /* we are currently only using the first queue */
        return 0;
index 6300fd27f2dbcc51157e362db65510c501b3ca6a..68e6a6613e9a1ccfd6a45f10d0ca0fb53c4c3dd6 100644 (file)
@@ -43,12 +43,12 @@ config MVMDIO
          This driver is used by the MV643XX_ETH and MVNETA drivers.
 
 config MVNETA
-       tristate "Marvell Armada 370/XP network interface support"
-       depends on MACH_ARMADA_370_XP
+       tristate "Marvell Armada 370/38x/XP network interface support"
+       depends on PLAT_ORION
        select MVMDIO
        ---help---
          This driver supports the network interface units in the
-         Marvell ARMADA XP and ARMADA 370 SoC family.
+         Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.
 
          Note that this driver is distinct from the mv643xx_eth
          driver, which should be used for the older Marvell SoCs
index 8e8a7eb43a2ce861249d678e1f1053be9b7b0ac5..13457032d15ff09489cff354b3322f06011e1c2b 100644 (file)
@@ -629,7 +629,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
 }
 
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
-                        void *accel_priv)
+                        void *accel_priv, select_queue_fallback_t fallback)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        u16 rings_p_up = priv->num_tx_rings_p_up;
@@ -641,7 +641,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
        if (vlan_tx_tag_present(skb))
                up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT;
 
-       return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up;
+       return fallback(dev, skb) % rings_p_up + up * rings_p_up;
 }
 
 static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
index 3af04c3f42ea96ddfa013ee874791c2db9dd6d94..9ca223bc90fc4fe7445a447828028b8a046f6fcb 100644 (file)
@@ -723,7 +723,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
-                        void *accel_priv);
+                        void *accel_priv, select_queue_fallback_t fallback);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
index e2f202e3932f518c78bc2c2febbe7efd32a39278..f2d7c702c77f3853fc05c90753f1ae90773d8753 100644 (file)
@@ -37,6 +37,17 @@ config DWMAC_SUNXI
          stmmac device driver. This driver is used for A20/A31
          GMAC    ethernet controller.
 
+config DWMAC_STI
+       bool "STi GMAC support"
+       depends on STMMAC_PLATFORM && ARCH_STI
+       default y
+       ---help---
+         Support for ethernet controller on STi SOCs.
+
+         This selects STi SoC glue layer support for the stmmac
+         device driver. This driver is used on for the STi series
+         SOCs GMAC ethernet controller.
+
 config STMMAC_PCI
        bool "STMMAC PCI bus support"
        depends on STMMAC_ETH && PCI
index ecadecea79b220c6c3e5d86f031d42c34df54e4d..dcef28775dadbeca184d8aca56358c389f1220e8 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
 stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
 stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
+stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
              chain_mode.o dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o \
              dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
new file mode 100644 (file)
index 0000000..552bbc1
--- /dev/null
@@ -0,0 +1,330 @@
+/**
+ * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
+ *
+ * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+#include <linux/phy.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+
+/**
+ *                     STi GMAC glue logic.
+ *                     --------------------
+ *
+ *              _
+ *             |  \
+ *     --------|0  \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK
+ * phyclk      |    |___________________________________________
+ *             |    |  |                       (phyclk-in)
+ *     --------|1  /   |
+ * int-clk     |_ /    |
+ *                     |        _
+ *                     |       |  \
+ *                     |_______|1  \ ETH_SEL_TX_RETIME_CLK
+ *                             |    |___________________________
+ *                             |    |          (tx-retime-clk)
+ *                      _______|0  /
+ *                     |       |_ /
+ *              _      |
+ *             |  \    |
+ *     --------|0  \   |
+ * clk_125     |    |__|
+ *             |    |  ETH_SEL_TXCLK_NOT_CLK125
+ *     --------|1  /
+ * txclk       |_ /
+ *
+ *
+ * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can
+ * generate 50MHz clock or MAC can generate it.
+ * This bit is configured by "st,ext-phyclk" property.
+ *
+ * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz
+ * clock either comes from clk-125 pin or txclk pin. This configuration is
+ * totally driven by the board wiring. This bit is configured by
+ * "st,tx-retime-src" property.
+ *
+ * TXCLK configuration is different for different phy interface modes
+ * and changes according to link speed in modes like RGMII.
+ *
+ * Below table summarizes the clock requirement and clock sources for
+ * supported phy interface modes with link speeds.
+ * ________________________________________________
+ *|  PHY_MODE  | 1000 Mbit Link | 100 Mbit Link   |
+ * ------------------------------------------------
+ *|    MII     |       n/a      |      25Mhz      |
+ *|            |                |      txclk      |
+ * ------------------------------------------------
+ *|    GMII    |     125Mhz     |      25Mhz      |
+ *|            |  clk-125/txclk |      txclk      |
+ * ------------------------------------------------
+ *|    RGMII   |     125Mhz     |      25Mhz      |
+ *|            |  clk-125/txclk |      clkgen     |
+ * ------------------------------------------------
+ *|    RMII    |       n/a      |      25Mhz      |
+ *|            |                |clkgen/phyclk-in |
+ * ------------------------------------------------
+ *
+ * TX lines are always retimed with a clk, which can vary depending
+ * on the board configuration. Below is the table of these bits
+ * in eth configuration register depending on source of retime clk.
+ *
+ *---------------------------------------------------------------
+ * src  | tx_rt_clk    | int_not_ext_phyclk    | txclk_n_clk125|
+ *---------------------------------------------------------------
+ * txclk |     0       |       n/a             |       1       |
+ *---------------------------------------------------------------
+ * ck_125|     0       |       n/a             |       0       |
+ *---------------------------------------------------------------
+ * phyclk|     1       |       0               |       n/a     |
+ *---------------------------------------------------------------
+ * clkgen|     1       |       1               |       n/a     |
+ *---------------------------------------------------------------
+ */
+
+ /* Register definition */
+
+ /* 3 bits [8:6]
+  *  [6:6]      ETH_SEL_TXCLK_NOT_CLK125
+  *  [7:7]      ETH_SEL_INTERNAL_NOTEXT_PHYCLK
+  *  [8:8]      ETH_SEL_TX_RETIME_CLK
+  *
+  */
+
+#define TX_RETIME_SRC_MASK             GENMASK(8, 6)
+#define ETH_SEL_TX_RETIME_CLK          BIT(8)
+#define ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
+#define ETH_SEL_TXCLK_NOT_CLK125       BIT(6)
+
+#define ENMII_MASK                     GENMASK(5, 5)
+#define ENMII                          BIT(5)
+
+/**
+ * 3 bits [4:2]
+ *     000-GMII/MII
+ *     001-RGMII
+ *     010-SGMII
+ *     100-RMII
+*/
+#define MII_PHY_SEL_MASK               GENMASK(4, 2)
+#define ETH_PHY_SEL_RMII               BIT(4)
+#define ETH_PHY_SEL_SGMII              BIT(3)
+#define ETH_PHY_SEL_RGMII              BIT(2)
+#define ETH_PHY_SEL_GMII               0x0
+#define ETH_PHY_SEL_MII                        0x0
+
+#define IS_PHY_IF_MODE_RGMII(iface)    (iface == PHY_INTERFACE_MODE_RGMII || \
+                       iface == PHY_INTERFACE_MODE_RGMII_ID || \
+                       iface == PHY_INTERFACE_MODE_RGMII_RXID || \
+                       iface == PHY_INTERFACE_MODE_RGMII_TXID)
+
+#define IS_PHY_IF_MODE_GBIT(iface)     (IS_PHY_IF_MODE_RGMII(iface) || \
+                       iface == PHY_INTERFACE_MODE_GMII)
+
+struct sti_dwmac {
+       int interface;
+       bool ext_phyclk;
+       bool is_tx_retime_src_clk_125;
+       struct clk *clk;
+       int reg;
+       struct device *dev;
+       struct regmap *regmap;
+};
+
+static u32 phy_intf_sels[] = {
+       [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
+       [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
+       [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
+       [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
+       [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
+       [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
+};
+
+enum {
+       TX_RETIME_SRC_NA = 0,
+       TX_RETIME_SRC_TXCLK = 1,
+       TX_RETIME_SRC_CLK_125,
+       TX_RETIME_SRC_PHYCLK,
+       TX_RETIME_SRC_CLKGEN,
+};
+
+static const char *const tx_retime_srcs[] = {
+       [TX_RETIME_SRC_NA] = "",
+       [TX_RETIME_SRC_TXCLK] = "txclk",
+       [TX_RETIME_SRC_CLK_125] = "clk_125",
+       [TX_RETIME_SRC_PHYCLK] = "phyclk",
+       [TX_RETIME_SRC_CLKGEN] = "clkgen",
+};
+
+static u32 tx_retime_val[] = {
+       [TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125,
+       [TX_RETIME_SRC_CLK_125] = 0x0,
+       [TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK,
+       [TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK |
+           ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
+};
+
+static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd)
+{
+       u32 src = 0, freq = 0;
+
+       if (spd == SPEED_100) {
+               if (dwmac->interface == PHY_INTERFACE_MODE_MII ||
+                   dwmac->interface == PHY_INTERFACE_MODE_GMII) {
+                       src = TX_RETIME_SRC_TXCLK;
+               } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
+                       if (dwmac->ext_phyclk) {
+                               src = TX_RETIME_SRC_PHYCLK;
+                       } else {
+                               src = TX_RETIME_SRC_CLKGEN;
+                               freq = 50000000;
+                       }
+
+               } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
+                       src = TX_RETIME_SRC_CLKGEN;
+                       freq = 25000000;
+               }
+
+               if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk)
+                       clk_set_rate(dwmac->clk, freq);
+
+       } else if (spd == SPEED_1000) {
+               if (dwmac->is_tx_retime_src_clk_125)
+                       src = TX_RETIME_SRC_CLK_125;
+               else
+                       src = TX_RETIME_SRC_TXCLK;
+       }
+
+       regmap_update_bits(dwmac->regmap, dwmac->reg,
+                          TX_RETIME_SRC_MASK, tx_retime_val[src]);
+}
+
+static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
+{
+       struct sti_dwmac *dwmac = priv;
+
+       if (dwmac->clk)
+               clk_disable_unprepare(dwmac->clk);
+}
+
+static void sti_fix_mac_speed(void *priv, unsigned int spd)
+{
+       struct sti_dwmac *dwmac = priv;
+
+       setup_retime_src(dwmac, spd);
+
+       return;
+}
+
+static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
+                               struct platform_device *pdev)
+{
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct regmap *regmap;
+       int err;
+
+       if (!np)
+               return -EINVAL;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
+       if (!res)
+               return -ENODATA;
+
+       regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       dwmac->dev = dev;
+       dwmac->interface = of_get_phy_mode(np);
+       dwmac->regmap = regmap;
+       dwmac->reg = res->start;
+       dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
+       dwmac->is_tx_retime_src_clk_125 = false;
+
+       if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
+               const char *rs;
+
+               err = of_property_read_string(np, "st,tx-retime-src", &rs);
+               if (err < 0) {
+                       dev_err(dev, "st,tx-retime-src not specified\n");
+                       return err;
+               }
+
+               if (!strcasecmp(rs, "clk_125"))
+                       dwmac->is_tx_retime_src_clk_125 = true;
+       }
+
+       dwmac->clk = devm_clk_get(dev, "sti-ethclk");
+
+       if (IS_ERR(dwmac->clk))
+               dwmac->clk = NULL;
+
+       return 0;
+}
+
+static int sti_dwmac_init(struct platform_device *pdev, void *priv)
+{
+       struct sti_dwmac *dwmac = priv;
+       struct regmap *regmap = dwmac->regmap;
+       int iface = dwmac->interface;
+       u32 reg = dwmac->reg;
+       u32 val, spd;
+
+       if (dwmac->clk)
+               clk_prepare_enable(dwmac->clk);
+
+       regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
+
+       val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
+       regmap_update_bits(regmap, reg, ENMII_MASK, val);
+
+       if (IS_PHY_IF_MODE_GBIT(iface))
+               spd = SPEED_1000;
+       else
+               spd = SPEED_100;
+
+       setup_retime_src(dwmac, spd);
+
+       return 0;
+}
+
+static void *sti_dwmac_setup(struct platform_device *pdev)
+{
+       struct sti_dwmac *dwmac;
+       int ret;
+
+       dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+       if (!dwmac)
+               return ERR_PTR(-ENOMEM);
+
+       ret = sti_dwmac_parse_data(dwmac, pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to parse OF data\n");
+               return ERR_PTR(ret);
+       }
+
+       return dwmac;
+}
+
+const struct stmmac_of_data sti_gmac_data = {
+       .fix_mac_speed = sti_fix_mac_speed,
+       .setup = sti_dwmac_setup,
+       .init = sti_dwmac_init,
+       .exit = sti_dwmac_exit,
+};
index d9af26ed58ee7d3c231c64b110924420c41b765e..f9e60d7918c4ac0b800a664ecae26e0228033f53 100644 (file)
@@ -133,6 +133,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv);
 #ifdef CONFIG_DWMAC_SUNXI
 extern const struct stmmac_of_data sun7i_gmac_data;
 #endif
+#ifdef CONFIG_DWMAC_STI
+extern const struct stmmac_of_data sti_gmac_data;
+#endif
 extern struct platform_driver stmmac_pltfr_driver;
 static inline int stmmac_register_platform(void)
 {
index 5884a7d2063b9bf650a7940485f9e96ea2cb0022..c61bc72b8e9006a2f8cb654421a7aaed50730436 100644 (file)
 static const struct of_device_id stmmac_dt_ids[] = {
 #ifdef CONFIG_DWMAC_SUNXI
        { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
+#endif
+#ifdef CONFIG_DWMAC_STI
+       { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data},
+       { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data},
+       { .compatible = "st,stih127-dwmac", .data = &sti_gmac_data},
 #endif
        /* SoC specific glue layers should come before generic bindings */
        { .compatible = "st,spear600-gmac"},
index 1d860ce914edefabba03f681a1d44a48c5c4911e..651087b5c8da57c9f9226925ef33f61372986531 100644 (file)
@@ -554,7 +554,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                 * common for both the interface as the interface shares
                 * the same hardware resource.
                 */
-               for (i = 0; i <= priv->data.slaves; i++)
+               for (i = 0; i < priv->data.slaves; i++)
                        if (priv->slaves[i].ndev->flags & IFF_PROMISC)
                                flag = true;
 
@@ -578,7 +578,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                        unsigned long timeout = jiffies + HZ;
 
                        /* Disable Learn for all ports */
-                       for (i = 0; i <= priv->data.slaves; i++) {
+                       for (i = 0; i < priv->data.slaves; i++) {
                                cpsw_ale_control_set(ale, i,
                                                     ALE_PORT_NOLEARN, 1);
                                cpsw_ale_control_set(ale, i,
@@ -606,7 +606,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                        cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
 
                        /* Enable Learn for all ports */
-                       for (i = 0; i <= priv->data.slaves; i++) {
+                       for (i = 0; i < priv->data.slaves; i++) {
                                cpsw_ale_control_set(ale, i,
                                                     ALE_PORT_NOLEARN, 0);
                                cpsw_ale_control_set(ale, i,
@@ -1896,6 +1896,11 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                        memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
                slave_data->phy_if = of_get_phy_mode(slave_node);
+               if (slave_data->phy_if < 0) {
+                       pr_err("Missing or malformed slave[%d] phy-mode property\n",
+                              i);
+                       return slave_data->phy_if;
+               }
 
                if (data->dual_emac) {
                        if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
index 023237a657207995e367ec365269d155043377c0..17503da9f7a589d5f56484329179c4c68c4af429 100644 (file)
@@ -2071,7 +2071,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
 /* Return subqueue id on this core (one per core). */
 static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
-                                void *accel_priv)
+                                void *accel_priv, select_queue_fallback_t fallback)
 {
        return smp_processor_id();
 }
index 1ec65feebb9e29cb1b9bfe7ffe2343fdfad9c537..4bfdf8c7ada033cf964f1da66daba0137b499e6f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
@@ -600,7 +601,8 @@ static void axienet_start_xmit_done(struct net_device *ndev)
                size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
                packets++;
 
-               lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM;
+               ++lp->tx_bd_ci;
+               lp->tx_bd_ci %= TX_BD_NUM;
                cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
                status = cur_p->status;
        }
@@ -686,7 +688,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                                     skb_headlen(skb), DMA_TO_DEVICE);
 
        for (ii = 0; ii < num_frag; ii++) {
-               lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+               ++lp->tx_bd_tail;
+               lp->tx_bd_tail %= TX_BD_NUM;
                cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
                frag = &skb_shinfo(skb)->frags[ii];
                cur_p->phys = dma_map_single(ndev->dev.parent,
@@ -702,7 +705,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
        /* Start the transfer */
        axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
-       lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+       ++lp->tx_bd_tail;
+       lp->tx_bd_tail %= TX_BD_NUM;
 
        return NETDEV_TX_OK;
 }
@@ -774,7 +778,8 @@ static void axienet_recv(struct net_device *ndev)
                cur_p->status = 0;
                cur_p->sw_id_offset = (u32) new_skb;
 
-               lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM;
+               ++lp->rx_bd_ci;
+               lp->rx_bd_ci %= RX_BD_NUM;
                cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
        }
 
index 7756118c2f0aee4c3671f45bc0bd13e15143d607..7141a1937360fabe59070e983c8737701307b48b 100644 (file)
@@ -88,8 +88,12 @@ static int netvsc_open(struct net_device *net)
 {
        struct net_device_context *net_device_ctx = netdev_priv(net);
        struct hv_device *device_obj = net_device_ctx->device_ctx;
+       struct netvsc_device *nvdev;
+       struct rndis_device *rdev;
        int ret = 0;
 
+       netif_carrier_off(net);
+
        /* Open up the device */
        ret = rndis_filter_open(device_obj);
        if (ret != 0) {
@@ -99,6 +103,11 @@ static int netvsc_open(struct net_device *net)
 
        netif_start_queue(net);
 
+       nvdev = hv_get_drvdata(device_obj);
+       rdev = nvdev->extension;
+       if (!rdev->link_state)
+               netif_carrier_on(net);
+
        return ret;
 }
 
@@ -229,23 +238,24 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
        struct net_device *net;
        struct net_device_context *ndev_ctx;
        struct netvsc_device *net_device;
+       struct rndis_device *rdev;
 
        net_device = hv_get_drvdata(device_obj);
+       rdev = net_device->extension;
+
+       rdev->link_state = status != 1;
+
        net = net_device->ndev;
 
-       if (!net) {
-               netdev_err(net, "got link status but net device "
-                               "not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED)
                return;
-       }
 
+       ndev_ctx = netdev_priv(net);
        if (status == 1) {
-               netif_carrier_on(net);
-               ndev_ctx = netdev_priv(net);
                schedule_delayed_work(&ndev_ctx->dwork, 0);
                schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
        } else {
-               netif_carrier_off(net);
+               schedule_delayed_work(&ndev_ctx->dwork, 0);
        }
 }
 
@@ -388,17 +398,35 @@ static const struct net_device_ops device_ops = {
  * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
  * another netif_notify_peers() into a delayed work, otherwise GARP packet
  * will not be sent after quick migration, and cause network disconnection.
+ * Also, we update the carrier status here.
  */
-static void netvsc_send_garp(struct work_struct *w)
+static void netvsc_link_change(struct work_struct *w)
 {
        struct net_device_context *ndev_ctx;
        struct net_device *net;
        struct netvsc_device *net_device;
+       struct rndis_device *rdev;
+       bool notify;
+
+       rtnl_lock();
 
        ndev_ctx = container_of(w, struct net_device_context, dwork.work);
        net_device = hv_get_drvdata(ndev_ctx->device_ctx);
+       rdev = net_device->extension;
        net = net_device->ndev;
-       netdev_notify_peers(net);
+
+       if (rdev->link_state) {
+               netif_carrier_off(net);
+               notify = false;
+       } else {
+               netif_carrier_on(net);
+               notify = true;
+       }
+
+       rtnl_unlock();
+
+       if (notify)
+               netdev_notify_peers(net);
 }
 
 
@@ -414,13 +442,10 @@ static int netvsc_probe(struct hv_device *dev,
        if (!net)
                return -ENOMEM;
 
-       /* Set initial state */
-       netif_carrier_off(net);
-
        net_device_ctx = netdev_priv(net);
        net_device_ctx->device_ctx = dev;
        hv_set_drvdata(dev, net);
-       INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+       INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
        INIT_WORK(&net_device_ctx->work, do_set_multicast);
 
        net->netdev_ops = &device_ops;
@@ -443,8 +468,6 @@ static int netvsc_probe(struct hv_device *dev,
        }
        memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
 
-       netif_carrier_on(net);
-
        ret = register_netdev(net);
        if (ret != 0) {
                pr_err("Unable to register netdev.\n");
index 177441afeb9680de599905bf75e8c1e10a9c7e0b..24b6dddd7f2f58445af7d0c5af47d399c31ac799 100644 (file)
@@ -522,7 +522,6 @@ static void irtty_close(struct tty_struct *tty)
        sirdev_put_instance(priv->dev);
 
        /* Stop tty */
-       irtty_stop_receiver(tty, TRUE);
        clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
        if (tty->ops->stop)
                tty->ops->stop(tty);
index 8433de4509c75a35cb65e7abdacb4f8968cb4008..a5d21893670d2692cf73da15113a2f116c3f0352 100644 (file)
@@ -879,14 +879,15 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        dev->priv_flags |= IFF_MACVLAN;
        err = netdev_upper_dev_link(lowerdev, dev);
        if (err)
-               goto destroy_port;
-
+               goto unregister_netdev;
 
        list_add_tail_rcu(&vlan->list, &port->vlans);
        netif_stacked_transfer_operstate(lowerdev, dev);
 
        return 0;
 
+unregister_netdev:
+       unregister_netdevice(dev);
 destroy_port:
        port->count -= 1;
        if (!port->count)
index 9414fa272160a88314878e7e3c639c134c8e4690..98e7cbf720a5859b8639ebe0653c6ccfd9c51f02 100644 (file)
@@ -1006,11 +1006,6 @@ static int dp83640_probe(struct phy_device *phydev)
        } else
                list_add_tail(&dp83640->list, &clock->phylist);
 
-       if (clock->chosen && !list_empty(&clock->phylist))
-               recalibrate(clock);
-       else
-               enable_broadcast(dp83640->phydev, clock->page, 1);
-
        dp83640_clock_put(clock);
        return 0;
 
@@ -1063,6 +1058,14 @@ static void dp83640_remove(struct phy_device *phydev)
 
 static int dp83640_config_init(struct phy_device *phydev)
 {
+       struct dp83640_private *dp83640 = phydev->priv;
+       struct dp83640_clock *clock = dp83640->clock;
+
+       if (clock->chosen && !list_empty(&clock->phylist))
+               recalibrate(clock);
+       else
+               enable_broadcast(phydev, clock->page, 1);
+
        enable_status_frames(phydev, true);
        ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
        return 0;
index 28407426fd6fdbc7dc0e21eb83c8acaba380065b..c8624a8235ab2f1020c4c387be290b631ed1b0dc 100644 (file)
@@ -1648,7 +1648,7 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
-                            void *accel_priv)
+                            void *accel_priv, select_queue_fallback_t fallback)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 44c4db8450f0347b4ea6ce861da7f05524ebdb5d..8fe9cb7d0f72e9fb7d34307f9a12797772844db1 100644 (file)
@@ -366,7 +366,7 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash)
  * hope the rxq no. may help here.
  */
 static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
-                           void *accel_priv)
+                           void *accel_priv, select_queue_fallback_t fallback)
 {
        struct tun_struct *tun = netdev_priv(dev);
        struct tun_flow_entry *e;
index 409499fdb157a6a6ad0676da9ed5590b528e1aa3..7e7269fd3707728d16705fc27c93c2f7a45b666f 100644 (file)
@@ -296,7 +296,6 @@ config USB_NET_SR9800
        tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices"
        depends on USB_USBNET
        select CRC32
-       default y
        ---help---
          Say Y if you want to use one of the following 100Mbps USB Ethernet
          device based on the CoreChip-sz SR9800 chip.
index 9765a7d4766dcd4a717bd7cd0bea56c71953deb1..5d194093f3e1f3b3c1893faf0cf8ebb266facdad 100644 (file)
@@ -917,7 +917,8 @@ static const struct driver_info ax88178_info = {
        .status = asix_status,
        .link_reset = ax88178_link_reset,
        .reset = ax88178_reset,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
+                FLAG_MULTI_PACKET,
        .rx_fixup = asix_rx_fixup_common,
        .tx_fixup = asix_tx_fixup,
 };
index d6f64dad05bcb707c0c26dbe2886abd73e760db1..955df81a43589bc30857b56db94f94886ce9cc30 100644 (file)
@@ -1118,6 +1118,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        u16 hdr_off;
        u32 *pkt_hdr;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        skb_trim(skb, skb->len - 4);
        memcpy(&rx_hdr, skb_tail_pointer(skb), 4);
        le32_to_cpus(&rx_hdr);
index e4a8a93fbaf7eec07ca3af2d2c813c08609b9c12..1cc24e6f23e2528150a3e9a660e134732e5cd988 100644 (file)
@@ -84,6 +84,10 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        u32                     size;
        u32                     count;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        header = (struct gl_header *) skb->data;
 
        // get the packet count of the received skb
index a305a7b2dae6f85ce4877a2f38e7d413688d5b1c..82d844a8ebd093e79c26ada9fc728fec8b10576e 100644 (file)
@@ -526,8 +526,9 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
        u8 status;
 
-       if (skb->len == 0) {
-               dev_err(&dev->udev->dev, "unexpected empty rx frame\n");
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len) {
+               dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
                return 0;
        }
 
index 0a85d92277750d061300f269b19f6c4be54dbe07..4cbdb1307f3e2ed0ad850a5ab076f80aaee26ce5 100644 (file)
@@ -364,6 +364,10 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        struct nc_trailer       *trailer;
        u16                     hdr_len, packet_len;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        if (!(skb->len & 0x01)) {
                netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n",
                           skb->len, dev->net->hard_header_len, dev->hard_mtu,
index ff5c87128ffe90066e734fa200015b4cd4cc49c3..313cb6cd4848e033bab664788c24c0a88ce55996 100644 (file)
@@ -80,10 +80,10 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
        __be16 proto;
 
-       /* usbnet rx_complete guarantees that skb->len is at least
-        * hard_header_len, so we can inspect the dest address without
-        * checking skb->len
-        */
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        switch (skb->data[0] & 0xf0) {
        case 0x40:
                proto = htons(ETH_P_IP);
@@ -732,6 +732,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)},    /* Telit LE920 */
        {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)},    /* Olivetti Olicard 200 */
        {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},    /* Cinterion PLxx */
+       {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)},    /* Cinterion PHxx,PXxx */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index a48bc0f20c1a860a66299d00391381cf58972b95..524a47a2812075490ac601b93590dd06d4caeccb 100644 (file)
@@ -492,6 +492,10 @@ EXPORT_SYMBOL_GPL(rndis_unbind);
  */
 int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        /* peripheral may have batched packets to us... */
        while (likely(skb->len)) {
                struct rndis_data_hdr   *hdr = (void *)skb->data;
index f17b9e02dd348166333d691a06b8b12b0a48a3e7..d9e7892262faa6a0543807d4d411163a5f59ac78 100644 (file)
@@ -2106,6 +2106,10 @@ static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
 
 static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        while (skb->len > 0) {
                u32 rx_cmd_a, rx_cmd_b, align_count, size;
                struct sk_buff *ax_skb;
index 8dd54a0f7b2973a29596fdb5ef99143269ce30cc..424db65e43962545b1746df63deb23833bf0c18b 100644 (file)
@@ -1723,6 +1723,10 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
 
 static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        while (skb->len > 0) {
                u32 header, align_count;
                struct sk_buff *ax_skb;
index 4175eb9fdecab2ee6e6442a45cd1961b9f18446d..b94a0fbb8b3b5a74ed466c4d5a66e25f4f2e0edc 100644 (file)
@@ -63,6 +63,10 @@ static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
        int offset = 0;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        while (offset + sizeof(u32) < skb->len) {
                struct sk_buff *sr_skb;
                u16 size;
@@ -823,7 +827,7 @@ static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf)
                dev->rx_urb_size =
                        SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size;
        }
-       netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__,
+       netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__,
                   dev->rx_urb_size);
        return 0;
 
index 4671da755e7b87f60758259021bcc5ab7f7c6cd1..dd10d5817d2a975b414dc40bf0f4937b46c263be 100644 (file)
@@ -542,17 +542,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
        }
        // else network stack removes extra byte if we forced a short packet
 
-       if (skb->len) {
-               /* all data was already cloned from skb inside the driver */
-               if (dev->driver_info->flags & FLAG_MULTI_PACKET)
-                       dev_kfree_skb_any(skb);
-               else
-                       usbnet_skb_return(dev, skb);
+       /* all data was already cloned from skb inside the driver */
+       if (dev->driver_info->flags & FLAG_MULTI_PACKET)
+               goto done;
+
+       if (skb->len < ETH_HLEN) {
+               dev->net->stats.rx_errors++;
+               dev->net->stats.rx_length_errors++;
+               netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len);
+       } else {
+               usbnet_skb_return(dev, skb);
                return;
        }
 
-       netif_dbg(dev, rx_err, dev->net, "drop\n");
-       dev->net->stats.rx_errors++;
 done:
        skb_queue_tail(&dev->done, skb);
 }
@@ -574,13 +576,6 @@ static void rx_complete (struct urb *urb)
        switch (urb_status) {
        /* success */
        case 0:
-               if (skb->len < dev->net->hard_header_len) {
-                       state = rx_cleanup;
-                       dev->net->stats.rx_errors++;
-                       dev->net->stats.rx_length_errors++;
-                       netif_dbg(dev, rx_err, dev->net,
-                                 "rx length %d\n", skb->len);
-               }
                break;
 
        /* stalls need manual reset. this is rare ... except that
index d6bc7cb61bfb9b31ffa478fc77aae84ef1c39905..1a2973b7acf2500f5c97c992315793d0b4b9a9a7 100644 (file)
@@ -110,7 +110,7 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band)
                ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
 
        if (ah->ah_version == AR5K_AR5210) {
-               srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+               srev = (ath5k_hw_reg_read(ah, AR5K_PHY(256)) >> 28) & 0xf;
                ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
        } else {
                srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
index aa7ad3a7a69b058e2e2d148279d3f9c0cc6b2afe..4e5c0f8c949610e9f3a6696f16018ce5bd3fe54e 100644 (file)
@@ -496,7 +496,7 @@ void hostap_init_proc(local_info_t *local)
 
 void hostap_remove_proc(local_info_t *local)
 {
-       remove_proc_subtree(local->ddev->name, hostap_proc);
+       proc_remove(local->proc);
 }
 
 
index c24d1d3d55f66a470d3e62663348e79eb729997f..73086c1629ca13be4e359badffd927a3fee43847 100644 (file)
@@ -696,6 +696,24 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
+static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+               return false;
+       return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+               return false;
+       if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+               return true;
+
+       /* disabled by default */
+       return false;
+}
+
 static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif,
                                   enum ieee80211_ampdu_mlme_action action,
@@ -717,7 +735,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+               if (!iwl_enable_rx_ampdu(priv->cfg))
                        break;
                IWL_DEBUG_HT(priv, "start Rx\n");
                ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
@@ -729,7 +747,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
        case IEEE80211_AMPDU_TX_START:
                if (!priv->trans->ops->txq_enable)
                        break;
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+               if (!iwl_enable_tx_ampdu(priv->cfg))
                        break;
                IWL_DEBUG_HT(priv, "start Tx\n");
                ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
index c3728163be463224b4e3eb38b5573aa85370e193..75103554cd635061628470255dd7a6eae6e8b82f 100644 (file)
@@ -1286,7 +1286,7 @@ module_param_named(swcrypto, iwlwifi_mod_params.sw_crypto, int, S_IRUGO);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
 module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
 MODULE_PARM_DESC(11n_disable,
-       "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
+       "disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
 module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
                   int, S_IRUGO);
 MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
index 0a84ade7edac25b01d28df63158669083c442b8c..b29075c3da8e2e65e8c621c89fda3b5f9b586e79 100644 (file)
@@ -79,9 +79,12 @@ enum iwl_power_level {
        IWL_POWER_NUM
 };
 
-#define IWL_DISABLE_HT_ALL     BIT(0)
-#define IWL_DISABLE_HT_TXAGG   BIT(1)
-#define IWL_DISABLE_HT_RXAGG   BIT(2)
+enum iwl_disable_11n {
+       IWL_DISABLE_HT_ALL       = BIT(0),
+       IWL_DISABLE_HT_TXAGG     = BIT(1),
+       IWL_DISABLE_HT_RXAGG     = BIT(2),
+       IWL_ENABLE_HT_TXAGG      = BIT(3),
+};
 
 /**
  * struct iwl_mod_params
@@ -90,7 +93,7 @@ enum iwl_power_level {
  *
  * @sw_crypto: using hardware encryption, default = 0
  * @disable_11n: disable 11n capabilities, default = 0,
- *     use IWL_DISABLE_HT_* constants
+ *     use IWL_[DIS,EN]ABLE_HT_* constants
  * @amsdu_size_8K: enable 8K amsdu size, default = 0
  * @restart_fw: restart firmware, default = 1
  * @wd_disable: enable stuck queue check, default = 0
index 6bf9766e59821a1b45e0c666e2a59172fc84a9bc..c35b8661b39539403bd5c2503ac7ec6208cb99e0 100644 (file)
@@ -328,6 +328,24 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
        ieee80211_free_txskb(hw, skb);
 }
 
+static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+               return false;
+       return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+               return false;
+       if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+               return true;
+
+       /* enabled by default */
+       return true;
+}
+
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    enum ieee80211_ampdu_mlme_action action,
@@ -347,7 +365,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) {
+               if (!iwl_enable_rx_ampdu(mvm->cfg)) {
                        ret = -EINVAL;
                        break;
                }
@@ -357,7 +375,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
                break;
        case IEEE80211_AMPDU_TX_START:
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) {
+               if (!iwl_enable_tx_ampdu(mvm->cfg)) {
                        ret = -EINVAL;
                        break;
                }
index 4d79761b9c87e3121dee2c61151d54a5d5002cbe..9d3d2758ec355381ebaceea681e3fd2ebae5d753 100644 (file)
@@ -748,7 +748,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 
 static u16
 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
-                               void *accel_priv)
+                               void *accel_priv, select_queue_fallback_t fallback)
 {
        skb->priority = cfg80211_classify8021d(skb, NULL);
        return mwifiex_1d_to_wmm_queue[skb->priority];
index 56aee067f324694ef5c83b376bac600c52b845cf..a6ad79f61bf9bc026328c8be87414a5a7ef223d8 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef RTL8187_H
 #define RTL8187_H
 
+#include <linux/cache.h>
+
 #include "rtl818x.h"
 #include "leds.h"
 
@@ -139,7 +141,10 @@ struct rtl8187_priv {
        u8 aifsn[4];
        u8 rfkill_mask;
        struct {
-               __le64 buf;
+               union {
+                       __le64 buf;
+                       u8 dummy1[L1_CACHE_BYTES];
+               } ____cacheline_aligned;
                struct sk_buff_head queue;
        } b_tx_status; /* This queue is used by both -b and non-b devices */
        struct mutex io_mutex;
@@ -147,7 +152,8 @@ struct rtl8187_priv {
                u8 bits8;
                __le16 bits16;
                __le32 bits32;
-       } *io_dmabuf;
+               u8 dummy2[L1_CACHE_BYTES];
+       } *io_dmabuf ____cacheline_aligned;
        bool rfkill_off;
        u16 seqno;
 };
index deedae3c54498370462ef4bc1bde40d7749ee0c8..d1c0191a195b909e5095fde8807eb671b307e374 100644 (file)
@@ -48,7 +48,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
 
        /*<2> Enable Adapter */
        if (rtlpriv->cfg->ops->hw_init(hw))
-               return 1;
+               return false;
        RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 
        /*<3> Enable Interrupt */
index a82b30a1996ca97cc5041ac47899171fef15e25e..2eb0b38384dd7cef1323f5817be961954d31f514 100644 (file)
@@ -937,14 +937,26 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
        bool is92c;
        int err;
        u8 tmp_u1b;
+       unsigned long flags;
 
        rtlpci->being_init_adapter = true;
+
+       /* Since this function can take a very long time (up to 350 ms)
+        * and can be called with irqs disabled, reenable the irqs
+        * to let the other devices continue being serviced.
+        *
+        * It is safe doing so since our own interrupts will only be enabled
+        * in a subsequent step.
+        */
+       local_save_flags(flags);
+       local_irq_enable();
+
        rtlpriv->intf_ops->disable_aspm(hw);
        rtstatus = _rtl92ce_init_mac(hw);
        if (!rtstatus) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
                err = 1;
-               return err;
+               goto exit;
        }
 
        err = rtl92c_download_fw(hw);
@@ -952,7 +964,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
                         "Failed to download FW. Init HW without FW now..\n");
                err = 1;
-               return err;
+               goto exit;
        }
 
        rtlhal->last_hmeboxnum = 0;
@@ -1032,6 +1044,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n");
        }
        rtl92c_dm_init(hw);
+exit:
+       local_irq_restore(flags);
        rtlpci->being_init_adapter = false;
        return err;
 }
index 10b51106c854f20fc1b73bf80d9b5c37d23d8545..89e888a78899e2b61281f7007406e5f937cc28a0 100644 (file)
@@ -342,27 +342,72 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-/** Checks if the given "compat" string matches one of the strings in
- * the device's "compatible" property
+/**
+ * __of_device_is_compatible() - Check if the node matches given constraints
+ * @device: pointer to node
+ * @compat: required compatible string, NULL or "" for any match
+ * @type: required device_type value, NULL or "" for any match
+ * @name: required node name, NULL or "" for any match
+ *
+ * Checks if the given @compat, @type and @name strings match the
+ * properties of the given @device. A constraints can be skipped by
+ * passing NULL or an empty string as the constraint.
+ *
+ * Returns 0 for no match, and a positive integer on match. The return
+ * value is a relative score with larger values indicating better
+ * matches. The score is weighted for the most specific compatible value
+ * to get the highest score. Matching type is next, followed by matching
+ * name. Practically speaking, this results in the following priority
+ * order for matches:
+ *
+ * 1. specific compatible && type && name
+ * 2. specific compatible && type
+ * 3. specific compatible && name
+ * 4. specific compatible
+ * 5. general compatible && type && name
+ * 6. general compatible && type
+ * 7. general compatible && name
+ * 8. general compatible
+ * 9. type && name
+ * 10. type
+ * 11. name
  */
 static int __of_device_is_compatible(const struct device_node *device,
-                                    const char *compat)
+                                    const char *compat, const char *type, const char *name)
 {
-       const char* cp;
-       int cplen, l;
+       struct property *prop;
+       const char *cp;
+       int index = 0, score = 0;
+
+       /* Compatible match has highest priority */
+       if (compat && compat[0]) {
+               prop = __of_find_property(device, "compatible", NULL);
+               for (cp = of_prop_next_string(prop, NULL); cp;
+                    cp = of_prop_next_string(prop, cp), index++) {
+                       if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
+                               score = INT_MAX/2 - (index << 2);
+                               break;
+                       }
+               }
+               if (!score)
+                       return 0;
+       }
 
-       cp = __of_get_property(device, "compatible", &cplen);
-       if (cp == NULL)
-               return 0;
-       while (cplen > 0) {
-               if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
-                       return 1;
-               l = strlen(cp) + 1;
-               cp += l;
-               cplen -= l;
+       /* Matching type is better than matching name */
+       if (type && type[0]) {
+               if (!device->type || of_node_cmp(type, device->type))
+                       return 0;
+               score += 2;
        }
 
-       return 0;
+       /* Matching name is a bit better than not */
+       if (name && name[0]) {
+               if (!device->name || of_node_cmp(name, device->name))
+                       return 0;
+               score++;
+       }
+
+       return score;
 }
 
 /** Checks if the given "compat" string matches one of the strings in
@@ -375,7 +420,7 @@ int of_device_is_compatible(const struct device_node *device,
        int res;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       res = __of_device_is_compatible(device, compat);
+       res = __of_device_is_compatible(device, compat, NULL, NULL);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return res;
 }
@@ -681,10 +726,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
        raw_spin_lock_irqsave(&devtree_lock, flags);
        np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
-               if (type
-                   && !(np->type && (of_node_cmp(np->type, type) == 0)))
-                       continue;
-               if (__of_device_is_compatible(np, compatible) &&
+               if (__of_device_is_compatible(np, compatible, type, NULL) &&
                    of_node_get(np))
                        break;
        }
@@ -730,65 +772,26 @@ out:
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
-static const struct of_device_id *
-of_match_compatible(const struct of_device_id *matches,
-                       const struct device_node *node)
-{
-       const char *cp;
-       int cplen, l;
-       const struct of_device_id *m;
-
-       cp = __of_get_property(node, "compatible", &cplen);
-       while (cp && (cplen > 0)) {
-               m = matches;
-               while (m->name[0] || m->type[0] || m->compatible[0]) {
-                       /* Only match for the entries without type and name */
-                       if (m->name[0] || m->type[0] ||
-                               of_compat_cmp(m->compatible, cp,
-                                        strlen(m->compatible)))
-                               m++;
-                       else
-                               return m;
-               }
-
-               /* Get node's next compatible string */
-               l = strlen(cp) + 1;
-               cp += l;
-               cplen -= l;
-       }
-
-       return NULL;
-}
-
 static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
                                           const struct device_node *node)
 {
-       const struct of_device_id *m;
+       const struct of_device_id *best_match = NULL;
+       int score, best_score = 0;
 
        if (!matches)
                return NULL;
 
-       m = of_match_compatible(matches, node);
-       if (m)
-               return m;
-
-       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
-               int match = 1;
-               if (matches->name[0])
-                       match &= node->name
-                               && !strcmp(matches->name, node->name);
-               if (matches->type[0])
-                       match &= node->type
-                               && !strcmp(matches->type, node->type);
-               if (matches->compatible[0])
-                       match &= __of_device_is_compatible(node,
-                                                          matches->compatible);
-               if (match)
-                       return matches;
-               matches++;
+       for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
+               score = __of_device_is_compatible(node, matches->compatible,
+                                                 matches->type, matches->name);
+               if (score > best_score) {
+                       best_match = matches;
+                       best_score = score;
+               }
        }
-       return NULL;
+
+       return best_match;
 }
 
 /**
@@ -796,12 +799,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
  *     @matches:       array of of device match structures to search in
  *     @node:          the of device structure to match against
  *
- *     Low level utility function used by device matching. We have two ways
- *     of matching:
- *     - Try to find the best compatible match by comparing each compatible
- *       string of device node with all the given matches respectively.
- *     - If the above method failed, then try to match the compatible by using
- *       __of_device_is_compatible() besides the match in type and name.
+ *     Low level utility function used by device matching.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                         const struct device_node *node)
index 875b7b6f0d2a48bfdac42f40d6927cf59e6cf552..5b3c24f3cde57e8f0c26f578c1ef12fd0d58d650 100644 (file)
@@ -24,7 +24,11 @@ MODULE_LICENSE("GPL");
 
 static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
-       phydev->supported |= PHY_DEFAULT_FEATURES;
+       /* The default values for phydev->supported are provided by the PHY
+        * driver "features" member, we want to reset to sane defaults fist
+        * before supporting higher speeds.
+        */
+       phydev->supported &= PHY_DEFAULT_FEATURES;
 
        switch (max_speed) {
        default:
@@ -44,7 +48,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
 {
        struct phy_device *phy;
        bool is_c45;
-       int rc, prev_irq;
+       int rc;
        u32 max_speed = 0;
 
        is_c45 = of_device_is_compatible(child,
@@ -54,12 +58,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        if (!phy || IS_ERR(phy))
                return 1;
 
-       if (mdio->irq) {
-               prev_irq = mdio->irq[addr];
-               mdio->irq[addr] =
-                       irq_of_parse_and_map(child, 0);
-               if (!mdio->irq[addr])
-                       mdio->irq[addr] = prev_irq;
+       rc = irq_of_parse_and_map(child, 0);
+       if (rc > 0) {
+               phy->irq = rc;
+               if (mdio->irq)
+                       mdio->irq[addr] = rc;
+       } else {
+               if (mdio->irq)
+                       phy->irq = mdio->irq[addr];
        }
 
        /* Associate the OF node with the device structure so it
index e21012bde639cde305a8c14aab011fad020a7da2..6643d19209857dae4f6d2d1f9a3033280e2cc25e 100644 (file)
@@ -300,6 +300,72 @@ static void __init of_selftest_parse_interrupts_extended(void)
        of_node_put(np);
 }
 
+static struct of_device_id match_node_table[] = {
+       { .data = "A", .name = "name0", }, /* Name alone is lowest priority */
+       { .data = "B", .type = "type1", }, /* followed by type alone */
+
+       { .data = "Ca", .name = "name2", .type = "type1", }, /* followed by both together */
+       { .data = "Cb", .name = "name2", }, /* Only match when type doesn't match */
+       { .data = "Cc", .name = "name2", .type = "type2", },
+
+       { .data = "E", .compatible = "compat3" },
+       { .data = "G", .compatible = "compat2", },
+       { .data = "H", .compatible = "compat2", .name = "name5", },
+       { .data = "I", .compatible = "compat2", .type = "type1", },
+       { .data = "J", .compatible = "compat2", .type = "type1", .name = "name8", },
+       { .data = "K", .compatible = "compat2", .name = "name9", },
+       {}
+};
+
+static struct {
+       const char *path;
+       const char *data;
+} match_node_tests[] = {
+       { .path = "/testcase-data/match-node/name0", .data = "A", },
+       { .path = "/testcase-data/match-node/name1", .data = "B", },
+       { .path = "/testcase-data/match-node/a/name2", .data = "Ca", },
+       { .path = "/testcase-data/match-node/b/name2", .data = "Cb", },
+       { .path = "/testcase-data/match-node/c/name2", .data = "Cc", },
+       { .path = "/testcase-data/match-node/name3", .data = "E", },
+       { .path = "/testcase-data/match-node/name4", .data = "G", },
+       { .path = "/testcase-data/match-node/name5", .data = "H", },
+       { .path = "/testcase-data/match-node/name6", .data = "G", },
+       { .path = "/testcase-data/match-node/name7", .data = "I", },
+       { .path = "/testcase-data/match-node/name8", .data = "J", },
+       { .path = "/testcase-data/match-node/name9", .data = "K", },
+};
+
+static void __init of_selftest_match_node(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) {
+               np = of_find_node_by_path(match_node_tests[i].path);
+               if (!np) {
+                       selftest(0, "missing testcase node %s\n",
+                               match_node_tests[i].path);
+                       continue;
+               }
+
+               match = of_match_node(match_node_table, np);
+               if (!match) {
+                       selftest(0, "%s didn't match anything\n",
+                               match_node_tests[i].path);
+                       continue;
+               }
+
+               if (strcmp(match->data, match_node_tests[i].data) != 0) {
+                       selftest(0, "%s got wrong match. expected %s, got %s\n",
+                               match_node_tests[i].path, match_node_tests[i].data,
+                               (const char *)match->data);
+                       continue;
+               }
+               selftest(1, "passed");
+       }
+}
+
 static int __init of_selftest(void)
 {
        struct device_node *np;
@@ -316,6 +382,7 @@ static int __init of_selftest(void)
        of_selftest_property_match_string();
        of_selftest_parse_interrupts();
        of_selftest_parse_interrupts_extended();
+       of_selftest_match_node();
        pr_info("end of selftest - %i passed, %i failed\n",
                selftest_results.passed, selftest_results.failed);
        return 0;
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi
new file mode 100644 (file)
index 0000000..3a5b75a
--- /dev/null
@@ -0,0 +1,3 @@
+#include "tests-phandle.dtsi"
+#include "tests-interrupts.dtsi"
+#include "tests-match.dtsi"
diff --git a/drivers/of/testcase-data/tests-match.dtsi b/drivers/of/testcase-data/tests-match.dtsi
new file mode 100644 (file)
index 0000000..c9e5411
--- /dev/null
@@ -0,0 +1,19 @@
+
+/ {
+       testcase-data {
+               match-node {
+                       name0 { };
+                       name1 { device_type = "type1"; };
+                       a { name2 { device_type = "type1"; }; };
+                       b { name2 { }; };
+                       c { name2 { device_type = "type2"; }; };
+                       name3 { compatible = "compat3"; };
+                       name4 { compatible = "compat2", "compat3"; };
+                       name5 { compatible = "compat2", "compat3"; };
+                       name6 { compatible = "compat1", "compat2", "compat3"; };
+                       name7 { compatible = "compat2"; device_type = "type1"; };
+                       name8 { compatible = "compat2"; device_type = "type1"; };
+                       name9 { compatible = "compat2"; };
+               };
+       };
+};
index 13478ecd411306115b666a9e344754966ce3012b..0e79665afd445ebb8e6198a274960978c58c619e 100644 (file)
 #define PCIE_DEBUG_CTRL         0x1a60
 #define  PCIE_DEBUG_SOFT_RESET         BIT(20)
 
-/*
- * This product ID is registered by Marvell, and used when the Marvell
- * SoC is not the root complex, but an endpoint on the PCIe bus. It is
- * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI
- * bridge.
- */
-#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846
-
 /* PCI configuration space of a PCI-to-PCI bridge */
 struct mvebu_sw_pci_bridge {
        u16 vendor;
@@ -388,7 +380,8 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
 
        bridge->class = PCI_CLASS_BRIDGE_PCI;
        bridge->vendor = PCI_VENDOR_ID_MARVELL;
-       bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
+       bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16;
+       bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff;
        bridge->header_type = PCI_HEADER_TYPE_BRIDGE;
        bridge->cache_line_size = 0x10;
 
index 7a0fec6ce5717baac5ef564c743d129cbc03a892..955ab7990c5bd7045f2bf896e6d4c65989176089 100644 (file)
@@ -545,9 +545,15 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
                return -ENOMEM;
        list_for_each_entry(entry, &pdev->msi_list, list) {
                char *name = kmalloc(20, GFP_KERNEL);
+               if (!name)
+                       goto error_attrs;
+
                msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
-               if (!msi_dev_attr)
+               if (!msi_dev_attr) {
+                       kfree(name);
                        goto error_attrs;
+               }
+
                sprintf(name, "%d", entry->irq);
                sysfs_attr_init(&msi_dev_attr->attr);
                msi_dev_attr->attr.name = name;
@@ -589,6 +595,7 @@ error_attrs:
                ++count;
                msi_attr = msi_attrs[count];
        }
+       kfree(msi_attrs);
        return ret;
 }
 
@@ -959,7 +966,6 @@ EXPORT_SYMBOL(pci_disable_msi);
 /**
  * pci_msix_vec_count - return the number of device's MSI-X table entries
  * @dev: pointer to the pci_dev data structure of MSI-X device function
-
  * This function returns the number of device's MSI-X table entries and
  * therefore the number of MSI-X vectors device is capable of sending.
  * It returns a negative errno if the device is not capable of sending MSI-X
index 1febe90831b442303b7414faec770d4850ca53ed..6b05f6134b68700dc1450b249b1f9bfe7b43bdca 100644 (file)
@@ -1181,6 +1181,8 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
        int err;
+       u16 cmd;
+       u8 pin;
 
        err = pci_set_power_state(dev, PCI_D0);
        if (err < 0 && err != -EIO)
@@ -1190,6 +1192,14 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
                return err;
        pci_fixup_device(pci_fixup_enable, dev);
 
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       if (pin) {
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               if (cmd & PCI_COMMAND_INTX_DISABLE)
+                       pci_write_config_word(dev, PCI_COMMAND,
+                                             cmd & ~PCI_COMMAND_INTX_DISABLE);
+       }
+
        return 0;
 }
 
index afa2354f6600e72d904ea907ee92f775010ae8a9..c7a551c2d5f1b4d39b982d85222537ec3fbfb804 100644 (file)
@@ -5,7 +5,7 @@
 menu "PHY Subsystem"
 
 config GENERIC_PHY
-       tristate "PHY Core"
+       bool "PHY Core"
        help
          Generic PHY support.
 
@@ -61,6 +61,7 @@ config PHY_EXYNOS_DP_VIDEO
 config BCM_KONA_USB2_PHY
        tristate "Broadcom Kona USB2 PHY Driver"
        depends on GENERIC_PHY
+       depends on HAS_IOMEM
        help
          Enable this to support the Broadcom Kona USB 2.0 PHY.
 
index 5f5b0f4be5be3da4e3146f4479d416306f4de9e9..6c738376daff5110a791c3c3f6492ab818971165 100644 (file)
@@ -176,6 +176,8 @@ int phy_init(struct phy *phy)
                        dev_err(&phy->dev, "phy init failed --> %d\n", ret);
                        goto out;
                }
+       } else {
+               ret = 0; /* Override possible ret == -ENOTSUPP */
        }
        ++phy->init_count;
 
@@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy)
                        dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
                        goto out;
                }
+       } else {
+               ret = 0; /* Override possible ret == -ENOTSUPP */
        }
        ++phy->power_count;
        mutex_unlock(&phy->mutex);
@@ -404,17 +408,11 @@ struct phy *phy_get(struct device *dev, const char *string)
                index = of_property_match_string(dev->of_node, "phy-names",
                        string);
                phy = of_phy_get(dev, index);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "unable to find phy\n");
-                       return phy;
-               }
        } else {
                phy = phy_lookup(dev, string);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "unable to find phy\n");
-                       return phy;
-               }
        }
+       if (IS_ERR(phy))
+               return phy;
 
        if (!try_module_get(phy->ops->owner))
                return ERR_PTR(-EPROBE_DEFER);
index 1dbe6ce7b2ce795e0a81ec3a632a8b6d6927f2bc..0786fef842e7fd878507d4342074db65b942c47b 100644 (file)
@@ -76,10 +76,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
        if (IS_ERR(state->regs))
                return PTR_ERR(state->regs);
 
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
        if (IS_ERR(phy)) {
                dev_err(dev, "failed to create Display Port PHY\n");
@@ -87,6 +83,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
        }
        phy_set_drvdata(phy, state);
 
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        return 0;
 }
 
index 0c5efab11af18a5b2b7367014747e0b34984b585..7f139326a6424e8b38d5fdd9049f26d85e679e6c 100644 (file)
@@ -134,11 +134,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
        dev_set_drvdata(dev, state);
        spin_lock_init(&state->slock);
 
-       phy_provider = devm_of_phy_provider_register(dev,
-                                       exynos_mipi_video_phy_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
                struct phy *phy = devm_phy_create(dev,
                                        &exynos_mipi_video_phy_ops, NULL);
@@ -152,6 +147,11 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
                phy_set_drvdata(phy, &state->phys[i]);
        }
 
+       phy_provider = devm_of_phy_provider_register(dev,
+                                       exynos_mipi_video_phy_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        return 0;
 }
 
index d43786f6243742ed378fb1b7d3c6756fd111381d..d70ecd6a1b3f51e60077559159912e2564e6b1a1 100644 (file)
@@ -99,17 +99,17 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
        if (IS_ERR(priv->clk))
                return PTR_ERR(priv->clk);
 
-       phy_provider = devm_of_phy_provider_register(&pdev->dev,
-                                                    of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
        if (IS_ERR(phy))
                return PTR_ERR(phy);
 
        phy_set_drvdata(phy, priv);
 
+       phy_provider = devm_of_phy_provider_register(&pdev->dev,
+                                                    of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        /* The boot loader may of left it on. Turn it off. */
        phy_mvebu_sata_power_off(phy);
 
index bfc5c337f99a8178278d9aa8f0b9b7be74f41889..7699752fba11bfbfa8acff589d794262d2882cc4 100644 (file)
@@ -177,11 +177,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
        phy->phy.otg            = otg;
        phy->phy.type           = USB_PHY_TYPE_USB2;
 
-       phy_provider = devm_of_phy_provider_register(phy->dev,
-                       of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        control_node = of_parse_phandle(node, "ctrl-module", 0);
        if (!control_node) {
                dev_err(&pdev->dev, "Failed to get control device phandle\n");
@@ -214,6 +209,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
 
        phy_set_drvdata(generic_phy, phy);
 
+       phy_provider = devm_of_phy_provider_register(phy->dev,
+                       of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
        if (IS_ERR(phy->wkupclk)) {
                dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
index daf65e68aaab53c663847e05d2dcf1fbdb035544..c3ace1db8136eedef379691bc6fa532b4ff5d67c 100644 (file)
@@ -695,11 +695,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        otg->set_host           = twl4030_set_host;
        otg->set_peripheral     = twl4030_set_peripheral;
 
-       phy_provider = devm_of_phy_provider_register(twl->dev,
-               of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        phy = devm_phy_create(twl->dev, &ops, init_data);
        if (IS_ERR(phy)) {
                dev_dbg(&pdev->dev, "Failed to create PHY\n");
@@ -708,6 +703,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 
        phy_set_drvdata(phy, twl);
 
+       phy_provider = devm_of_phy_provider_register(twl->dev,
+               of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        /* init spinlock for workqueue */
        spin_lock_init(&twl->lock);
 
index 8a843a04c22456bb5c9856a92aba876c03beeca9..a40b9c34e9fffcd2bce08169cd7a256de067027f 100644 (file)
@@ -52,8 +52,10 @@ lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
                offset = pwm_map->output[i];
 
                /* Return an error if the pin is already assigned */
-               if (test_and_set_bit(offset, &lp3943->pin_used))
+               if (test_and_set_bit(offset, &lp3943->pin_used)) {
+                       kfree(pwm_map);
                        return ERR_PTR(-EBUSY);
+               }
        }
 
        return pwm_map;
index 16a309e5c024ed45b4276d13d1f8e14c2c0a131c..d1ac4caaf1b05d4b68dd4bd986355dc59263c6fd 100644 (file)
@@ -1359,7 +1359,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
                goto found;
        /* Don't log an error when called from regulator_get_optional() */
        } else if (!have_full_constraints() || exclusive) {
-               dev_err(dev, "dummy supplies not allowed\n");
+               dev_warn(dev, "dummy supplies not allowed\n");
        }
 
        mutex_unlock(&regulator_list_mutex);
index 56727eb745df69171d77fac8313e6ea3ab2499ef..91e99a2c8dc14354c4f60368f025fef15d78786e 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Regulator driver for DA9063 PMIC series
  *
@@ -60,7 +61,8 @@ struct da9063_regulator_info {
        .desc.ops = &da9063_ldo_ops, \
        .desc.min_uV = (min_mV) * 1000, \
        .desc.uV_step = (step_mV) * 1000, \
-       .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1), \
+       .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1 \
+               + (DA9063_V##regl_name##_BIAS)), \
        .desc.enable_reg = DA9063_REG_##regl_name##_CONT, \
        .desc.enable_mask = DA9063_LDO_EN, \
        .desc.vsel_reg = DA9063_REG_V##regl_name##_A, \
index 186df8785a912483ee84050160649eb7911037c2..e0619526708c88393069abf4411fa2ff9473e510 100644 (file)
@@ -166,9 +166,10 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev)
 
        ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches,
                        MAX14577_REG_MAX);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
-       }
+       else
+               ret = 0;
 
        of_node_put(np);
 
index d7164bb75d3e0bf2a88a61c1a82e6c79072cd8b5..d958dfa051254866808fe6c36cf9db7184627b94 100644 (file)
@@ -535,7 +535,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
                return -ENODEV;
        }
 
-       regulators_np = of_find_node_by_name(pmic_np, "regulators");
+       regulators_np = of_get_child_by_name(pmic_np, "regulators");
        if (!regulators_np) {
                dev_err(iodev->dev, "could not find regulators sub-node\n");
                return -EINVAL;
@@ -591,6 +591,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
                rmode++;
        }
 
+       of_node_put(regulators_np);
+
        if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
                pdata->buck2_gpiodvs = true;
 
index f6b9188c5af581b8c0d587932c5de1af5d996951..9f0ea6cb6922619dfe04803c284002431110e11f 100644 (file)
@@ -610,6 +610,7 @@ void chsc_chp_online(struct chp_id chpid)
                css_wait_for_slow_path();
                for_each_subchannel_staged(__s390_process_res_acc, NULL,
                                           &link);
+               css_schedule_reprobe();
        }
 }
 
index dc542e0a3055a6abb63314ee6dd20ecc451c7d2d..0bc91e46395a8d84ad8c989b6d2a7844593c3ba0 100644 (file)
@@ -311,7 +311,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
        } __packed * msg = ap_msg->message;
 
        int rcblen = CEIL4(xcRB->request_control_blk_length);
-       int replylen;
+       int replylen, req_sumlen, resp_sumlen;
        char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
        char *function_code;
 
@@ -321,12 +321,34 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
                xcRB->request_data_length;
        if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
                return -EINVAL;
+
+       /* Overflow check
+          sum must be greater (or equal) than the largest operand */
+       req_sumlen = CEIL4(xcRB->request_control_blk_length) +
+                       xcRB->request_data_length;
+       if ((CEIL4(xcRB->request_control_blk_length) <=
+                                               xcRB->request_data_length) ?
+               (req_sumlen < xcRB->request_data_length) :
+               (req_sumlen < CEIL4(xcRB->request_control_blk_length))) {
+               return -EINVAL;
+       }
+
        replylen = sizeof(struct type86_fmt2_msg) +
                CEIL4(xcRB->reply_control_blk_length) +
                xcRB->reply_data_length;
        if (replylen > MSGTYPE06_MAX_MSG_SIZE)
                return -EINVAL;
 
+       /* Overflow check
+          sum must be greater (or equal) than the largest operand */
+       resp_sumlen = CEIL4(xcRB->reply_control_blk_length) +
+                       xcRB->reply_data_length;
+       if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ?
+               (resp_sumlen < xcRB->reply_data_length) :
+               (resp_sumlen < CEIL4(xcRB->reply_control_blk_length))) {
+               return -EINVAL;
+       }
+
        /* prepare type6 header */
        msg->hdr = static_type6_hdrX;
        memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
index 6b4678a7900a086e711d4bf9a7f6004bc2efcb3c..4ccb5d869389e353113692d20f02f66d002046cd 100644 (file)
@@ -507,7 +507,6 @@ static int jsflash_init(void)
        }
 
        /* Let us be really paranoid for modifications to probing code. */
-       /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
        if (sparc_cpu_model != sun4m) {
                /* We must be on sun4m because we use MMU Bypass ASI. */
                return -ENXIO;
index 2eb97d7e8d122e21f7d3128270846754b4561313..0cb73074c1997409c4e63f6d39ac51e641eff088 100644 (file)
@@ -790,17 +790,32 @@ static inline int test_tgt_sess_count(struct qla_tgt *tgt)
 }
 
 /* Called by tcm_qla2xxx configfs code */
-void qlt_stop_phase1(struct qla_tgt *tgt)
+int qlt_stop_phase1(struct qla_tgt *tgt)
 {
        struct scsi_qla_host *vha = tgt->vha;
        struct qla_hw_data *ha = tgt->ha;
        unsigned long flags;
 
+       mutex_lock(&qla_tgt_mutex);
+       if (!vha->fc_vport) {
+               struct Scsi_Host *sh = vha->host;
+               struct fc_host_attrs *fc_host = shost_to_fc_host(sh);
+               bool npiv_vports;
+
+               spin_lock_irqsave(sh->host_lock, flags);
+               npiv_vports = (fc_host->npiv_vports_inuse);
+               spin_unlock_irqrestore(sh->host_lock, flags);
+
+               if (npiv_vports) {
+                       mutex_unlock(&qla_tgt_mutex);
+                       return -EPERM;
+               }
+       }
        if (tgt->tgt_stop || tgt->tgt_stopped) {
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e,
                    "Already in tgt->tgt_stop or tgt_stopped state\n");
-               dump_stack();
-               return;
+               mutex_unlock(&qla_tgt_mutex);
+               return -EPERM;
        }
 
        ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
@@ -815,6 +830,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt)
        qlt_clear_tgt_db(tgt, true);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
        mutex_unlock(&vha->vha_tgt.tgt_mutex);
+       mutex_unlock(&qla_tgt_mutex);
 
        flush_delayed_work(&tgt->sess_del_work);
 
@@ -841,6 +857,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt)
 
        /* Wait for sessions to clear out (just in case) */
        wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
+       return 0;
 }
 EXPORT_SYMBOL(qlt_stop_phase1);
 
@@ -3185,7 +3202,8 @@ restart:
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c,
                    "SRR cmd %p (se_cmd %p, tag %d, op %x), "
                    "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag,
-                   se_cmd->t_task_cdb[0], cmd->sg_cnt, cmd->offset);
+                   se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0,
+                   cmd->sg_cnt, cmd->offset);
 
                qlt_handle_srr(vha, sctio, imm);
 
@@ -4181,6 +4199,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
        tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
        tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
 
+       if (base_vha->fc_vport)
+               return 0;
+
        mutex_lock(&qla_tgt_mutex);
        list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
        mutex_unlock(&qla_tgt_mutex);
@@ -4194,6 +4215,10 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
        if (!vha->vha_tgt.qla_tgt)
                return 0;
 
+       if (vha->fc_vport) {
+               qlt_release(vha->vha_tgt.qla_tgt);
+               return 0;
+       }
        mutex_lock(&qla_tgt_mutex);
        list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry);
        mutex_unlock(&qla_tgt_mutex);
@@ -4265,6 +4290,12 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
                        continue;
                }
+               if (tgt->tgt_stop) {
+                       pr_debug("MODE_TARGET in shutdown on qla2xxx(%d)\n",
+                                host->host_no);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+                       continue;
+               }
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
                if (!scsi_host_get(host)) {
@@ -4279,12 +4310,11 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
                        scsi_host_put(host);
                        continue;
                }
-               mutex_unlock(&qla_tgt_mutex);
-
                rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn);
                if (rc != 0)
                        scsi_host_put(host);
 
+               mutex_unlock(&qla_tgt_mutex);
                return rc;
        }
        mutex_unlock(&qla_tgt_mutex);
index 66e755cdde573c47e902b1f45e0ac65b18d772bd..ce33d8c26406da00ccb67943093bae5f3fdec0b9 100644 (file)
@@ -1001,7 +1001,7 @@ extern void qlt_modify_vp_config(struct scsi_qla_host *,
 extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
 extern int qlt_mem_alloc(struct qla_hw_data *);
 extern void qlt_mem_free(struct qla_hw_data *);
-extern void qlt_stop_phase1(struct qla_tgt *);
+extern int qlt_stop_phase1(struct qla_tgt *);
 extern void qlt_stop_phase2(struct qla_tgt *);
 extern irqreturn_t qla83xx_msix_atio_q(int, void *);
 extern void qlt_83xx_iospace_config(struct qla_hw_data *);
index 75a141bbe74d178834a9f58c6fc723734e63758f..788c4fe2b0c9ec7a8113078c318421d7407ae855 100644 (file)
@@ -182,20 +182,6 @@ static int tcm_qla2xxx_npiv_parse_wwn(
        return 0;
 }
 
-static ssize_t tcm_qla2xxx_npiv_format_wwn(char *buf, size_t len,
-                                       u64 wwpn, u64 wwnn)
-{
-       u8 b[8], b2[8];
-
-       put_unaligned_be64(wwpn, b);
-       put_unaligned_be64(wwnn, b2);
-       return snprintf(buf, len,
-               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x,"
-               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
-               b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
-               b2[0], b2[1], b2[2], b2[3], b2[4], b2[5], b2[6], b2[7]);
-}
-
 static char *tcm_qla2xxx_npiv_get_fabric_name(void)
 {
        return "qla2xxx_npiv";
@@ -227,15 +213,6 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
        return lport->lport_naa_name;
 }
 
-static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
-{
-       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
-                               struct tcm_qla2xxx_tpg, se_tpg);
-       struct tcm_qla2xxx_lport *lport = tpg->lport;
-
-       return &lport->lport_npiv_name[0];
-}
-
 static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg)
 {
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
@@ -941,15 +918,41 @@ static ssize_t tcm_qla2xxx_tpg_show_enable(
                        atomic_read(&tpg->lport_tpg_enabled));
 }
 
+static void tcm_qla2xxx_depend_tpg(struct work_struct *work)
+{
+       struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
+                               struct tcm_qla2xxx_tpg, tpg_base_work);
+       struct se_portal_group *se_tpg = &base_tpg->se_tpg;
+       struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
+
+       if (!configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
+                                 &se_tpg->tpg_group.cg_item)) {
+               atomic_set(&base_tpg->lport_tpg_enabled, 1);
+               qlt_enable_vha(base_vha);
+       }
+       complete(&base_tpg->tpg_base_comp);
+}
+
+static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)
+{
+       struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
+                               struct tcm_qla2xxx_tpg, tpg_base_work);
+       struct se_portal_group *se_tpg = &base_tpg->se_tpg;
+       struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
+
+       if (!qlt_stop_phase1(base_vha->vha_tgt.qla_tgt)) {
+               atomic_set(&base_tpg->lport_tpg_enabled, 0);
+               configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
+                                      &se_tpg->tpg_group.cg_item);
+       }
+       complete(&base_tpg->tpg_base_comp);
+}
+
 static ssize_t tcm_qla2xxx_tpg_store_enable(
        struct se_portal_group *se_tpg,
        const char *page,
        size_t count)
 {
-       struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
-       struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
-                       struct tcm_qla2xxx_lport, lport_wwn);
-       struct scsi_qla_host *vha = lport->qla_vha;
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
                        struct tcm_qla2xxx_tpg, se_tpg);
        unsigned long op;
@@ -964,19 +967,28 @@ static ssize_t tcm_qla2xxx_tpg_store_enable(
                pr_err("Illegal value for tpg_enable: %lu\n", op);
                return -EINVAL;
        }
-
        if (op) {
-               atomic_set(&tpg->lport_tpg_enabled, 1);
-               qlt_enable_vha(vha);
+               if (atomic_read(&tpg->lport_tpg_enabled))
+                       return -EEXIST;
+
+               INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_depend_tpg);
        } else {
-               if (!vha->vha_tgt.qla_tgt) {
-                       pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n");
-                       return -ENODEV;
-               }
-               atomic_set(&tpg->lport_tpg_enabled, 0);
-               qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+               if (!atomic_read(&tpg->lport_tpg_enabled))
+                       return count;
+
+               INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_undepend_tpg);
        }
+       init_completion(&tpg->tpg_base_comp);
+       schedule_work(&tpg->tpg_base_work);
+       wait_for_completion(&tpg->tpg_base_comp);
 
+       if (op) {
+               if (!atomic_read(&tpg->lport_tpg_enabled))
+                       return -ENODEV;
+       } else {
+               if (atomic_read(&tpg->lport_tpg_enabled))
+                       return -EPERM;
+       }
        return count;
 }
 
@@ -1053,11 +1065,64 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg)
        /*
         * Clear local TPG=1 pointer for non NPIV mode.
         */
-               lport->tpg_1 = NULL;
-
+       lport->tpg_1 = NULL;
        kfree(tpg);
 }
 
+static ssize_t tcm_qla2xxx_npiv_tpg_show_enable(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       return tcm_qla2xxx_tpg_show_enable(se_tpg, page);
+}
+
+static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
+       struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
+                       struct tcm_qla2xxx_lport, lport_wwn);
+       struct scsi_qla_host *vha = lport->qla_vha;
+       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+                       struct tcm_qla2xxx_tpg, se_tpg);
+       unsigned long op;
+       int rc;
+
+       rc = kstrtoul(page, 0, &op);
+       if (rc < 0) {
+               pr_err("kstrtoul() returned %d\n", rc);
+               return -EINVAL;
+       }
+       if ((op != 1) && (op != 0)) {
+               pr_err("Illegal value for tpg_enable: %lu\n", op);
+               return -EINVAL;
+       }
+       if (op) {
+               if (atomic_read(&tpg->lport_tpg_enabled))
+                       return -EEXIST;
+
+               atomic_set(&tpg->lport_tpg_enabled, 1);
+               qlt_enable_vha(vha);
+       } else {
+               if (!atomic_read(&tpg->lport_tpg_enabled))
+                       return count;
+
+               atomic_set(&tpg->lport_tpg_enabled, 0);
+               qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+       }
+
+       return count;
+}
+
+TF_TPG_BASE_ATTR(tcm_qla2xxx_npiv, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = {
+        &tcm_qla2xxx_npiv_tpg_enable.attr,
+        NULL,
+};
+
 static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
        struct se_wwn *wwn,
        struct config_group *group,
@@ -1650,6 +1715,9 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
        struct scsi_qla_host *npiv_vha;
        struct tcm_qla2xxx_lport *lport =
                        (struct tcm_qla2xxx_lport *)target_lport_ptr;
+       struct tcm_qla2xxx_lport *base_lport =
+                       (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
+       struct tcm_qla2xxx_tpg *base_tpg;
        struct fc_vport_identifiers vport_id;
 
        if (!qla_tgt_mode_enabled(base_vha)) {
@@ -1657,6 +1725,13 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
                return -EPERM;
        }
 
+       if (!base_lport || !base_lport->tpg_1 ||
+           !atomic_read(&base_lport->tpg_1->lport_tpg_enabled)) {
+               pr_err("qla2xxx base_lport or tpg_1 not available\n");
+               return -EPERM;
+       }
+       base_tpg = base_lport->tpg_1;
+
        memset(&vport_id, 0, sizeof(vport_id));
        vport_id.port_name = npiv_wwpn;
        vport_id.node_name = npiv_wwnn;
@@ -1675,7 +1750,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
        npiv_vha = (struct scsi_qla_host *)vport->dd_data;
        npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr;
        lport->qla_vha = npiv_vha;
-
        scsi_host_get(npiv_vha->host);
        return 0;
 }
@@ -1714,8 +1788,6 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
        }
        lport->lport_npiv_wwpn = npiv_wwpn;
        lport->lport_npiv_wwnn = npiv_wwnn;
-       tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
-                       TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
        sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
 
        ret = tcm_qla2xxx_init_lport(lport);
@@ -1824,7 +1896,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
 static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
        .get_fabric_name                = tcm_qla2xxx_npiv_get_fabric_name,
        .get_fabric_proto_ident         = tcm_qla2xxx_get_fabric_proto_ident,
-       .tpg_get_wwn                    = tcm_qla2xxx_npiv_get_fabric_wwn,
+       .tpg_get_wwn                    = tcm_qla2xxx_get_fabric_wwn,
        .tpg_get_tag                    = tcm_qla2xxx_get_tag,
        .tpg_get_default_depth          = tcm_qla2xxx_get_default_depth,
        .tpg_get_pr_transport_id        = tcm_qla2xxx_get_pr_transport_id,
@@ -1935,7 +2007,7 @@ static int tcm_qla2xxx_register_configfs(void)
         */
        npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs =
-           tcm_qla2xxx_tpg_attrs;
+           tcm_qla2xxx_npiv_tpg_attrs;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
index 275d8b9a7a34121d4d7d356659bfe92816219a3f..33aaac8c7d5936bbdd3e2d9f934f2c92f2083331 100644 (file)
@@ -4,8 +4,6 @@
 #define TCM_QLA2XXX_VERSION    "v0.1"
 /* length of ASCII WWPNs including pad */
 #define TCM_QLA2XXX_NAMELEN    32
-/* lenth of ASCII NPIV 'WWPN+WWNN' including pad */
-#define TCM_QLA2XXX_NPIV_NAMELEN 66
 
 #include "qla_target.h"
 
@@ -43,6 +41,9 @@ struct tcm_qla2xxx_tpg {
        struct tcm_qla2xxx_tpg_attrib tpg_attrib;
        /* Returned by tcm_qla2xxx_make_tpg() */
        struct se_portal_group se_tpg;
+       /* Items for dealing with configfs_depend_item */
+       struct completion tpg_base_comp;
+       struct work_struct tpg_base_work;
 };
 
 struct tcm_qla2xxx_fc_loopid {
@@ -62,8 +63,6 @@ struct tcm_qla2xxx_lport {
        char lport_name[TCM_QLA2XXX_NAMELEN];
        /* ASCII formatted naa WWPN for VPD page 83 etc */
        char lport_naa_name[TCM_QLA2XXX_NAMELEN];
-       /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
-       char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
        /* map for fc_port pointers in 24-bit FC Port ID space */
        struct btree_head32 lport_fcport_map;
        /* vmalloc-ed memory for fc_port pointers for 16-bit FC loop ID */
index 7bd7f0d5f050a2ece3f176b1f05ca2f8936270a3..62ec84b42e31cfb77f1aad4e040da30e3a104ef6 100644 (file)
@@ -1684,7 +1684,7 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
 
        host_dev = scsi_get_device(shost);
        if (host_dev && host_dev->dma_mask)
-               bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT;
+               bounce_limit = (u64)dma_max_pfn(host_dev) << PAGE_SHIFT;
 
        return bounce_limit;
 }
index babb1cf67ce76505b1cc9f1b9654ea194751a081..47cf175430082c792424fdd1fbf52b353279f60b 100644 (file)
@@ -34,8 +34,6 @@ source "drivers/staging/winbond/Kconfig"
 
 source "drivers/staging/wlan-ng/Kconfig"
 
-source "drivers/staging/echo/Kconfig"
-
 source "drivers/staging/comedi/Kconfig"
 
 source "drivers/staging/olpc_dcon/Kconfig"
@@ -82,8 +80,6 @@ source "drivers/staging/wlags49_h2/Kconfig"
 
 source "drivers/staging/wlags49_h25/Kconfig"
 
-source "drivers/staging/sm7xxfb/Kconfig"
-
 source "drivers/staging/crystalhd/Kconfig"
 
 source "drivers/staging/cxt1e1/Kconfig"
@@ -128,8 +124,6 @@ source "drivers/staging/imx-drm/Kconfig"
 
 source "drivers/staging/dgrp/Kconfig"
 
-source "drivers/staging/sb105x/Kconfig"
-
 source "drivers/staging/fwserial/Kconfig"
 
 source "drivers/staging/goldfish/Kconfig"
@@ -150,4 +144,6 @@ source "drivers/staging/gs_fpgaboot/Kconfig"
 
 source "drivers/staging/nokia_h4p/Kconfig"
 
+source "drivers/staging/unisys/Kconfig"
+
 endif # STAGING
index 2c4949a9bd9b5839d0027d513ff5f473bc80d1e9..d12f6189db46ac8773923941d2ad68fd93ee9a17 100644 (file)
@@ -9,7 +9,6 @@ obj-$(CONFIG_SLICOSS)           += slicoss/
 obj-$(CONFIG_USBIP_CORE)       += usbip/
 obj-$(CONFIG_W35UND)           += winbond/
 obj-$(CONFIG_PRISM2_USB)       += wlan-ng/
-obj-$(CONFIG_ECHO)             += echo/
 obj-$(CONFIG_COMEDI)           += comedi/
 obj-$(CONFIG_FB_OLPC_DCON)     += olpc_dcon/
 obj-$(CONFIG_PANEL)            += panel/
@@ -35,7 +34,6 @@ obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)              += iio/
 obj-$(CONFIG_WLAGS49_H2)       += wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)      += wlags49_h25/
-obj-$(CONFIG_FB_SM7XX)         += sm7xxfb/
 obj-$(CONFIG_CRYSTALHD)                += crystalhd/
 obj-$(CONFIG_CXT1E1)           += cxt1e1/
 obj-$(CONFIG_FB_XGI)           += xgifb/
@@ -57,7 +55,6 @@ obj-$(CONFIG_NET_VENDOR_SILICOM)      += silicom/
 obj-$(CONFIG_CED1401)          += ced1401/
 obj-$(CONFIG_DRM_IMX)          += imx-drm/
 obj-$(CONFIG_DGRP)             += dgrp/
-obj-$(CONFIG_SB105X)           += sb105x/
 obj-$(CONFIG_FIREWIRE_SERIAL)  += fwserial/
 obj-$(CONFIG_GOLDFISH)         += goldfish/
 obj-$(CONFIG_LUSTRE_FS)                += lustre/
@@ -67,3 +64,4 @@ obj-$(CONFIG_DGAP)                    += dgap/
 obj-$(CONFIG_MTD_SPINAND_MT29F)        += mt29f_spinand/
 obj-$(CONFIG_GS_FPGABOOT)      += gs_fpgaboot/
 obj-$(CONFIG_BT_NOKIA_H4P)     += nokia_h4p/
+obj-$(CONFIG_UNISYSSPAR)       += unisys/
index b91c758883bf415162fcb9e67da5a5099ee69a58..ab28d2b5e308155e7e12ebae447b6a7ae5b66e09 100644 (file)
@@ -20,6 +20,19 @@ config ANDROID_BINDER_IPC
          Android process, using Binder to identify, invoke and pass arguments
          between said processes.
 
+config ANDROID_BINDER_IPC_32BIT
+       bool
+       depends on !64BIT && ANDROID_BINDER_IPC
+       default y
+       ---help---
+         The Binder API has been changed to support both 32 and 64bit
+         applications in a mixed environment.
+
+         Enable this to support an old 32-bit Android user-space (v4.4 and
+         earlier).
+
+         Note that enabling this will break newer Android user-space.
+
 config ASHMEM
        bool "Enable the Anonymous Shared Memory Subsystem"
        default n
index eaec1dab7fe489fbbc9d171a4acdf5f78d765df6..cfe4bc8f05cb82ec83b4e127ba53f8e72968a85c 100644 (file)
@@ -228,8 +228,8 @@ struct binder_node {
        int internal_strong_refs;
        int local_weak_refs;
        int local_strong_refs;
-       void __user *ptr;
-       void __user *cookie;
+       binder_uintptr_t ptr;
+       binder_uintptr_t cookie;
        unsigned has_strong_ref:1;
        unsigned pending_strong_ref:1;
        unsigned has_weak_ref:1;
@@ -242,7 +242,7 @@ struct binder_node {
 
 struct binder_ref_death {
        struct binder_work work;
-       void __user *cookie;
+       binder_uintptr_t cookie;
 };
 
 struct binder_ref {
@@ -515,14 +515,14 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc,
 }
 
 static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
-                                                 void __user *user_ptr)
+                                                 uintptr_t user_ptr)
 {
        struct rb_node *n = proc->allocated_buffers.rb_node;
        struct binder_buffer *buffer;
        struct binder_buffer *kern_ptr;
 
-       kern_ptr = user_ptr - proc->user_buffer_offset
-               - offsetof(struct binder_buffer, data);
+       kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset
+               - offsetof(struct binder_buffer, data));
 
        while (n) {
                buffer = rb_entry(n, struct binder_buffer, rb_node);
@@ -856,7 +856,7 @@ static void binder_free_buf(struct binder_proc *proc,
 }
 
 static struct binder_node *binder_get_node(struct binder_proc *proc,
-                                          void __user *ptr)
+                                          binder_uintptr_t ptr)
 {
        struct rb_node *n = proc->nodes.rb_node;
        struct binder_node *node;
@@ -875,8 +875,8 @@ static struct binder_node *binder_get_node(struct binder_proc *proc,
 }
 
 static struct binder_node *binder_new_node(struct binder_proc *proc,
-                                          void __user *ptr,
-                                          void __user *cookie)
+                                          binder_uintptr_t ptr,
+                                          binder_uintptr_t cookie)
 {
        struct rb_node **p = &proc->nodes.rb_node;
        struct rb_node *parent = NULL;
@@ -908,9 +908,9 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
        INIT_LIST_HEAD(&node->work.entry);
        INIT_LIST_HEAD(&node->async_todo);
        binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-                    "%d:%d node %d u%p c%p created\n",
+                    "%d:%d node %d u%016llx c%016llx created\n",
                     proc->pid, current->pid, node->debug_id,
-                    node->ptr, node->cookie);
+                    (u64)node->ptr, (u64)node->cookie);
        return node;
 }
 
@@ -1226,9 +1226,9 @@ static void binder_send_failed_reply(struct binder_transaction *t,
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
                                              struct binder_buffer *buffer,
-                                             size_t *failed_at)
+                                             binder_size_t *failed_at)
 {
-       size_t *offp, *off_end;
+       binder_size_t *offp, *off_end;
        int debug_id = buffer->debug_id;
 
        binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1239,7 +1239,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
        if (buffer->target_node)
                binder_dec_node(buffer->target_node, 1, 0);
 
-       offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+       offp = (binder_size_t *)(buffer->data +
+                                ALIGN(buffer->data_size, sizeof(void *)));
        if (failed_at)
                off_end = failed_at;
        else
@@ -1249,8 +1250,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
                if (*offp > buffer->data_size - sizeof(*fp) ||
                    buffer->data_size < sizeof(*fp) ||
                    !IS_ALIGNED(*offp, sizeof(u32))) {
-                       pr_err("transaction release %d bad offset %zd, size %zd\n",
-                        debug_id, *offp, buffer->data_size);
+                       pr_err("transaction release %d bad offset %lld, size %zd\n",
+                              debug_id, (u64)*offp, buffer->data_size);
                        continue;
                }
                fp = (struct flat_binder_object *)(buffer->data + *offp);
@@ -1259,13 +1260,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
                case BINDER_TYPE_WEAK_BINDER: {
                        struct binder_node *node = binder_get_node(proc, fp->binder);
                        if (node == NULL) {
-                               pr_err("transaction release %d bad node %p\n",
-                                       debug_id, fp->binder);
+                               pr_err("transaction release %d bad node %016llx\n",
+                                      debug_id, (u64)fp->binder);
                                break;
                        }
                        binder_debug(BINDER_DEBUG_TRANSACTION,
-                                    "        node %d u%p\n",
-                                    node->debug_id, node->ptr);
+                                    "        node %d u%016llx\n",
+                                    node->debug_id, (u64)node->ptr);
                        binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
                } break;
                case BINDER_TYPE_HANDLE:
@@ -1303,7 +1304,7 @@ static void binder_transaction(struct binder_proc *proc,
 {
        struct binder_transaction *t;
        struct binder_work *tcomplete;
-       size_t *offp, *off_end;
+       binder_size_t *offp, *off_end;
        struct binder_proc *target_proc;
        struct binder_thread *target_thread = NULL;
        struct binder_node *target_node = NULL;
@@ -1432,18 +1433,20 @@ static void binder_transaction(struct binder_proc *proc,
 
        if (reply)
                binder_debug(BINDER_DEBUG_TRANSACTION,
-                            "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n",
+                            "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n",
                             proc->pid, thread->pid, t->debug_id,
                             target_proc->pid, target_thread->pid,
-                            tr->data.ptr.buffer, tr->data.ptr.offsets,
-                            tr->data_size, tr->offsets_size);
+                            (u64)tr->data.ptr.buffer,
+                            (u64)tr->data.ptr.offsets,
+                            (u64)tr->data_size, (u64)tr->offsets_size);
        else
                binder_debug(BINDER_DEBUG_TRANSACTION,
-                            "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n",
+                            "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n",
                             proc->pid, thread->pid, t->debug_id,
                             target_proc->pid, target_node->debug_id,
-                            tr->data.ptr.buffer, tr->data.ptr.offsets,
-                            tr->data_size, tr->offsets_size);
+                            (u64)tr->data.ptr.buffer,
+                            (u64)tr->data.ptr.offsets,
+                            (u64)tr->data_size, (u64)tr->offsets_size);
 
        if (!reply && !(tr->flags & TF_ONE_WAY))
                t->from = thread;
@@ -1472,23 +1475,26 @@ static void binder_transaction(struct binder_proc *proc,
        if (target_node)
                binder_inc_node(target_node, 1, 0, NULL);
 
-       offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+       offp = (binder_size_t *)(t->buffer->data +
+                                ALIGN(tr->data_size, sizeof(void *)));
 
-       if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+       if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
+                          tr->data.ptr.buffer, tr->data_size)) {
                binder_user_error("%d:%d got transaction with invalid data ptr\n",
                                proc->pid, thread->pid);
                return_error = BR_FAILED_REPLY;
                goto err_copy_data_failed;
        }
-       if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+       if (copy_from_user(offp, (const void __user *)(uintptr_t)
+                          tr->data.ptr.offsets, tr->offsets_size)) {
                binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
                                proc->pid, thread->pid);
                return_error = BR_FAILED_REPLY;
                goto err_copy_data_failed;
        }
-       if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
-               binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n",
-                               proc->pid, thread->pid, tr->offsets_size);
+       if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) {
+               binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n",
+                               proc->pid, thread->pid, (u64)tr->offsets_size);
                return_error = BR_FAILED_REPLY;
                goto err_bad_offset;
        }
@@ -1498,8 +1504,8 @@ static void binder_transaction(struct binder_proc *proc,
                if (*offp > t->buffer->data_size - sizeof(*fp) ||
                    t->buffer->data_size < sizeof(*fp) ||
                    !IS_ALIGNED(*offp, sizeof(u32))) {
-                       binder_user_error("%d:%d got transaction with invalid offset, %zd\n",
-                                       proc->pid, thread->pid, *offp);
+                       binder_user_error("%d:%d got transaction with invalid offset, %lld\n",
+                                         proc->pid, thread->pid, (u64)*offp);
                        return_error = BR_FAILED_REPLY;
                        goto err_bad_offset;
                }
@@ -1519,10 +1525,10 @@ static void binder_transaction(struct binder_proc *proc,
                                node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
                        }
                        if (fp->cookie != node->cookie) {
-                               binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n",
+                               binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
                                        proc->pid, thread->pid,
-                                       fp->binder, node->debug_id,
-                                       fp->cookie, node->cookie);
+                                       (u64)fp->binder, node->debug_id,
+                                       (u64)fp->cookie, (u64)node->cookie);
                                goto err_binder_get_ref_for_node_failed;
                        }
                        ref = binder_get_ref_for_node(target_proc, node);
@@ -1540,9 +1546,9 @@ static void binder_transaction(struct binder_proc *proc,
 
                        trace_binder_transaction_node_to_ref(t, node, ref);
                        binder_debug(BINDER_DEBUG_TRANSACTION,
-                                    "        node %d u%p -> ref %d desc %d\n",
-                                    node->debug_id, node->ptr, ref->debug_id,
-                                    ref->desc);
+                                    "        node %d u%016llx -> ref %d desc %d\n",
+                                    node->debug_id, (u64)node->ptr,
+                                    ref->debug_id, ref->desc);
                } break;
                case BINDER_TYPE_HANDLE:
                case BINDER_TYPE_WEAK_HANDLE: {
@@ -1564,9 +1570,9 @@ static void binder_transaction(struct binder_proc *proc,
                                binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
                                trace_binder_transaction_ref_to_node(t, ref);
                                binder_debug(BINDER_DEBUG_TRANSACTION,
-                                            "        ref %d desc %d -> node %d u%p\n",
+                                            "        ref %d desc %d -> node %d u%016llx\n",
                                             ref->debug_id, ref->desc, ref->node->debug_id,
-                                            ref->node->ptr);
+                                            (u64)ref->node->ptr);
                        } else {
                                struct binder_ref *new_ref;
                                new_ref = binder_get_ref_for_node(target_proc, ref->node);
@@ -1682,9 +1688,9 @@ err_dead_binder:
 err_invalid_target_handle:
 err_no_context_mgr_node:
        binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-                    "%d:%d transaction failed %d, size %zd-%zd\n",
+                    "%d:%d transaction failed %d, size %lld-%lld\n",
                     proc->pid, thread->pid, return_error,
-                    tr->data_size, tr->offsets_size);
+                    (u64)tr->data_size, (u64)tr->offsets_size);
 
        {
                struct binder_transaction_log_entry *fe;
@@ -1702,9 +1708,11 @@ err_no_context_mgr_node:
 
 static int binder_thread_write(struct binder_proc *proc,
                        struct binder_thread *thread,
-                       void __user *buffer, size_t size, size_t *consumed)
+                       binder_uintptr_t binder_buffer, size_t size,
+                       binder_size_t *consumed)
 {
        uint32_t cmd;
+       void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
        void __user *ptr = buffer + *consumed;
        void __user *end = buffer + size;
 
@@ -1773,33 +1781,33 @@ static int binder_thread_write(struct binder_proc *proc,
                }
                case BC_INCREFS_DONE:
                case BC_ACQUIRE_DONE: {
-                       void __user *node_ptr;
-                       void __user *cookie;
+                       binder_uintptr_t node_ptr;
+                       binder_uintptr_t cookie;
                        struct binder_node *node;
 
-                       if (get_user(node_ptr, (void * __user *)ptr))
+                       if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
-                       if (get_user(cookie, (void * __user *)ptr))
+                       ptr += sizeof(binder_uintptr_t);
+                       if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(binder_uintptr_t);
                        node = binder_get_node(proc, node_ptr);
                        if (node == NULL) {
-                               binder_user_error("%d:%d %s u%p no match\n",
+                               binder_user_error("%d:%d %s u%016llx no match\n",
                                        proc->pid, thread->pid,
                                        cmd == BC_INCREFS_DONE ?
                                        "BC_INCREFS_DONE" :
                                        "BC_ACQUIRE_DONE",
-                                       node_ptr);
+                                       (u64)node_ptr);
                                break;
                        }
                        if (cookie != node->cookie) {
-                               binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n",
+                               binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n",
                                        proc->pid, thread->pid,
                                        cmd == BC_INCREFS_DONE ?
                                        "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-                                       node_ptr, node->debug_id,
-                                       cookie, node->cookie);
+                                       (u64)node_ptr, node->debug_id,
+                                       (u64)cookie, (u64)node->cookie);
                                break;
                        }
                        if (cmd == BC_ACQUIRE_DONE) {
@@ -1835,27 +1843,28 @@ static int binder_thread_write(struct binder_proc *proc,
                        return -EINVAL;
 
                case BC_FREE_BUFFER: {
-                       void __user *data_ptr;
+                       binder_uintptr_t data_ptr;
                        struct binder_buffer *buffer;
 
-                       if (get_user(data_ptr, (void * __user *)ptr))
+                       if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(binder_uintptr_t);
 
                        buffer = binder_buffer_lookup(proc, data_ptr);
                        if (buffer == NULL) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n",
-                                       proc->pid, thread->pid, data_ptr);
+                               binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
+                                       proc->pid, thread->pid, (u64)data_ptr);
                                break;
                        }
                        if (!buffer->allow_user_free) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n",
-                                       proc->pid, thread->pid, data_ptr);
+                               binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
+                                       proc->pid, thread->pid, (u64)data_ptr);
                                break;
                        }
                        binder_debug(BINDER_DEBUG_FREE_BUFFER,
-                                    "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
-                                    proc->pid, thread->pid, data_ptr, buffer->debug_id,
+                                    "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
+                                    proc->pid, thread->pid, (u64)data_ptr,
+                                    buffer->debug_id,
                                     buffer->transaction ? "active" : "finished");
 
                        if (buffer->transaction) {
@@ -1925,16 +1934,16 @@ static int binder_thread_write(struct binder_proc *proc,
                case BC_REQUEST_DEATH_NOTIFICATION:
                case BC_CLEAR_DEATH_NOTIFICATION: {
                        uint32_t target;
-                       void __user *cookie;
+                       binder_uintptr_t cookie;
                        struct binder_ref *ref;
                        struct binder_ref_death *death;
 
                        if (get_user(target, (uint32_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(uint32_t);
-                       if (get_user(cookie, (void __user * __user *)ptr))
+                       if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(binder_uintptr_t);
                        ref = binder_get_ref(proc, target);
                        if (ref == NULL) {
                                binder_user_error("%d:%d %s invalid ref %d\n",
@@ -1947,12 +1956,12 @@ static int binder_thread_write(struct binder_proc *proc,
                        }
 
                        binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-                                    "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+                                    "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n",
                                     proc->pid, thread->pid,
                                     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
                                     "BC_REQUEST_DEATH_NOTIFICATION" :
                                     "BC_CLEAR_DEATH_NOTIFICATION",
-                                    cookie, ref->debug_id, ref->desc,
+                                    (u64)cookie, ref->debug_id, ref->desc,
                                     ref->strong, ref->weak, ref->node->debug_id);
 
                        if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
@@ -1990,9 +1999,10 @@ static int binder_thread_write(struct binder_proc *proc,
                                }
                                death = ref->death;
                                if (death->cookie != cookie) {
-                                       binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
+                                       binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n",
                                                proc->pid, thread->pid,
-                                               death->cookie, cookie);
+                                               (u64)death->cookie,
+                                               (u64)cookie);
                                        break;
                                }
                                ref->death = NULL;
@@ -2012,9 +2022,9 @@ static int binder_thread_write(struct binder_proc *proc,
                } break;
                case BC_DEAD_BINDER_DONE: {
                        struct binder_work *w;
-                       void __user *cookie;
+                       binder_uintptr_t cookie;
                        struct binder_ref_death *death = NULL;
-                       if (get_user(cookie, (void __user * __user *)ptr))
+                       if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
 
                        ptr += sizeof(void *);
@@ -2026,11 +2036,12 @@ static int binder_thread_write(struct binder_proc *proc,
                                }
                        }
                        binder_debug(BINDER_DEBUG_DEAD_BINDER,
-                                    "%d:%d BC_DEAD_BINDER_DONE %p found %p\n",
-                                    proc->pid, thread->pid, cookie, death);
+                                    "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n",
+                                    proc->pid, thread->pid, (u64)cookie,
+                                    death);
                        if (death == NULL) {
-                               binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
-                                       proc->pid, thread->pid, cookie);
+                               binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n",
+                                       proc->pid, thread->pid, (u64)cookie);
                                break;
                        }
 
@@ -2082,9 +2093,10 @@ static int binder_has_thread_work(struct binder_thread *thread)
 
 static int binder_thread_read(struct binder_proc *proc,
                              struct binder_thread *thread,
-                             void  __user *buffer, size_t size,
-                             size_t *consumed, int non_block)
+                             binder_uintptr_t binder_buffer, size_t size,
+                             binder_size_t *consumed, int non_block)
 {
+       void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
        void __user *ptr = buffer + *consumed;
        void __user *end = buffer + size;
 
@@ -2229,32 +2241,40 @@ retry:
                                if (put_user(cmd, (uint32_t __user *)ptr))
                                        return -EFAULT;
                                ptr += sizeof(uint32_t);
-                               if (put_user(node->ptr, (void * __user *)ptr))
+                               if (put_user(node->ptr,
+                                            (binder_uintptr_t __user *)ptr))
                                        return -EFAULT;
-                               ptr += sizeof(void *);
-                               if (put_user(node->cookie, (void * __user *)ptr))
+                               ptr += sizeof(binder_uintptr_t);
+                               if (put_user(node->cookie,
+                                            (binder_uintptr_t __user *)ptr))
                                        return -EFAULT;
-                               ptr += sizeof(void *);
+                               ptr += sizeof(binder_uintptr_t);
 
                                binder_stat_br(proc, thread, cmd);
                                binder_debug(BINDER_DEBUG_USER_REFS,
-                                            "%d:%d %s %d u%p c%p\n",
-                                            proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
+                                            "%d:%d %s %d u%016llx c%016llx\n",
+                                            proc->pid, thread->pid, cmd_name,
+                                            node->debug_id,
+                                            (u64)node->ptr, (u64)node->cookie);
                        } else {
                                list_del_init(&w->entry);
                                if (!weak && !strong) {
                                        binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-                                                    "%d:%d node %d u%p c%p deleted\n",
-                                                    proc->pid, thread->pid, node->debug_id,
-                                                    node->ptr, node->cookie);
+                                                    "%d:%d node %d u%016llx c%016llx deleted\n",
+                                                    proc->pid, thread->pid,
+                                                    node->debug_id,
+                                                    (u64)node->ptr,
+                                                    (u64)node->cookie);
                                        rb_erase(&node->rb_node, &proc->nodes);
                                        kfree(node);
                                        binder_stats_deleted(BINDER_STAT_NODE);
                                } else {
                                        binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-                                                    "%d:%d node %d u%p c%p state unchanged\n",
-                                                    proc->pid, thread->pid, node->debug_id, node->ptr,
-                                                    node->cookie);
+                                                    "%d:%d node %d u%016llx c%016llx state unchanged\n",
+                                                    proc->pid, thread->pid,
+                                                    node->debug_id,
+                                                    (u64)node->ptr,
+                                                    (u64)node->cookie);
                                }
                        }
                } break;
@@ -2272,17 +2292,18 @@ retry:
                        if (put_user(cmd, (uint32_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(uint32_t);
-                       if (put_user(death->cookie, (void * __user *)ptr))
+                       if (put_user(death->cookie,
+                                    (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(binder_uintptr_t);
                        binder_stat_br(proc, thread, cmd);
                        binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-                                    "%d:%d %s %p\n",
+                                    "%d:%d %s %016llx\n",
                                      proc->pid, thread->pid,
                                      cmd == BR_DEAD_BINDER ?
                                      "BR_DEAD_BINDER" :
                                      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
-                                     death->cookie);
+                                     (u64)death->cookie);
 
                        if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
                                list_del(&w->entry);
@@ -2312,8 +2333,8 @@ retry:
                                binder_set_nice(target_node->min_priority);
                        cmd = BR_TRANSACTION;
                } else {
-                       tr.target.ptr = NULL;
-                       tr.cookie = NULL;
+                       tr.target.ptr = 0;
+                       tr.cookie = 0;
                        cmd = BR_REPLY;
                }
                tr.code = t->code;
@@ -2330,8 +2351,9 @@ retry:
 
                tr.data_size = t->buffer->data_size;
                tr.offsets_size = t->buffer->offsets_size;
-               tr.data.ptr.buffer = (void *)t->buffer->data +
-                                       proc->user_buffer_offset;
+               tr.data.ptr.buffer = (binder_uintptr_t)(
+                                       (uintptr_t)t->buffer->data +
+                                       proc->user_buffer_offset);
                tr.data.ptr.offsets = tr.data.ptr.buffer +
                                        ALIGN(t->buffer->data_size,
                                            sizeof(void *));
@@ -2346,14 +2368,14 @@ retry:
                trace_binder_transaction_received(t);
                binder_stat_br(proc, thread, cmd);
                binder_debug(BINDER_DEBUG_TRANSACTION,
-                            "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n",
+                            "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
                             proc->pid, thread->pid,
                             (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
                             "BR_REPLY",
                             t->debug_id, t->from ? t->from->proc->pid : 0,
                             t->from ? t->from->pid : 0, cmd,
                             t->buffer->data_size, t->buffer->offsets_size,
-                            tr.data.ptr.buffer, tr.data.ptr.offsets);
+                            (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
 
                list_del(&t->work.entry);
                t->buffer->allow_user_free = 1;
@@ -2423,8 +2445,8 @@ static void binder_release_work(struct list_head *list)
 
                        death = container_of(w, struct binder_ref_death, work);
                        binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-                               "undelivered death notification, %p\n",
-                               death->cookie);
+                               "undelivered death notification, %016llx\n",
+                               (u64)death->cookie);
                        kfree(death);
                        binder_stats_deleted(BINDER_STAT_DEATH);
                } break;
@@ -2580,12 +2602,16 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        goto err;
                }
                binder_debug(BINDER_DEBUG_READ_WRITE,
-                            "%d:%d write %zd at %016lx, read %zd at %016lx\n",
-                            proc->pid, thread->pid, bwr.write_size,
-                            bwr.write_buffer, bwr.read_size, bwr.read_buffer);
+                            "%d:%d write %lld at %016llx, read %lld at %016llx\n",
+                            proc->pid, thread->pid,
+                            (u64)bwr.write_size, (u64)bwr.write_buffer,
+                            (u64)bwr.read_size, (u64)bwr.read_buffer);
 
                if (bwr.write_size > 0) {
-                       ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+                       ret = binder_thread_write(proc, thread,
+                                                 bwr.write_buffer,
+                                                 bwr.write_size,
+                                                 &bwr.write_consumed);
                        trace_binder_write_done(ret);
                        if (ret < 0) {
                                bwr.read_consumed = 0;
@@ -2595,7 +2621,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
                }
                if (bwr.read_size > 0) {
-                       ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+                       ret = binder_thread_read(proc, thread, bwr.read_buffer,
+                                                bwr.read_size,
+                                                &bwr.read_consumed,
+                                                filp->f_flags & O_NONBLOCK);
                        trace_binder_read_done(ret);
                        if (!list_empty(&proc->todo))
                                wake_up_interruptible(&proc->wait);
@@ -2606,9 +2635,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
                }
                binder_debug(BINDER_DEBUG_READ_WRITE,
-                            "%d:%d wrote %zd of %zd, read return %zd of %zd\n",
-                            proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
-                            bwr.read_consumed, bwr.read_size);
+                            "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
+                            proc->pid, thread->pid,
+                            (u64)bwr.write_consumed, (u64)bwr.write_size,
+                            (u64)bwr.read_consumed, (u64)bwr.read_size);
                if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
                        ret = -EFAULT;
                        goto err;
@@ -2637,7 +2667,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
                } else
                        binder_context_mgr_uid = current->cred->euid;
-               binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
+               binder_context_mgr_node = binder_new_node(proc, 0, 0);
                if (binder_context_mgr_node == NULL) {
                        ret = -ENOMEM;
                        goto err;
@@ -2904,7 +2934,7 @@ static int binder_node_release(struct binder_node *node, int refs)
                refs++;
 
                if (!ref->death)
-                       goto out;
+                       continue;
 
                death++;
 
@@ -2917,7 +2947,6 @@ static int binder_node_release(struct binder_node *node, int refs)
                        BUG();
        }
 
-out:
        binder_debug(BINDER_DEBUG_DEAD_BINDER,
                     "node %d now dead, refs %d, death %d\n",
                     node->debug_id, refs, death);
@@ -3133,8 +3162,9 @@ static void print_binder_work(struct seq_file *m, const char *prefix,
                break;
        case BINDER_WORK_NODE:
                node = container_of(w, struct binder_node, work);
-               seq_printf(m, "%snode work %d: u%p c%p\n",
-                          prefix, node->debug_id, node->ptr, node->cookie);
+               seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
+                          prefix, node->debug_id,
+                          (u64)node->ptr, (u64)node->cookie);
                break;
        case BINDER_WORK_DEAD_BINDER:
                seq_printf(m, "%shas dead binder\n", prefix);
@@ -3194,8 +3224,8 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
        hlist_for_each_entry(ref, &node->refs, node_entry)
                count++;
 
-       seq_printf(m, "  node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
-                  node->debug_id, node->ptr, node->cookie,
+       seq_printf(m, "  node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d",
+                  node->debug_id, (u64)node->ptr, (u64)node->cookie,
                   node->has_strong_ref, node->has_weak_ref,
                   node->local_strong_refs, node->local_weak_refs,
                   node->internal_strong_refs, count);
@@ -3497,6 +3527,7 @@ static const struct file_operations binder_fops = {
        .owner = THIS_MODULE,
        .poll = binder_poll,
        .unlocked_ioctl = binder_ioctl,
+       .compat_ioctl = binder_ioctl,
        .mmap = binder_mmap,
        .open = binder_open,
        .flush = binder_flush,
index d4101a671718ef2c8428c18074dec6fd13f94c65..eb0834656dfe2fa8810ef7db4444516030a27e11 100644 (file)
 #ifndef _LINUX_BINDER_H
 #define _LINUX_BINDER_H
 
+#ifdef CONFIG_ANDROID_BINDER_IPC_32BIT
+#define BINDER_IPC_32BIT 1
+#endif
+
 #include "uapi/binder.h"
 
 #endif /* _LINUX_BINDER_H */
index 82a567c2af6797bdfb5e004adffa51c447b53645..7f20f3dc83690cad36cfa82c2a946384a8c30bb8 100644 (file)
@@ -152,7 +152,7 @@ TRACE_EVENT(binder_transaction_node_to_ref,
        TP_STRUCT__entry(
                __field(int, debug_id)
                __field(int, node_debug_id)
-               __field(void __user *, node_ptr)
+               __field(binder_uintptr_t, node_ptr)
                __field(int, ref_debug_id)
                __field(uint32_t, ref_desc)
        ),
@@ -163,8 +163,9 @@ TRACE_EVENT(binder_transaction_node_to_ref,
                __entry->ref_debug_id = ref->debug_id;
                __entry->ref_desc = ref->desc;
        ),
-       TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d",
-                 __entry->debug_id, __entry->node_debug_id, __entry->node_ptr,
+       TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d",
+                 __entry->debug_id, __entry->node_debug_id,
+                 (u64)__entry->node_ptr,
                  __entry->ref_debug_id, __entry->ref_desc)
 );
 
@@ -177,7 +178,7 @@ TRACE_EVENT(binder_transaction_ref_to_node,
                __field(int, ref_debug_id)
                __field(uint32_t, ref_desc)
                __field(int, node_debug_id)
-               __field(void __user *, node_ptr)
+               __field(binder_uintptr_t, node_ptr)
        ),
        TP_fast_assign(
                __entry->debug_id = t->debug_id;
@@ -186,9 +187,10 @@ TRACE_EVENT(binder_transaction_ref_to_node,
                __entry->node_debug_id = ref->node->debug_id;
                __entry->node_ptr = ref->node->ptr;
        ),
-       TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p",
+       TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx",
                  __entry->debug_id, __entry->node_debug_id,
-                 __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr)
+                 __entry->ref_debug_id, __entry->ref_desc,
+                 (u64)__entry->node_ptr)
 );
 
 TRACE_EVENT(binder_transaction_ref_to_ref,
index 4bcf00a872705927d8228ac33af82d06d19e6ec0..b545d3d1da3e5f6ccbd59f783e55ce30ff23479d 100644 (file)
@@ -88,7 +88,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
        int array_size = ARRAY_SIZE(lowmem_adj);
        int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
        int other_file = global_page_state(NR_FILE_PAGES) -
-                                               global_page_state(NR_SHMEM);
+                                               global_page_state(NR_SHMEM) -
+                                               total_swapcache_pages();
 
        if (lowmem_adj_size < array_size)
                array_size = lowmem_adj_size;
index 2b1eb8106d58e22cb42f61a6aae19f56884376ff..904adb7600cf219a3a0940d4e539836a4dea49db 100644 (file)
@@ -39,6 +39,14 @@ enum {
        FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
 };
 
+#ifdef BINDER_IPC_32BIT
+typedef __u32 binder_size_t;
+typedef __u32 binder_uintptr_t;
+#else
+typedef __u64 binder_size_t;
+typedef __u64 binder_uintptr_t;
+#endif
+
 /*
  * This is the flattened representation of a Binder object for transfer
  * between processes.  The 'offsets' supplied as part of a binder transaction
@@ -53,12 +61,12 @@ struct flat_binder_object {
 
        /* 8 bytes of data. */
        union {
-               void __user     *binder;        /* local object */
-               __u32       handle;             /* remote object */
+               binder_uintptr_t        binder; /* local object */
+               __u32                   handle; /* remote object */
        };
 
        /* extra data associated with local object */
-       void __user             *cookie;
+       binder_uintptr_t        cookie;
 };
 
 /*
@@ -67,12 +75,12 @@ struct flat_binder_object {
  */
 
 struct binder_write_read {
-       size_t write_size;      /* bytes to write */
-       size_t write_consumed;  /* bytes consumed by driver */
-       unsigned long   write_buffer;
-       size_t read_size;       /* bytes to read */
-       size_t read_consumed;   /* bytes consumed by driver */
-       unsigned long   read_buffer;
+       binder_size_t           write_size;     /* bytes to write */
+       binder_size_t           write_consumed; /* bytes consumed by driver */
+       binder_uintptr_t        write_buffer;
+       binder_size_t           read_size;      /* bytes to read */
+       binder_size_t           read_consumed;  /* bytes consumed by driver */
+       binder_uintptr_t        read_buffer;
 };
 
 /* Use with BINDER_VERSION, driver fills in fields. */
@@ -82,7 +90,11 @@ struct binder_version {
 };
 
 /* This is the current protocol version. */
+#ifdef BINDER_IPC_32BIT
 #define BINDER_CURRENT_PROTOCOL_VERSION 7
+#else
+#define BINDER_CURRENT_PROTOCOL_VERSION 8
+#endif
 
 #define BINDER_WRITE_READ              _IOWR('b', 1, struct binder_write_read)
 #define BINDER_SET_IDLE_TIMEOUT                _IOW('b', 3, __s64)
@@ -119,18 +131,20 @@ struct binder_transaction_data {
         * identifying the target and contents of the transaction.
         */
        union {
-               __u32   handle; /* target descriptor of command transaction */
-               void    *ptr;   /* target descriptor of return transaction */
+               /* target descriptor of command transaction */
+               __u32   handle;
+               /* target descriptor of return transaction */
+               binder_uintptr_t ptr;
        } target;
-       void            *cookie;        /* target object cookie */
+       binder_uintptr_t        cookie; /* target object cookie */
        __u32           code;           /* transaction command */
 
        /* General information about the transaction. */
        __u32           flags;
        pid_t           sender_pid;
        uid_t           sender_euid;
-       size_t          data_size;      /* number of bytes of data */
-       size_t          offsets_size;   /* number of bytes of offsets */
+       binder_size_t   data_size;      /* number of bytes of data */
+       binder_size_t   offsets_size;   /* number of bytes of offsets */
 
        /* If this transaction is inline, the data immediately
         * follows here; otherwise, it ends with a pointer to
@@ -139,19 +153,24 @@ struct binder_transaction_data {
        union {
                struct {
                        /* transaction data */
-                       const void __user       *buffer;
+                       binder_uintptr_t        buffer;
                        /* offsets from buffer to flat_binder_object structs */
-                       const void __user       *offsets;
+                       binder_uintptr_t        offsets;
                } ptr;
                __u8    buf[8];
        } data;
 };
 
 struct binder_ptr_cookie {
-       void *ptr;
-       void *cookie;
+       binder_uintptr_t ptr;
+       binder_uintptr_t cookie;
 };
 
+struct binder_handle_cookie {
+       __u32 handle;
+       binder_uintptr_t cookie;
+} __attribute__((packed));
+
 struct binder_pri_desc {
        __s32 priority;
        __u32 desc;
@@ -159,8 +178,8 @@ struct binder_pri_desc {
 
 struct binder_pri_ptr_cookie {
        __s32 priority;
-       void *ptr;
-       void *cookie;
+       binder_uintptr_t ptr;
+       binder_uintptr_t cookie;
 };
 
 enum binder_driver_return_protocol {
@@ -235,11 +254,11 @@ enum binder_driver_return_protocol {
         * stop threadpool thread
         */
 
-       BR_DEAD_BINDER = _IOR('r', 15, void *),
+       BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
        /*
         * void *: cookie
         */
-       BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
+       BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
        /*
         * void *: cookie
         */
@@ -265,7 +284,7 @@ enum binder_driver_command_protocol {
         * Else you have acquired a primary reference on the object.
         */
 
-       BC_FREE_BUFFER = _IOW('c', 3, void *),
+       BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
        /*
         * void *: ptr to transaction data received on a read
         */
@@ -308,19 +327,21 @@ enum binder_driver_command_protocol {
         * of looping threads it has available.
         */
 
-       BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
+       BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14,
+                                               struct binder_handle_cookie),
        /*
-        * void *: ptr to binder
+        * int: handle
         * void *: cookie
         */
 
-       BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
+       BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15,
+                                               struct binder_handle_cookie),
        /*
-        * void *: ptr to binder
+        * int: handle
         * void *: cookie
         */
 
-       BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
+       BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
        /*
         * void *: cookie
         */
index 8dfdd2732bdc329b3865c010d0afdb8e1e248337..95a2358267bad3704d2500287e417735735cdb82 100644 (file)
@@ -40,7 +40,7 @@ static INT bcm_close(struct net_device *dev)
 }
 
 static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
-                           void *accel_priv)
+                           void *accel_priv, select_queue_fallback_t fallback)
 {
        return ClassifyPacket(netdev_priv(dev), skb);
 }
index 94f32728f7c8c37b54bd63f83be89091c4250733..5b03a19778d6f0b874a1ee38c5c0cd55969841bb 100644 (file)
@@ -1,5 +1,5 @@
 #include "headers.h"
-
+#include <linux/usb/ch9.h>
 static struct usb_device_id InterfaceUsbtable[] = {
        { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
        { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
@@ -347,81 +347,6 @@ static int device_run(struct bcm_interface_adapter *psIntfAdapter)
        return 0;
 }
 
-
-static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-}
-
-static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_BULK);
-}
-
-static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_CONTROL);
-}
-
-static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_INT);
-}
-
-static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_ISOC);
-}
-
-static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
-{
-       return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
-{
-       return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
-static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
-{
-       return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
-{
-       return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
-static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
-{
-       return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
-{
-       return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
 static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 {
        struct usb_host_interface *iface_desc;
@@ -481,8 +406,8 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
                                 * If Modem is high speed device EP2 should be INT OUT End point
                                 * If Mode is FS then EP2 should be bulk end point
                                 */
-                               if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (bcm_usb_endpoint_is_int_out(endpoint) == false))
-                                       || ((psIntfAdapter->bHighSpeedDevice == false) && (bcm_usb_endpoint_is_bulk_out(endpoint) == false))) {
+                               if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (usb_endpoint_is_int_out(endpoint) == false))
+                                       || ((psIntfAdapter->bHighSpeedDevice == false) && (usb_endpoint_is_bulk_out(endpoint) == false))) {
                                        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
                                                "Configuring the EEPROM\n");
                                        /* change the EP2, EP4 to INT OUT end point */
@@ -501,7 +426,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
                                        }
 
                                }
-                               if ((psIntfAdapter->bHighSpeedDevice == false) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+                               if ((psIntfAdapter->bHighSpeedDevice == false) && usb_endpoint_is_bulk_out(endpoint)) {
                                        /* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
                                        UINT _uiData = ntohl(EP2_CFG_INT);
                                        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
@@ -513,7 +438,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
                                endpoint = &iface_desc->endpoint[EP4].desc;
                                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
                                        "Choosing AltSetting as a default setting.\n");
-                               if (bcm_usb_endpoint_is_int_out(endpoint) == false) {
+                               if (usb_endpoint_is_int_out(endpoint) == false) {
                                        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
                                                "Dongle does not have BCM16 Fix.\n");
                                        /* change the EP2, EP4 to INT OUT end point and use EP4 in altsetting */
@@ -541,7 +466,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
        for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) {
                endpoint = &iface_desc->endpoint[value].desc;
 
-               if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint)) {
+               if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                        psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
                        psIntfAdapter->sBulkIn.bulk_in_endpointAddr = endpoint->bEndpointAddress;
@@ -550,14 +475,14 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
                                                                psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
                }
 
-               if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+               if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && usb_endpoint_is_bulk_out(endpoint)) {
                        psIntfAdapter->sBulkOut.bulk_out_endpointAddr = endpoint->bEndpointAddress;
                        psIntfAdapter->sBulkOut.bulk_out_pipe =
                                usb_sndbulkpipe(psIntfAdapter->udev,
                                        psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
                }
 
-               if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint)) {
+               if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                        psIntfAdapter->sIntrIn.int_in_size = buffer_size;
                        psIntfAdapter->sIntrIn.int_in_endpointAddr = endpoint->bEndpointAddress;
@@ -568,7 +493,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
                                return -EINVAL;
                }
 
-               if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint)) {
+               if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && usb_endpoint_is_int_out(endpoint)) {
                        if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
                                (psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer)) {
                                /* use first intout end point as a bulk out end point */
index 0727599bf5fa8ec63b47005d1b7ca5abf721f364..4f315835ddfcfd0348d6f70c203f0fb0d3b93cb1 100644 (file)
@@ -222,10 +222,7 @@ static USHORT      IpVersion4(struct bcm_mini_adapter *Adapter,
 
                //Checking classifier validity
                if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
-               {
-                       bClassificationSucceed = false;
                        break;
-               }
 
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
                if (pstClassifierRule->bIpv6Protocol)
@@ -233,51 +230,47 @@ static USHORT     IpVersion4(struct bcm_mini_adapter *Adapter,
 
                //**************Checking IP header parameter**************************//
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
-               if (false == (bClassificationSucceed =
-                       MatchSrcIpAddress(pstClassifierRule, iphd->saddr)))
+               if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
                        break;
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
 
-               if (false == (bClassificationSucceed =
-                       MatchDestIpAddress(pstClassifierRule, iphd->daddr)))
+               if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
                        break;
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
 
-               if (false == (bClassificationSucceed =
-                       MatchTos(pstClassifierRule, iphd->tos)))
-               {
+               if (!MatchTos(pstClassifierRule, iphd->tos)) {
                        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
                        break;
                }
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
 
-               if (false == (bClassificationSucceed =
-                       MatchProtocol(pstClassifierRule, iphd->protocol)))
+               if (!MatchProtocol(pstClassifierRule, iphd->protocol))
                        break;
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
 
                //if protocol is not TCP or UDP then no need of comparing source port and destination port
-               if (iphd->protocol != TCP && iphd->protocol != UDP)
+               if (iphd->protocol != TCP && iphd->protocol != UDP) {
+                       bClassificationSucceed = TRUE;
                        break;
+               }
                //******************Checking Transport Layer Header field if present *****************//
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
                        (iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
 
-               if (false == (bClassificationSucceed =
-                       MatchSrcPort(pstClassifierRule,
-                               ntohs((iphd->protocol == UDP) ?
-                               xprt_hdr->uhdr.source : xprt_hdr->thdr.source))))
+               if (!MatchSrcPort(pstClassifierRule,
+                                 ntohs((iphd->protocol == UDP) ?
+                                 xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
                        break;
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
 
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
                        (iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
                        xprt_hdr->thdr.dest);
-               if (false == (bClassificationSucceed =
-                       MatchDestPort(pstClassifierRule,
-                       ntohs((iphd->protocol == UDP) ?
-                       xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest))))
+               if (!MatchDestPort(pstClassifierRule,
+                                  ntohs((iphd->protocol == UDP) ?
+                                  xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
                        break;
+               bClassificationSucceed = TRUE;
        } while (0);
 
        if (TRUE == bClassificationSucceed)
index f441e33660fe2ed213241aa6ad9f54a907282c93..c281fdabb4ed16ca6ddfd80f0692d513a1fbcb16 100644 (file)
@@ -1054,7 +1054,6 @@ static int Handle1401Esc(DEVICE_EXTENSION *pdx, char *pCh,
                                /*  This can never happen, really */
                                dev_err(&pdx->interface->dev,
                                        "ERROR: DMA setup while transfer still waiting\n");
-                               spin_unlock(&pdx->stagedLock);
                        } else {
                                if ((wTransType == TM_EXTTOHOST)
                                    || (wTransType == TM_EXTTO1401)) {
index ac1edd9d1e21ad4c81f88f40443dd40e5d8bf6ad..a819e543ed30292dc5fba66e505c25976126afd1 100644 (file)
@@ -1481,7 +1481,8 @@ static int do_cmd_ioctl(struct comedi_device *dev,
        async->cmd.data = NULL;
        /* load channel/gain list */
        async->cmd.chanlist = memdup_user(user_chanlist,
-                                         async->cmd.chanlist_len * sizeof(int));
+                                         async->cmd.chanlist_len *
+                                         sizeof(int));
        if (IS_ERR(async->cmd.chanlist)) {
                ret = PTR_ERR(async->cmd.chanlist);
                async->cmd.chanlist = NULL;
index f36bf3e02c4127e9cf25b84d1f733821acb567f8..d46123a975820868ef3d2fd3ac9d61c75ed21a15 100644 (file)
@@ -61,31 +61,31 @@ struct comedi_subdevice {
 
        unsigned int *chanlist; /* driver-owned chanlist (not used) */
 
-       int (*insn_read) (struct comedi_device *, struct comedi_subdevice *,
+       int (*insn_read)(struct comedi_device *, struct comedi_subdevice *,
+                        struct comedi_insn *, unsigned int *);
+       int (*insn_write)(struct comedi_device *, struct comedi_subdevice *,
                          struct comedi_insn *, unsigned int *);
-       int (*insn_write) (struct comedi_device *, struct comedi_subdevice *,
+       int (*insn_bits)(struct comedi_device *, struct comedi_subdevice *,
+                        struct comedi_insn *, unsigned int *);
+       int (*insn_config)(struct comedi_device *, struct comedi_subdevice *,
                           struct comedi_insn *, unsigned int *);
-       int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *,
-                         struct comedi_insn *, unsigned int *);
-       int (*insn_config) (struct comedi_device *, struct comedi_subdevice *,
-                           struct comedi_insn *, unsigned int *);
-
-       int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
-       int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *,
-                          struct comedi_cmd *);
-       int (*poll) (struct comedi_device *, struct comedi_subdevice *);
-       int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
+
+       int (*do_cmd)(struct comedi_device *, struct comedi_subdevice *);
+       int (*do_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
+                         struct comedi_cmd *);
+       int (*poll)(struct comedi_device *, struct comedi_subdevice *);
+       int (*cancel)(struct comedi_device *, struct comedi_subdevice *);
        /* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */
        /* int (*do_unlock)(struct comedi_device *, \
                        struct comedi_subdevice *); */
 
        /* called when the buffer changes */
-       int (*buf_change) (struct comedi_device *dev,
-                          struct comedi_subdevice *s, unsigned long new_size);
+       int (*buf_change)(struct comedi_device *dev,
+                         struct comedi_subdevice *s, unsigned long new_size);
 
-       void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s,
-                      void *data, unsigned int num_bytes,
-                      unsigned int start_chan_index);
+       void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s,
+                     void *data, unsigned int num_bytes,
+                     unsigned int start_chan_index);
        enum dma_data_direction async_dma_dir;
 
        unsigned int state;
@@ -146,8 +146,8 @@ struct comedi_async {
 
        unsigned int cb_mask;
 
-       int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
-                       unsigned int x);
+       int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s,
+                      unsigned int x);
 };
 
 struct comedi_driver {
@@ -155,9 +155,9 @@ struct comedi_driver {
 
        const char *driver_name;
        struct module *module;
-       int (*attach) (struct comedi_device *, struct comedi_devconfig *);
-       void (*detach) (struct comedi_device *);
-       int (*auto_attach) (struct comedi_device *, unsigned long);
+       int (*attach)(struct comedi_device *, struct comedi_devconfig *);
+       void (*detach)(struct comedi_device *);
+       int (*auto_attach)(struct comedi_device *, unsigned long);
 
        /* number of elements in board_name and board_id arrays */
        unsigned int num_names;
@@ -202,8 +202,8 @@ struct comedi_device {
 
        struct fasync_struct *async_queue;
 
-       int (*open) (struct comedi_device *dev);
-       void (*close) (struct comedi_device *dev);
+       int (*open)(struct comedi_device *dev);
+       void (*close)(struct comedi_device *dev);
 };
 
 static inline const void *comedi_board(const struct comedi_device *dev)
index 8ce3335422cd3dec81d44580aa3d93bb9a42edcb..80cca95c830a16092e5ded0675d5428798c109a3 100644 (file)
@@ -169,9 +169,9 @@ static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
                                         unsigned int *data)
 {
        struct addi_private *devpriv = dev->private;
-       unsigned int ui_Status = 0;
-       unsigned int ui_Command = 0;
-       unsigned int ui_Mode = 0;
+       unsigned int ui_Status;
+       unsigned int ui_Command;
+       unsigned int ui_Mode;
 
        i_Temp = 0;
        devpriv->tsk_Current = current;
@@ -182,23 +182,18 @@ static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
        else
                ui_Mode = 0;
 
-/* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); */
        ui_Command = 0;
-/* ui_Command = ui_Command & 0xFFFFF9FEUL; */
        outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       ui_Command = 0;
+
        ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /************************/
+
        /* Set the reload value */
-       /************************/
        outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
-       /*********************/
+
        /* Set the time unit */
-       /*********************/
        outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
        if (data[0] == ADDIDATA_TIMER) {
 
-               /******************************/
                /* Set the mode :             */
                /* - Disable the hardware     */
                /* - Disable the counter mode */
@@ -206,101 +201,82 @@ static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
                /* - Disable the reset        */
                /* - Enable the timer mode    */
                /* - Set the timer mode       */
-               /******************************/
 
                ui_Command =
                        (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
 
-       }                       /* if (data[0] == ADDIDATA_TIMER) */
-       else {
-               if (data[0] == ADDIDATA_WATCHDOG) {
+       } else if (data[0] == ADDIDATA_WATCHDOG) {
 
-                       /******************************/
-                       /* Set the mode :             */
-                       /* - Disable the hardware     */
-                       /* - Disable the counter mode */
-                       /* - Disable the warning      */
-                       /* - Disable the reset        */
-                       /* - Disable the timer mode   */
-                       /******************************/
+               /* Set the mode :             */
+               /* - Disable the hardware     */
+               /* - Disable the counter mode */
+               /* - Disable the warning      */
+               /* - Disable the reset        */
+               /* - Disable the timer mode   */
 
-                       ui_Command = ui_Command & 0xFFF819E2UL;
+               ui_Command = ui_Command & 0xFFF819E2UL;
 
-               } else {
-                       dev_err(dev->class_dev, "The parameter for Timer/watchdog selection is in error\n");
-                       return -EINVAL;
-               }
+       } else {
+               dev_err(dev->class_dev, "The parameter for Timer/watchdog selection is in error\n");
+               return -EINVAL;
        }
+
        outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       ui_Command = 0;
+
        ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /********************************/
+
        /* Disable the hardware trigger */
-       /********************************/
        ui_Command = ui_Command & 0xFFFFF89FUL;
        if (data[4] == ADDIDATA_ENABLE) {
-               /**********************************/
+
                /* Set the hardware trigger level */
-               /**********************************/
                ui_Command = ui_Command | (data[5] << 5);
        }
        outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       ui_Command = 0;
+
        ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /*****************************/
+
        /* Disable the hardware gate */
-       /*****************************/
        ui_Command = ui_Command & 0xFFFFF87FUL;
        if (data[6] == ADDIDATA_ENABLE) {
-               /*******************************/
+
                /* Set the hardware gate level */
-               /*******************************/
                ui_Command = ui_Command | (data[7] << 7);
        }
        outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       ui_Command = 0;
+
        ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /*******************************/
+
        /* Disable the hardware output */
-       /*******************************/
        ui_Command = ui_Command & 0xFFFFF9FBUL;
-       /*********************************/
+
        /* Set the hardware output level */
-       /*********************************/
        ui_Command = ui_Command | (data[8] << 2);
        outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
        if (data[9] == ADDIDATA_ENABLE) {
-               /************************/
+
                /* Set the reload value */
-               /************************/
                outl(data[11],
                        devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
-               /**********************/
+
                /* Set the time unite */
-               /**********************/
                outl(data[10],
                        devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
        }
 
-       ui_Command = 0;
        ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /*******************************/
+
        /* Disable the hardware output */
-       /*******************************/
        ui_Command = ui_Command & 0xFFFFF9F7UL;
-       /*********************************/
+
        /* Set the hardware output level */
-       /*********************************/
        ui_Command = ui_Command | (data[12] << 3);
        outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /*************************************/
-       /**  Enable the watchdog interrupt  **/
-       /*************************************/
-       ui_Command = 0;
+
+       /* Enable the watchdog interrupt */
        ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       /*******************************/
+
        /* Set the interrupt selection */
-       /*******************************/
        ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
 
        ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
@@ -342,25 +318,23 @@ static int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
                                                 unsigned int *data)
 {
        struct addi_private *devpriv = dev->private;
-       unsigned int ui_Command = 0;
-       int i_Count = 0;
+       unsigned int ui_Command;
+       int i_Count;
 
        if (data[0] == 1) {
                ui_Command =
                        inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-               /**********************/
+
                /* Start the hardware */
-               /**********************/
                ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
                outl(ui_Command,
                        devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       }                       /*  if  (data[0]==1) */
+       }
        if (data[0] == 2) {
                ui_Command =
                        inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-               /***************************/
+
                /* Set the trigger command */
-               /***************************/
                ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
                outl(ui_Command,
                        devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
@@ -375,7 +349,7 @@ static int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
                */
                outl(ui_Command,
                        devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-       }                       /*   if (data[1]==0) */
+       }
        if (data[0] == 3) {
                /* stop all Watchdogs */
                ui_Command = 0;
@@ -459,32 +433,23 @@ static int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev,
                                       unsigned int *data)
 {
        struct addi_private *devpriv = dev->private;
-       unsigned int ui_Status = 0;     /*  Status register */
+       unsigned int ui_Status; /*  Status register */
 
        i_WatchdogNbr = insn->unused[0];
 
-       /******************/
        /* Get the status */
-       /******************/
-
        ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
 
-       /***********************************/
        /* Get the software trigger status */
-       /***********************************/
-
        data[0] = ((ui_Status >> 1) & 1);
-       /***********************************/
+
        /* Get the hardware trigger status */
-       /***********************************/
        data[1] = ((ui_Status >> 2) & 1);
-       /*********************************/
+
        /* Get the software clear status */
-       /*********************************/
        data[2] = ((ui_Status >> 3) & 1);
-       /***************************/
+
        /* Get the overflow status */
-       /***************************/
        data[3] = ((ui_Status >> 0) & 1);
        if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER)
                data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
@@ -525,9 +490,8 @@ static int i_APCI035_ConfigAnalogInput(struct comedi_device *dev,
        devpriv->tsk_Current = current;
        outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
        outl(0, devpriv->iobase + 128 + 0);
-       /********************************/
+
        /* Initialise the warning value */
-       /********************************/
        outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
        outl((data[0] << 8), devpriv->iobase + 128 + 0);
        outl(0x200000UL, devpriv->iobase + 128 + 12);
@@ -562,20 +526,15 @@ static int i_APCI035_ReadAnalogInput(struct comedi_device *dev,
                                     unsigned int *data)
 {
        struct addi_private *devpriv = dev->private;
-       unsigned int ui_CommandRegister = 0;
+       unsigned int ui_CommandRegister;
 
-       /******************/
        /*  Set the start */
-       /******************/
        ui_CommandRegister = 0x80000;
-       /******************************/
+
        /* Write the command register */
-       /******************************/
        outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
 
-       /***************************************/
        /* Read the digital value of the input */
-       /***************************************/
        data[0] = inl(devpriv->iobase + 128 + 28);
        return insn->n;
 }
@@ -598,11 +557,13 @@ static int i_APCI035_ReadAnalogInput(struct comedi_device *dev,
 static int i_APCI035_Reset(struct comedi_device *dev)
 {
        struct addi_private *devpriv = dev->private;
-       int i_Count = 0;
+       int i_Count;
 
        for (i_Count = 1; i_Count <= 4; i_Count++) {
                i_WatchdogNbr = i_Count;
-               outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);    /* stop all timers */
+
+               /* stop all timers */
+               outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
        }
        outl(0x0, devpriv->iobase + 128 + 12);  /* Disable the warning delay */
 
@@ -630,50 +591,45 @@ static void v_APCI035_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
        struct addi_private *devpriv = dev->private;
-       unsigned int ui_StatusRegister1 = 0;
-       unsigned int ui_StatusRegister2 = 0;
-       unsigned int ui_ReadCommand = 0;
-       unsigned int ui_ChannelNumber = 0;
-       unsigned int ui_DigitalTemperature = 0;
+       unsigned int ui_StatusRegister1;
+       unsigned int ui_StatusRegister2;
+       unsigned int ui_ReadCommand;
+       unsigned int ui_ChannelNumber;
+       unsigned int ui_DigitalTemperature;
 
        if (i_Temp == 1) {
                i_WatchdogNbr = i_Flag;
                i_Flag = i_Flag + 1;
        }
-       /**************************************/
+
        /* Read the interrupt status register of temperature Warning */
-       /**************************************/
        ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
-       /**************************************/
-       /* Read the interrupt status register for Watchdog/timer */
-       /**************************************/
 
+       /* Read the interrupt status register for Watchdog/timer */
        ui_StatusRegister2 =
                inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
 
        /* Test if warning relay interrupt */
        if ((((ui_StatusRegister1) & 0x8) == 0x8)) {
-               /**********************************/
+
                /* Disable the temperature warning */
-               /**********************************/
                ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
                ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
                outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
-               /***************************/
+
                /* Read the channel number */
-               /***************************/
                ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
-               /**************************************/
+
                /* Read the digital temperature value */
-               /**************************************/
                ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
-               send_sig(SIGIO, devpriv->tsk_Current, 0);       /*  send signal to the sample */
-       }                       /* if (((ui_StatusRegister1 & 0x8) == 0x8)) */
 
-       else {
-               if ((ui_StatusRegister2 & 0x1) == 0x1)
-                       send_sig(SIGIO, devpriv->tsk_Current, 0);       /*  send signal to the sample */
-       }                       /* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */
+               /*  send signal to the sample */
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+       } else if ((ui_StatusRegister2 & 0x1) == 0x1) {
+               /*  send signal to the sample */
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+       }
 
        return;
 }
index 1c32816e9130ef8e079536a4cea33fcd8a77b640..ec43c38958dec7c3470312630a9285a160d09bdf 100644 (file)
 /*
-    comedi/drivers/ke_counter.c
-    Comedi driver for Kolter-Electronic PCI Counter 1 Card
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds@schleef.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.
-*/
-/*
-Driver: ke_counter
-Description: Driver for Kolter Electronic Counter Card
-Devices: [Kolter Electronic] PCI Counter Card (ke_counter)
-Author: Michael Hillmann
-Updated: Mon, 14 Apr 2008 15:42:42 +0100
-Status: tested
-
-Configuration Options: not applicable, uses PCI auto config
+ * ke_counter.c
+ * Comedi driver for Kolter-Electronic PCI Counter 1 Card
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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.
+ */
 
-This driver is a simple driver to read the counter values from
-Kolter Electronic PCI Counter Card.
-*/
+/*
+ * Driver: ke_counter
+ * Description: Driver for Kolter Electronic Counter Card
+ * Devices: (Kolter Electronic) PCI Counter Card [ke_counter]
+ * Author: Michael Hillmann
+ * Updated: Mon, 14 Apr 2008 15:42:42 +0100
+ * Status: tested
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
 
 #include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
 
-#define CNT_CARD_DEVICE_ID      0x0014
+/*
+ * PCI BAR 0 Register I/O map
+ */
+#define KE_RESET_REG(x)                        (0x00 + ((x) * 0x20))
+#define KE_LATCH_REG(x)                        (0x00 + ((x) * 0x20))
+#define KE_LSB_REG(x)                  (0x04 + ((x) * 0x20))
+#define KE_MID_REG(x)                  (0x08 + ((x) * 0x20))
+#define KE_MSB_REG(x)                  (0x0c + ((x) * 0x20))
+#define KE_SIGN_REG(x)                 (0x10 + ((x) * 0x20))
+#define KE_OSC_SEL_REG                 0xf8
+#define KE_OSC_SEL_EXT                 (1 << 0)
+#define KE_OSC_SEL_4MHZ                        (2 << 0)
+#define KE_OSC_SEL_20MHZ               (3 << 0)
+#define KE_DO_REG                      0xfc
+
+static int ke_counter_insn_write(struct comedi_device *dev,
+                                struct comedi_subdevice *s,
+                                struct comedi_insn *insn,
+                                unsigned int *data)
+{
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int val;
+       int i;
+
+       for (i = 0; i < insn->n; i++) {
+               val = data[0];
 
-/*-- counter write ----------------------------------------------------------*/
+               /* Order matters */
+               outb((val >> 24) & 0xff, dev->iobase + KE_SIGN_REG(chan));
+               outb((val >> 16) & 0xff, dev->iobase + KE_MSB_REG(chan));
+               outb((val >> 8) & 0xff, dev->iobase + KE_MID_REG(chan));
+               outb((val >> 0) & 0xff, dev->iobase + KE_LSB_REG(chan));
+       }
 
-/* This should be used only for resetting the counters; maybe it is better
-   to make a special command 'reset'. */
-static int cnt_winsn(struct comedi_device *dev,
-                    struct comedi_subdevice *s, struct comedi_insn *insn,
-                    unsigned int *data)
-{
-       int chan = CR_CHAN(insn->chanspec);
-
-       outb((unsigned char)((data[0] >> 24) & 0xff),
-            dev->iobase + chan * 0x20 + 0x10);
-       outb((unsigned char)((data[0] >> 16) & 0xff),
-            dev->iobase + chan * 0x20 + 0x0c);
-       outb((unsigned char)((data[0] >> 8) & 0xff),
-            dev->iobase + chan * 0x20 + 0x08);
-       outb((unsigned char)((data[0] >> 0) & 0xff),
-            dev->iobase + chan * 0x20 + 0x04);
-
-       /* return the number of samples written */
-       return 1;
+       return insn->n;
 }
 
-/*-- counter read -----------------------------------------------------------*/
-
-static int cnt_rinsn(struct comedi_device *dev,
-                    struct comedi_subdevice *s, struct comedi_insn *insn,
-                    unsigned int *data)
+static int ke_counter_insn_read(struct comedi_device *dev,
+                               struct comedi_subdevice *s,
+                               struct comedi_insn *insn,
+                               unsigned int *data)
 {
-       unsigned char a0, a1, a2, a3, a4;
-       int chan = CR_CHAN(insn->chanspec);
-       int result;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int val;
+       int i;
 
-       a0 = inb(dev->iobase + chan * 0x20);
-       a1 = inb(dev->iobase + chan * 0x20 + 0x04);
-       a2 = inb(dev->iobase + chan * 0x20 + 0x08);
-       a3 = inb(dev->iobase + chan * 0x20 + 0x0c);
-       a4 = inb(dev->iobase + chan * 0x20 + 0x10);
+       for (i = 0; i < insn->n; i++) {
+               /* Order matters */
+               inb(dev->iobase + KE_LATCH_REG(chan));
 
-       result = (a1 + (a2 * 256) + (a3 * 65536));
-       if (a4 > 0)
-               result = result - s->maxdata;
+               val = inb(dev->iobase + KE_LSB_REG(chan));
+               val |= (inb(dev->iobase + KE_MID_REG(chan)) << 8);
+               val |= (inb(dev->iobase + KE_MSB_REG(chan)) << 16);
+               val |= (inb(dev->iobase + KE_SIGN_REG(chan)) << 24);
 
-       *data = (unsigned int)result;
+               data[i] = val;
+       }
 
-       /* return the number of samples read */
-       return 1;
+       return insn->n;
 }
 
-static int cnt_auto_attach(struct comedi_device *dev,
-                                    unsigned long context_unused)
+static int ke_counter_do_insn_bits(struct comedi_device *dev,
+                                  struct comedi_subdevice *s,
+                                  struct comedi_insn *insn,
+                                  unsigned int *data)
+{
+       if (comedi_dio_update_state(s, data))
+               outb(s->state, dev->iobase + KE_DO_REG);
+
+       data[1] = s->state;
+
+       return insn->n;
+}
+
+static int ke_counter_auto_attach(struct comedi_device *dev,
+                                 unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct comedi_subdevice *s;
@@ -97,27 +118,32 @@ static int cnt_auto_attach(struct comedi_device *dev,
                return ret;
        dev->iobase = pci_resource_start(pcidev, 0);
 
-       ret = comedi_alloc_subdevices(dev, 1);
+       ret = comedi_alloc_subdevices(dev, 2);
        if (ret)
                return ret;
 
        s = &dev->subdevices[0];
-       dev->read_subdev = s;
-
-       s->type = COMEDI_SUBD_COUNTER;
-       s->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
-       s->n_chan = 3;
-       s->maxdata = 0x00ffffff;
-       s->insn_read = cnt_rinsn;
-       s->insn_write = cnt_winsn;
-
-       /*  select 20MHz clock */
-       outb(3, dev->iobase + 248);
-
-       /*  reset all counters */
-       outb(0, dev->iobase);
-       outb(0, dev->iobase + 0x20);
-       outb(0, dev->iobase + 0x40);
+       s->type         = COMEDI_SUBD_COUNTER;
+       s->subdev_flags = SDF_READABLE;
+       s->n_chan       = 3;
+       s->maxdata      = 0x01ffffff;
+       s->range_table  = &range_unknown;
+       s->insn_read    = ke_counter_insn_read;
+       s->insn_write   = ke_counter_insn_write;
+
+       s = &dev->subdevices[1];
+       s->type         = COMEDI_SUBD_DO;
+       s->subdev_flags = SDF_WRITABLE;
+       s->n_chan       = 3;
+       s->maxdata      = 1;
+       s->range_table  = &range_digital;
+       s->insn_bits    = ke_counter_do_insn_bits;
+
+       outb(KE_OSC_SEL_20MHZ, dev->iobase + KE_OSC_SEL_REG);
+
+       outb(0, dev->iobase + KE_RESET_REG(0));
+       outb(0, dev->iobase + KE_RESET_REG(1));
+       outb(0, dev->iobase + KE_RESET_REG(2));
 
        return 0;
 }
@@ -125,7 +151,7 @@ static int cnt_auto_attach(struct comedi_device *dev,
 static struct comedi_driver ke_counter_driver = {
        .driver_name    = "ke_counter",
        .module         = THIS_MODULE,
-       .auto_attach    = cnt_auto_attach,
+       .auto_attach    = ke_counter_auto_attach,
        .detach         = comedi_pci_disable,
 };
 
@@ -137,7 +163,7 @@ static int ke_counter_pci_probe(struct pci_dev *dev,
 }
 
 static const struct pci_device_id ke_counter_pci_table[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, 0x0014) },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, ke_counter_pci_table);
@@ -151,5 +177,5 @@ static struct pci_driver ke_counter_pci_driver = {
 module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Kolter Electronic Counter Card");
 MODULE_LICENSE("GPL");
index 8adb535516bdf2216bf82e17f1d9d54457fca2b7..3a86d482babdff13732e3194d6ed259b0962de86 100644 (file)
@@ -4407,6 +4407,9 @@ static int ni_E_init(struct comedi_device *dev)
                                                        &ni_gpct_read_register,
                                                        counter_variant,
                                                        NUM_GPCT);
+       if (!devpriv->counter_dev)
+               return -ENOMEM;
+
        /* General purpose counters */
        for (j = 0; j < NUM_GPCT; ++j) {
                s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
index 84931117da35210771d68f6e06c713cd51e6e3b4..e96665ea3662fc091a048c01041da2f44c13d84e 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include "comet_tables.h"
 
 /*****************************************************************************
 *
index f5ce8529b4ae30392d949444fd8226b5dac1728d..40dbe2c623c4ff382c0588cb8c362f866078fbc0 100644 (file)
@@ -25,7 +25,8 @@
 #include "pmcc4.h"
 
 #if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
-    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+defined(CONFIG_SBE_HDLC_V7_MODULE) || \
+defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
 #define _v7_hdlc_  1
 #else
 #define _v7_hdlc_  0
@@ -33,9 +34,9 @@
 
 #if _v7_hdlc_
 #define V7(x) (x ## _v7)
-extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
-extern int  register_hdlc_device_v7 (hdlc_device *);
-extern int  unregister_hdlc_device_v7 (hdlc_device *);
+extern int  hdlc_netif_rx_v7(hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7(hdlc_device *);
+extern int  unregister_hdlc_device_v7(hdlc_device *);
 
 #else
 #define V7(x) x
@@ -53,49 +54,49 @@ extern int  drvr_state;
 
 #if 1
 u_int32_t
-pci_read_32 (u_int32_t *p)
+pci_read_32(u_int32_t *p)
 {
 #ifdef FLOW_DEBUG
-    u_int32_t   v;
+       u_int32_t   v;
 
-    FLUSH_PCI_READ ();
-    v = le32_to_cpu (*p);
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
-    return v;
+       FLUSH_PCI_READ();
+       v = le32_to_cpu(*p);
+       if (cxt1e1_log_level >= LOG_DEBUG)
+               pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
+       return v;
 #else
-    FLUSH_PCI_READ ();              /* */
-    return le32_to_cpu (*p);
+       FLUSH_PCI_READ();              /* */
+       return le32_to_cpu(*p);
 #endif
 }
 
 void
-pci_write_32 (u_int32_t *p, u_int32_t v)
+pci_write_32(u_int32_t *p, u_int32_t v)
 {
 #ifdef FLOW_DEBUG
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
+       if (cxt1e1_log_level >= LOG_DEBUG)
+               pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
 #endif
-    *p = cpu_to_le32 (v);
-    FLUSH_PCI_WRITE ();             /* This routine is called from routines
-                                     * which do multiple register writes
-                                     * which themselves need flushing between
-                                     * writes in order to guarantee write
-                                     * ordering.  It is less code-cumbersome
-                                     * to flush here-in then to investigate
-                                     * and code the many other register
-                                     * writing routines. */
+       *p = cpu_to_le32 (v);
+       FLUSH_PCI_WRITE();             /* This routine is called from routines
+                                       * which do multiple register writes
+                                       * which themselves need flushing between
+                                       * writes in order to guarantee write
+                                       * ordering.  It is less code-cumbersome
+                                       * to flush here-in then to investigate
+                                       * and code the many other register
+                                       * writing routines. */
 }
 #endif
 
 
 void
-pci_flush_write (ci_t *ci)
+pci_flush_write(ci_t *ci)
 {
-    volatile u_int32_t v;
+       volatile u_int32_t v;
 
     /* issue a PCI read to flush PCI write thru bridge */
-    v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
+       v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
 
     /*
      * return nothing, this just reads PCI bridge interface to flush
@@ -105,55 +106,53 @@ pci_flush_write (ci_t *ci)
 
 
 static void
-watchdog_func (unsigned long arg)
+watchdog_func(unsigned long arg)
 {
-    struct watchdog *wd = (void *) arg;
-
-    if (drvr_state != SBE_DRVR_AVAILABLE)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-            pr_warning("%s: drvr not available (%x)\n", __func__, drvr_state);
-        return;
-    }
-    schedule_work (&wd->work);
-    mod_timer (&wd->h, jiffies + wd->ticks);
+       struct watchdog *wd = (void *) arg;
+
+       if (drvr_state != SBE_DRVR_AVAILABLE) {
+               if (cxt1e1_log_level >= LOG_MONITOR)
+                       pr_warning("%s: drvr not available (%x)\n",
+                                  __func__, drvr_state);
+               return;
+       }
+       schedule_work(&wd->work);
+       mod_timer(&wd->h, jiffies + wd->ticks);
 }
 
-int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *c, int usec)
+int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *),
+                    void *c, int usec)
 {
-    wdp->func = f;
-    wdp->softc = c;
-    wdp->ticks = (HZ) * (usec / 1000) / 1000;
-    INIT_WORK(&wdp->work, (void *)f);
-    init_timer (&wdp->h);
-    {
-        ci_t       *ci = (ci_t *) c;
-
-        wdp->h.data = (unsigned long) &ci->wd;
-    }
-    wdp->h.function = watchdog_func;
-    return 0;
+       wdp->func = f;
+       wdp->softc = c;
+       wdp->ticks = (HZ) * (usec / 1000) / 1000;
+       INIT_WORK(&wdp->work, (void *)f);
+       init_timer(&wdp->h);
+       {
+               ci_t       *ci = (ci_t *) c;
+
+               wdp->h.data = (unsigned long) &ci->wd;
+       }
+       wdp->h.function = watchdog_func;
+       return 0;
 }
 
 void
-OS_uwait (int usec, char *description)
+OS_uwait(int usec, char *description)
 {
-    int         tmp;
-
-    if (usec >= 1000)
-    {
-        mdelay (usec / 1000);
-        /* now delay residual */
-        tmp = (usec / 1000) * 1000; /* round */
-        tmp = usec - tmp;           /* residual */
-        if (tmp)
-        {                           /* wait on residual */
-            udelay (tmp);
-        }
-    } else
-    {
-        udelay (usec);
-    }
+       int         tmp;
+
+       if (usec >= 1000) {
+               mdelay(usec / 1000);
+               /* now delay residual */
+               tmp = (usec / 1000) * 1000; /* round */
+               tmp = usec - tmp;           /* residual */
+               if (tmp) {                           /* wait on residual */
+                       udelay(tmp);
+               }
+       } else {
+               udelay(usec);
+       }
 }
 
 /* dummy short delay routine called as a subroutine so that compiler
@@ -161,96 +160,95 @@ OS_uwait (int usec, char *description)
  */
 
 void
-OS_uwait_dummy (void)
+OS_uwait_dummy(void)
 {
 #ifndef USE_MAX_INT_DELAY
-    dummy++;
+       dummy++;
 #else
-    udelay (1);
+       udelay(1);
 #endif
 }
 
 
 void
-OS_sem_init (void *sem, int state)
+OS_sem_init(void *sem, int state)
 {
-    switch (state)
-    {
-        case SEM_TAKEN:
-               sema_init((struct semaphore *) sem, 0);
-        break;
-    case SEM_AVAILABLE:
+       switch (state) {
+       case SEM_TAKEN:
+           sema_init((struct semaphore *) sem, 0);
+           break;
+       case SEM_AVAILABLE:
            sema_init((struct semaphore *) sem, 1);
-        break;
-    default:                        /* otherwise, set sem.count to state's
-                                     * value */
-        sema_init (sem, state);
-        break;
-    }
+           break;
+       default:                        /* otherwise, set sem.count to state's
+                                       * value */
+           sema_init(sem, state);
+           break;
+       }
 }
 
 
 int
-sd_line_is_ok (void *user)
+sd_line_is_ok(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+       struct net_device *ndev = (struct net_device *) user;
 
-    return netif_carrier_ok (ndev);
+       return netif_carrier_ok(ndev);
 }
 
 void
-sd_line_is_up (void *user)
+sd_line_is_up(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+       struct net_device *ndev = (struct net_device *) user;
 
-    netif_carrier_on (ndev);
-    return;
+       netif_carrier_on(ndev);
+       return;
 }
 
 void
-sd_line_is_down (void *user)
+sd_line_is_down(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+       struct net_device *ndev = (struct net_device *) user;
 
-    netif_carrier_off (ndev);
-    return;
+       netif_carrier_off(ndev);
+       return;
 }
 
 void
-sd_disable_xmit (void *user)
+sd_disable_xmit(void *user)
 {
-    struct net_device *dev = (struct net_device *) user;
+       struct net_device *dev = (struct net_device *) user;
 
-    netif_stop_queue (dev);
-    return;
+       netif_stop_queue(dev);
+       return;
 }
 
 void
-sd_enable_xmit (void *user)
+sd_enable_xmit(void *user)
 {
-    struct net_device *dev = (struct net_device *) user;
+       struct net_device *dev = (struct net_device *) user;
 
-    netif_wake_queue (dev);
-    return;
+       netif_wake_queue(dev);
+       return;
 }
 
 int
-sd_queue_stopped (void *user)
+sd_queue_stopped(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+       struct net_device *ndev = (struct net_device *) user;
 
-    return netif_queue_stopped (ndev);
+       return netif_queue_stopped(ndev);
 }
 
 void sd_recv_consume(void *token, size_t len, void *user)
 {
-    struct net_device *ndev = user;
-    struct sk_buff *skb = token;
+       struct net_device *ndev = user;
+       struct sk_buff *skb = token;
 
-    skb->dev = ndev;
-    skb_put (skb, len);
-    skb->protocol = hdlc_type_trans(skb, ndev);
-    netif_rx(skb);
+       skb->dev = ndev;
+       skb_put(skb, len);
+       skb->protocol = hdlc_type_trans(skb, ndev);
+       netif_rx(skb);
 }
 
 
@@ -263,77 +261,76 @@ void sd_recv_consume(void *token, size_t len, void *user)
 
 extern ci_t *CI;                /* dummy pointer to board ZERO's data */
 void
-VMETRO_TRIGGER (ci_t *ci, int x)
+VMETRO_TRIGGER(ci_t *ci, int x)
 {
-    struct s_comet_reg    *comet;
-    volatile u_int32_t data;
-
-    comet = ci->port[0].cometbase;  /* default to COMET # 0 */
-
-    switch (x)
-    {
-    default:
-    case 0:
-        data = pci_read_32 ((u_int32_t *) &comet->__res24);     /* 0x90 */
-        break;
-    case 1:
-        data = pci_read_32 ((u_int32_t *) &comet->__res25);     /* 0x94 */
-        break;
-    case 2:
-        data = pci_read_32 ((u_int32_t *) &comet->__res26);     /* 0x98 */
-        break;
-    case 3:
-        data = pci_read_32 ((u_int32_t *) &comet->__res27);     /* 0x9C */
-        break;
-    case 4:
-        data = pci_read_32 ((u_int32_t *) &comet->__res88);     /* 0x220 */
-        break;
-    case 5:
-        data = pci_read_32 ((u_int32_t *) &comet->__res89);     /* 0x224 */
-        break;
-    case 6:
-        data = pci_read_32 ((u_int32_t *) &comet->__res8A);     /* 0x228 */
-        break;
-    case 7:
-        data = pci_read_32 ((u_int32_t *) &comet->__res8B);     /* 0x22C */
-        break;
-    case 8:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA0);     /* 0x280 */
-        break;
-    case 9:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA1);     /* 0x284 */
-        break;
-    case 10:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA2);     /* 0x288 */
-        break;
-    case 11:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA3);     /* 0x28C */
-        break;
-    case 12:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA4);     /* 0x290 */
-        break;
-    case 13:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA5);     /* 0x294 */
-        break;
-    case 14:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA6);     /* 0x298 */
-        break;
-    case 15:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA7);     /* 0x29C */
-        break;
-    case 16:
-        data = pci_read_32 ((u_int32_t *) &comet->__res74);     /* 0x1D0 */
-        break;
-    case 17:
-        data = pci_read_32 ((u_int32_t *) &comet->__res75);     /* 0x1D4 */
-        break;
-    case 18:
-        data = pci_read_32 ((u_int32_t *) &comet->__res76);     /* 0x1D8 */
-        break;
-    case 19:
-        data = pci_read_32 ((u_int32_t *) &comet->__res77);     /* 0x1DC */
-        break;
-    }
+       struct s_comet_reg    *comet;
+       volatile u_int32_t data;
+
+       comet = ci->port[0].cometbase;  /* default to COMET # 0 */
+
+       switch (x) {
+       default:
+       case 0:
+           data = pci_read_32((u_int32_t *) &comet->__res24);     /* 0x90 */
+           break;
+       case 1:
+           data = pci_read_32((u_int32_t *) &comet->__res25);     /* 0x94 */
+           break;
+       case 2:
+           data = pci_read_32((u_int32_t *) &comet->__res26);     /* 0x98 */
+           break;
+       case 3:
+           data = pci_read_32((u_int32_t *) &comet->__res27);     /* 0x9C */
+           break;
+       case 4:
+           data = pci_read_32((u_int32_t *) &comet->__res88);     /* 0x220 */
+           break;
+       case 5:
+           data = pci_read_32((u_int32_t *) &comet->__res89);     /* 0x224 */
+           break;
+       case 6:
+           data = pci_read_32((u_int32_t *) &comet->__res8A);     /* 0x228 */
+           break;
+       case 7:
+           data = pci_read_32((u_int32_t *) &comet->__res8B);     /* 0x22C */
+           break;
+       case 8:
+           data = pci_read_32((u_int32_t *) &comet->__resA0);     /* 0x280 */
+           break;
+       case 9:
+           data = pci_read_32((u_int32_t *) &comet->__resA1);     /* 0x284 */
+           break;
+       case 10:
+           data = pci_read_32((u_int32_t *) &comet->__resA2);     /* 0x288 */
+           break;
+       case 11:
+           data = pci_read_32((u_int32_t *) &comet->__resA3);     /* 0x28C */
+           break;
+       case 12:
+           data = pci_read_32((u_int32_t *) &comet->__resA4);     /* 0x290 */
+           break;
+       case 13:
+           data = pci_read_32((u_int32_t *) &comet->__resA5);     /* 0x294 */
+           break;
+       case 14:
+           data = pci_read_32((u_int32_t *) &comet->__resA6);     /* 0x298 */
+           break;
+       case 15:
+           data = pci_read_32((u_int32_t *) &comet->__resA7);     /* 0x29C */
+           break;
+       case 16:
+           data = pci_read_32((u_int32_t *) &comet->__res74);     /* 0x1D0 */
+           break;
+       case 17:
+           data = pci_read_32((u_int32_t *) &comet->__res75);     /* 0x1D4 */
+           break;
+       case 18:
+           data = pci_read_32((u_int32_t *) &comet->__res76);     /* 0x1D8 */
+           break;
+       case 19:
+           data = pci_read_32((u_int32_t *) &comet->__res77);     /* 0x1DC */
+           break;
+       }
 }
 
 
index 02b4f8f1aca5d6197407c693d34a6025a8b813a1..d87a011360bddc3faed1c50fd160a910e55ba628 100644 (file)
@@ -36,355 +36,354 @@ extern int  error_flag;
 extern int  drvr_state;
 
 /* forward references */
-void        c4_stopwd (ci_t *);
-struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
+void        c4_stopwd(ci_t *);
+struct net_device * __init c4_add_dev(hdw_info_t *, int, unsigned long,
+                                     unsigned long, int, int);
 
 
 struct s_hdw_info hdw_info[MAX_BOARDS];
 
 
-void        __init
-show_two (hdw_info_t *hi, int brdno)
+void __init
+show_two(hdw_info_t *hi, int brdno)
 {
-    ci_t       *ci;
-    struct pci_dev *pdev;
-    char       *bid;
-    char       *bp, banner[80];
-    char        sn[6];
-
-    bp = banner;
-    memset (banner, 0, 80);         /* clear print buffer */
-
-    ci = (ci_t *)(netdev_priv(hi->ndev));
-    bid = sbeid_get_bdname (ci);
-    switch (hi->promfmt)
-    {
-    case PROM_FORMAT_TYPE1:
-        memcpy (sn, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-        break;
-    case PROM_FORMAT_TYPE2:
-        memcpy (sn, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-        break;
-    default:
-        memset (sn, 0, 6);
-        break;
-    }
-
-    sprintf (banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
-             hi->devname, bid,
-             ((sn[3] << 16) & 0xff0000) |
-              ((sn[4] << 8) & 0x00ff00) |
-              (sn[5] & 0x0000ff),
-             (u_int8_t) hi->revid[0]);
-
-    pr_info("%s\n", banner);
-
-    pdev = hi->pdev[0];
-    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-            hi->devname, "MUSYCC",
-            (unsigned long) hi->addr_mapped[0], hi->addr[0],
-            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
-            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
-
-    pdev = hi->pdev[1];
-    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-            hi->devname, "EBUS  ",
-            (unsigned long) hi->addr_mapped[1], hi->addr[1],
-            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
-            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
+       ci_t       *ci;
+       struct pci_dev *pdev;
+       char       *bid;
+       char       banner[80];
+       char    sn[6];
+
+       /* clear print buffer */
+       memset(banner, 0, 80);
+
+       ci = (ci_t *)(netdev_priv(hi->ndev));
+       bid = sbeid_get_bdname(ci);
+       switch (hi->promfmt) {
+       case PROM_FORMAT_TYPE1:
+               memcpy(sn, (FLD_TYPE1 *)(hi->mfg_info.pft1.Serial), 6);
+               break;
+       case PROM_FORMAT_TYPE2:
+               memcpy(sn, (FLD_TYPE2 *)(hi->mfg_info.pft2.Serial), 6);
+               break;
+       default:
+               memset(sn, 0, 6);
+               break;
+       }
+
+       sprintf(banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
+               hi->devname, bid,
+               ((sn[3] << 16) & 0xff0000) |
+               ((sn[4] << 8) & 0x00ff00) |
+               (sn[5] & 0x0000ff),
+               (u_int8_t) hi->revid[0]);
+
+       pr_info("%s\n", banner);
+
+       pdev = hi->pdev[0];
+       pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+               hi->devname, "MUSYCC",
+               (unsigned long) hi->addr_mapped[0], hi->addr[0],
+               hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
+               (u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
+
+       pdev = hi->pdev[1];
+       pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+               hi->devname, "EBUS  ",
+               (unsigned long) hi->addr_mapped[1], hi->addr[1],
+               hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
+               (u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
 }
 
 
-void        __init
-hdw_sn_get (hdw_info_t *hi, int brdno)
+void __init
+hdw_sn_get(hdw_info_t *hi, int brdno)
 {
-    /* obtain hardware EEPROM information */
-    long        addr;
+       /* obtain hardware EEPROM information */
+       long        addr;
 
-    addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
+       addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
 
-    /* read EEPROM with largest known format size... */
-    pmc_eeprom_read_buffer (addr, 0, (char *) hi->mfg_info.data, sizeof (FLD_TYPE2));
+       /* read EEPROM with largest known format size... */
+       pmc_eeprom_read_buffer(addr, 0, (char *)hi->mfg_info.data,
+                              sizeof(FLD_TYPE2));
 
 #if 0
-    {
-        unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
-
-        pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
-        pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
-        pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
-        pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
-        pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
-        pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
-    }
+       {
+               unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
+
+               pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3),
+                       *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
+               pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11),
+                       *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
+               pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19),
+                       *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
+               pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27),
+                       *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
+               pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35),
+                       *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
+               pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43),
+                       *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
+       }
 #endif
 #if 0
-    pr_info("sn: %x %x %x %x %x %x\n",
-            hi->mfg_info.Serial[0],
-            hi->mfg_info.Serial[1],
-            hi->mfg_info.Serial[2],
-            hi->mfg_info.Serial[3],
-            hi->mfg_info.Serial[4],
-            hi->mfg_info.Serial[5]);
+       pr_info("sn: %x %x %x %x %x %x\n",
+                       hi->mfg_info.Serial[0],
+                       hi->mfg_info.Serial[1],
+                       hi->mfg_info.Serial[2],
+                       hi->mfg_info.Serial[3],
+                       hi->mfg_info.Serial[4],
+                       hi->mfg_info.Serial[5]);
 #endif
 
-    if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk)
-    {
-        /* bad crc, data is suspect */
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: EEPROM cksum error\n", hi->devname);
-        hi->mfg_info_sts = EEPROM_CRCERR;
-    } else
-        hi->mfg_info_sts = EEPROM_OK;
+       hi->promfmt = pmc_verify_cksum(&hi->mfg_info.data);
+       if (hi->promfmt == PROM_FORMAT_Unk) {
+               /* bad crc, data is suspect */
+               if (cxt1e1_log_level >= LOG_WARN)
+                       pr_info("%s: EEPROM cksum error\n", hi->devname);
+               hi->mfg_info_sts = EEPROM_CRCERR;
+       } else
+               hi->mfg_info_sts = EEPROM_OK;
 }
 
 
-void        __init
-prep_hdw_info (void)
+       void __init
+prep_hdw_info(void)
 {
-    hdw_info_t *hi;
-    int         i;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        hi->pci_busno = 0xff;
-        hi->pci_slot = 0xff;
-        hi->pci_pin[0] = 0;
-        hi->pci_pin[1] = 0;
-        hi->ndev = NULL;
-        hi->addr[0] = 0L;
-        hi->addr[1] = 0L;
-        hi->addr_mapped[0] = 0L;
-        hi->addr_mapped[1] = 0L;
-    }
+       hdw_info_t *hi;
+       int         i;
+
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               hi->pci_busno = 0xff;
+               hi->pci_slot = 0xff;
+               hi->pci_pin[0] = 0;
+               hi->pci_pin[1] = 0;
+               hi->ndev = NULL;
+               hi->addr[0] = 0L;
+               hi->addr[1] = 0L;
+               hi->addr_mapped[0] = 0L;
+               hi->addr_mapped[1] = 0L;
+       }
 }
 
 void
-cleanup_ioremap (void)
+cleanup_ioremap(void)
 {
-    hdw_info_t *hi;
-    int         i;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        if (hi->addr_mapped[0])
-        {
-            iounmap ((void *) (hi->addr_mapped[0]));
-            release_mem_region ((long) hi->addr[0], hi->len[0]);
-            hi->addr_mapped[0] = 0;
-        }
-        if (hi->addr_mapped[1])
-        {
-            iounmap ((void *) (hi->addr_mapped[1]));
-            release_mem_region ((long) hi->addr[1], hi->len[1]);
-            hi->addr_mapped[1] = 0;
-        }
-    }
+       hdw_info_t *hi;
+       int         i;
+
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               if (hi->pci_slot == 0xff)
+                       break;
+               if (hi->addr_mapped[0]) {
+                       iounmap((void *)(hi->addr_mapped[0]));
+                       release_mem_region((long) hi->addr[0], hi->len[0]);
+                       hi->addr_mapped[0] = 0;
+               }
+               if (hi->addr_mapped[1]) {
+                       iounmap((void *)(hi->addr_mapped[1]));
+                       release_mem_region((long) hi->addr[1], hi->len[1]);
+                       hi->addr_mapped[1] = 0;
+               }
+       }
 }
 
 
 void
-cleanup_devs (void)
+cleanup_devs(void)
 {
-    hdw_info_t *hi;
-    int         i;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff || !hi->ndev)
-            break;
-        c4_stopwd(netdev_priv(hi->ndev));
+       hdw_info_t *hi;
+       int         i;
+
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               if (hi->pci_slot == 0xff || !hi->ndev)
+                       break;
+               c4_stopwd(netdev_priv(hi->ndev));
 #ifdef CONFIG_PROC_FS
-        sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
+               sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
 #endif
-        unregister_netdev (hi->ndev);
-        free_irq (hi->pdev[0]->irq, hi->ndev);
+               unregister_netdev(hi->ndev);
+               free_irq(hi->pdev[0]->irq, hi->ndev);
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-        free_irq (hi->pdev[1]->irq, hi->ndev);
+               free_irq(hi->pdev[1]->irq, hi->ndev);
 #endif
-        OS_kfree (hi->ndev);
-    }
+               OS_kfree(hi->ndev);
+       }
 }
 
 
 static int  __init
-c4_hdw_init (struct pci_dev *pdev, int found)
+c4_hdw_init(struct pci_dev *pdev, int found)
 {
-    hdw_info_t *hi;
-    int         i;
-    int         fun, slot;
-    unsigned char busno = 0xff;
-
-    /* our MUSYCC chip supports two functions, 0 & 1 */
-    if ((fun = PCI_FUNC (pdev->devfn)) > 1)
-    {
-        pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
-        return 0;
-    }
-    if (pdev->bus)                  /* obtain bus number */
-        busno = pdev->bus->number;
-    else
-        busno = 0;                  /* default for system PCI inconsistency */
-    slot = pdev->devfn & ~0x07;
-
-    /*
-     * Functions 0 & 1 for a given board (identified by same bus(busno) and
-     * slot(slot)) are placed into the same 'hardware' structure.  The first
-     * part of the board's functionality will be placed into an unpopulated
-     * element, identified by "slot==(0xff)".  The second part of a board's
-     * functionality will match the previously loaded slot/busno.
-     */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        /*
-         * match with board's first found interface, otherwise this is first
-         * found
-         */
-        if ((hi->pci_slot == 0xff) ||   /* new board */
-            ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
-            break;                  /* found for-loop exit */
-    }
-    if (i == MAX_BOARDS)            /* no match in above loop means MAX
-                                     * exceeded */
-    {
-        pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
-        return 0;
-    }
-    if (pdev->bus)
-        hi->pci_busno = pdev->bus->number;
-    else
-        hi->pci_busno = 0;          /* default for system PCI inconsistency */
-    hi->pci_slot = slot;
-    pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
-    pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]);
-    hi->bus = pdev->bus;
-    hi->addr[fun] = pci_resource_start (pdev, 0);
-    hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1;
-    hi->pdev[fun] = pdev;
-
-    {
-        /*
-         * create device name from module name, plus add the appropriate
-         * board number
-         */
-        char       *cp = hi->devname;
-
-        strcpy (cp, KBUILD_MODNAME);
-        cp += strlen (cp);          /* reposition */
-        *cp++ = '-';
-        *cp++ = '0' + (found / 2);  /* there are two found interfaces per
-                                     * board */
-        *cp = 0;                    /* termination */
-    }
-
-    return 1;
+       hdw_info_t *hi;
+       int         i;
+       int         fun, slot;
+       unsigned char busno = 0xff;
+
+       /* our MUSYCC chip supports two functions, 0 & 1 */
+       fun = PCI_FUNC(pdev->devfn);
+       if (fun > 1) {
+               pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
+               return 0;
+       }
+
+       /* obtain bus number */
+       if (pdev->bus)
+               busno = pdev->bus->number;
+       else
+               busno = 0; /* default for system PCI inconsistency */
+       slot = pdev->devfn & ~0x07;
+
+       /*
+        * Functions 0 & 1 for a given board (identified by same bus(busno) and
+        * slot(slot)) are placed into the same 'hardware' structure.  The first
+        * part of the board's functionality will be placed into an unpopulated
+        * element, identified by "slot==(0xff)".  The second part of a board's
+        * functionality will match the previously loaded slot/busno.
+        */
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               /*
+                * match with board's first found interface, otherwise this is
+                * fisrt found
+                */
+               if ((hi->pci_slot == 0xff) ||   /* new board */
+                   ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
+                       break;                  /* found for-loop exit */
+       }
+
+       /* no match in above loop means MAX exceeded */
+       if (i == MAX_BOARDS) {
+               pr_warning("exceeded number of allowed devices (>%d)?\n",
+                          MAX_BOARDS);
+               return 0;
+       }
+
+       if (pdev->bus)
+               hi->pci_busno = pdev->bus->number;
+       else
+               hi->pci_busno = 0; /* default for system PCI inconsistency */
+
+       hi->pci_slot = slot;
+       pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &hi->revid[fun]);
+       hi->bus = pdev->bus;
+       hi->addr[fun] = pci_resource_start(pdev, 0);
+       hi->len[fun] = pci_resource_end(pdev, 0) - hi->addr[fun] + 1;
+       hi->pdev[fun] = pdev;
+
+       {
+               /*
+                * create device name from module name, plus add the appropriate
+                * board number
+                */
+               char       *cp = hi->devname;
+
+               strcpy(cp, KBUILD_MODNAME);
+               cp += strlen(cp);          /* reposition */
+               *cp++ = '-';
+               *cp++ = '0' + (found / 2);  /* there are two found interfaces per
+               * board */
+               *cp = 0;                    /* termination */
+       }
+
+       return 1;
 }
 
-
-status_t    __init
-c4hw_attach_all (void)
+status_t __init
+c4hw_attach_all(void)
 {
-    hdw_info_t *hi;
-    struct pci_dev *pdev = NULL;
-    int         found = 0, i, j;
-
-    error_flag = 0;
-    prep_hdw_info ();
-    /*** scan PCI bus for all possible boards */
-    while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
-                                    PCI_DEVICE_ID_CN8474,
-                                    pdev)))
-    {
-        if (c4_hdw_init (pdev, found))
-            found++;
-    }
-    if (!found)
-    {
-        pr_warning("No boards found\n");
-        return -ENODEV;
-    }
-    /* sanity check for consistent hardware found */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
-        {
-            pr_warning("%s: something very wrong with pci_get_device\n",
-                       hi->devname);
-            return -EIO;
-        }
-    }
-    /* bring board's memory regions on/line */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        for (j = 0; j < 2; j++)
-        {
-           if (!request_mem_region (hi->addr[j], hi->len[j], hi->devname))
-            {
-                pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
-                           hi->devname, hi->addr[j], hi->len[j]);
-                cleanup_ioremap ();
-                return -ENOMEM;
-            }
-            hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
-            if (!hi->addr_mapped[j])
-            {
-                pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
-                           hi->devname, hi->addr[j], hi->len[j]);
-                cleanup_ioremap ();
-                return -ENOMEM;
-            }
+       hdw_info_t *hi;
+       struct pci_dev *pdev = NULL;
+       int         found = 0, i, j;
+
+       error_flag = 0;
+       prep_hdw_info();
+       /*** scan PCI bus for all possible boards */
+       while ((pdev = pci_get_device(PCI_VENDOR_ID_CONEXANT,
+                                     PCI_DEVICE_ID_CN8474,
+                                     pdev))) {
+               if (c4_hdw_init(pdev, found))
+                       found++;
+       }
+
+       if (!found) {
+               pr_warning("No boards found\n");
+               return -ENODEV;
+       }
+
+       /* sanity check for consistent hardware found */
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1])) {
+                       pr_warning("%s: something very wrong with pci_get_device\n",
+                                  hi->devname);
+                       return -EIO;
+               }
+       }
+       /* bring board's memory regions on/line */
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               if (hi->pci_slot == 0xff)
+                       break;
+               for (j = 0; j < 2; j++) {
+                       if (!request_mem_region(hi->addr[j], hi->len[j], hi->devname)) {
+                               pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
+                                          hi->devname, hi->addr[j], hi->len[j]);
+                               cleanup_ioremap();
+                               return -ENOMEM;
+                       }
+
+                       hi->addr_mapped[j] = (unsigned long)ioremap(hi->addr[j], hi->len[j]);
+                       if (!hi->addr_mapped[j]) {
+                               pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
+                                          hi->devname, hi->addr[j], hi->len[j]);
+                               cleanup_ioremap();
+                               return -ENOMEM;
+                       }
 #ifdef SBE_MAP_DEBUG
-            pr_warning("%s: io remapped from phys %x to virt %x\n",
-                       hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
+                       pr_warning("%s: io remapped from phys %x to virt %x\n",
+                                  hi->devname, (u_int32_t) hi->addr[j],
+                                  (u_int32_t) hi->addr_mapped[j]);
 #endif
-        }
-    }
-
-    drvr_state = SBE_DRVR_AVAILABLE;
-
-    /* Have now memory mapped all boards.  Now allow board's access to system */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        if (pci_enable_device (hi->pdev[0]) ||
-            pci_enable_device (hi->pdev[1]))
-        {
-            drvr_state = SBE_DRVR_DOWN;
-            pr_warning("%s: failed to enable card %d slot %d\n",
-                       hi->devname, i, hi->pci_slot);
-            cleanup_devs ();
-            cleanup_ioremap ();
-            return -EIO;
-        }
-        pci_set_master (hi->pdev[0]);
-        pci_set_master (hi->pdev[1]);
-        if (!(hi->ndev = c4_add_dev (hi, i, (long) hi->addr_mapped[0],
-                                     (long) hi->addr_mapped[1],
-                                     hi->pdev[0]->irq,
-                                     hi->pdev[1]->irq)))
-        {
-            drvr_state = SBE_DRVR_DOWN;
-            cleanup_ioremap ();
-            /* NOTE: c4_add_dev() does its own device cleanup */
+               }
+       }
+
+       drvr_state = SBE_DRVR_AVAILABLE;
+
+       /* Have now memory mapped all boards.  Now allow board's access to system */
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+               if (hi->pci_slot == 0xff)
+                       break;
+               if (pci_enable_device(hi->pdev[0]) ||
+                   pci_enable_device(hi->pdev[1])) {
+                       drvr_state = SBE_DRVR_DOWN;
+                       pr_warning("%s: failed to enable card %d slot %d\n",
+                                  hi->devname, i, hi->pci_slot);
+                       cleanup_devs();
+                       cleanup_ioremap();
+                       return -EIO;
+               }
+               pci_set_master(hi->pdev[0]);
+               pci_set_master(hi->pdev[1]);
+               hi->ndev = c4_add_dev(hi, i, (long) hi->addr_mapped[0],
+                                     (long) hi->addr_mapped[1],
+                                     hi->pdev[0]->irq,
+                                     hi->pdev[1]->irq);
+               if (!hi->ndev) {
+                       drvr_state = SBE_DRVR_DOWN;
+                       cleanup_ioremap();
+                       /* NOTE: c4_add_dev() does its own device cleanup */
 #if 0
-            cleanup_devs ();
+                       cleanup_devs();
 #endif
-            return error_flag;      /* error_flag set w/in add_dev() */
-        }
-        show_two (hi, i);           /* displays found information */
-    }
-    return 0;
+                       return error_flag; /* error_flag set w/in add_dev() */
+               }
+               show_two(hi, i); /* displays found information */
+       }
+       return 0;
 }
 
 /***  End-of-File  ***/
index 4a08e16e42f719470cd9a0b63de557d2b3ff704b..579e68e3deced66c7314b85009bc1b519c9379a5 100644 (file)
@@ -31,7 +31,7 @@
 #include "pmcc4_private.h"
 #include "sbeproc.h"
 
-/*****************************************************************************************
+/*******************************************************************************
  * Error out early if we have compiler trouble.
  *
  *   (This section is included from the kernel's init/main.c as a friendly
 #warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
 #endif
 
-/*****************************************************************************************/
+/*******************************************************************************/
 
 #define CHANNAME "hdlc"
 
 /*******************************************************************/
 /* forward references */
-status_t    c4_chan_work_init (mpi_t *, mch_t *);
-void        musycc_wq_chan_restart (void *);
-status_t __init c4_init (ci_t *, u_char *, u_char *);
-status_t __init c4_init2 (ci_t *);
-ci_t       *__init c4_new (void *);
-int __init  c4hw_attach_all (void);
-void __init hdw_sn_get (hdw_info_t *, int);
+status_t    c4_chan_work_init(mpi_t *, mch_t *);
+void        musycc_wq_chan_restart(void *);
+status_t __init c4_init(ci_t *, u_char *, u_char *);
+status_t __init c4_init2(ci_t *);
+ci_t       *__init c4_new(void *);
+int __init  c4hw_attach_all(void);
+void __init hdw_sn_get(hdw_info_t *, int);
 
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-irqreturn_t c4_ebus_intr_th_handler (void *);
+irqreturn_t c4_ebus_intr_th_handler(void *);
 
 #endif
-int         c4_frame_rw (ci_t *, struct sbecom_port_param *);
-status_t    c4_get_port (ci_t *, int);
-int         c4_loop_port (ci_t *, int, u_int8_t);
-int         c4_musycc_rw (ci_t *, struct c4_musycc_param *);
-int         c4_new_chan (ci_t *, int, int, void *);
-status_t    c4_set_port (ci_t *, int);
-int         c4_pld_rw (ci_t *, struct sbecom_port_param *);
-void        cleanup_devs (void);
-void        cleanup_ioremap (void);
-status_t    musycc_chan_down (ci_t *, int);
-irqreturn_t musycc_intr_th_handler (void *);
-int         musycc_start_xmit (ci_t *, int, void *);
+int         c4_frame_rw(ci_t *, struct sbecom_port_param *);
+status_t    c4_get_port(ci_t *, int);
+int         c4_loop_port(ci_t *, int, u_int8_t);
+int         c4_musycc_rw(ci_t *, struct c4_musycc_param *);
+int         c4_new_chan(ci_t *, int, int, void *);
+status_t    c4_set_port(ci_t *, int);
+int         c4_pld_rw(ci_t *, struct sbecom_port_param *);
+void        cleanup_devs(void);
+void        cleanup_ioremap(void);
+status_t    musycc_chan_down(ci_t *, int);
+irqreturn_t musycc_intr_th_handler(void *);
+int         musycc_start_xmit(ci_t *, int, void *);
 
 extern char pmcc4_OSSI_release[];
 extern ci_t *CI;
 extern struct s_hdw_info hdw_info[];
 
 #if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
-    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+       defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
 #define _v7_hdlc_  1
 #else
 #define _v7_hdlc_  0
@@ -94,9 +94,9 @@ extern struct s_hdw_info hdw_info[];
 
 #if _v7_hdlc_
 #define V7(x) (x ## _v7)
-extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
-extern int  register_hdlc_device_v7 (hdlc_device *);
-extern int  unregister_hdlc_device_v7 (hdlc_device *);
+extern int  hdlc_netif_rx_v7(hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7(hdlc_device *);
+extern int  unregister_hdlc_device_v7(hdlc_device *);
 
 #else
 #define V7(x) x
@@ -127,33 +127,33 @@ module_param(max_rxdesc_used, int, 0444);
 /****************************************************************************/
 /****************************************************************************/
 
-void       *
-getuserbychan (int channum)
+void *
+getuserbychan(int channum)
 {
-    mch_t      *ch;
+       mch_t      *ch;
 
-    ch = c4_find_chan (channum);
-    return ch ? ch->user : NULL;
+       ch = c4_find_chan(channum);
+       return ch ? ch->user : NULL;
 }
 
 
-char       *
-get_hdlc_name (hdlc_device *hdlc)
+char *
+get_hdlc_name(hdlc_device *hdlc)
 {
-    struct c4_priv *priv = hdlc->priv;
-    struct net_device *dev = getuserbychan (priv->channum);
+       struct c4_priv *priv = hdlc->priv;
+       struct net_device *dev = getuserbychan(priv->channum);
 
-    return dev->name;
+       return dev->name;
 }
 
 
-static      status_t
-mkret (int bsd)
+static status_t
+mkret(int bsd)
 {
-    if (bsd > 0)
-        return -bsd;
-    else
-        return bsd;
+       if (bsd > 0)
+               return -bsd;
+       else
+               return bsd;
 }
 
 /***************************************************************************/
@@ -179,956 +179,978 @@ mkret (int bsd)
  * within a port's group.
  */
 void
-c4_wk_chan_restart (mch_t *ch)
+c4_wk_chan_restart(mch_t *ch)
 {
-    mpi_t      *pi = ch->up;
+       mpi_t      *pi = ch->up;
 
 #ifdef RLD_RESTART_DEBUG
-    pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
-            __func__, pi->portnum, ch->channum, ch);
+       pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
+               __func__, pi->portnum, ch->channum, ch);
 #endif
 
-    /* create new entry w/in workqueue for this channel and let'er rip */
+       /* create new entry w/in workqueue for this channel and let'er rip */
 
-    /** queue_work (struct workqueue_struct *queue,
-     **             struct work_struct *work);
-     **/
-    queue_work (pi->wq_port, &ch->ch_work);
+       /** queue_work(struct workqueue_struct *queue,
+        **            struct work_struct *work);
+        **/
+       queue_work(pi->wq_port, &ch->ch_work);
 }
 
 status_t
-c4_wk_chan_init (mpi_t *pi, mch_t *ch)
+c4_wk_chan_init(mpi_t *pi, mch_t *ch)
 {
-    /*
-     * this will be used to restart a stopped channel
-     */
-
-    /** INIT_WORK (struct work_struct *work,
-     **            void (*function)(void *),
-     **            void *data);
-     **/
-    INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
-    return 0;                       /* success */
+       /*
+        * this will be used to restart a stopped channel
+        */
+
+       /** INIT_WORK(struct work_struct *work,
+        **           void (*function)(void *),
+        **           void *data);
+        **/
+       INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
+       return 0;                       /* success */
 }
 
 status_t
-c4_wq_port_init (mpi_t *pi)
+c4_wq_port_init(mpi_t *pi)
 {
 
-    char        name[16], *np;  /* NOTE: name of the queue limited by system
-                                 * to 10 characters */
+       char        name[16], *np;  /* NOTE: name of the queue limited by system
+                                    * to 10 characters */
 
-    if (pi->wq_port)
-        return 0;                   /* already initialized */
+       if (pi->wq_port)
+               return 0;                   /* already initialized */
 
-    np = name;
-    memset (name, 0, 16);
-    sprintf (np, "%s%d", pi->up->devname, pi->portnum); /* IE pmcc4-01) */
+       np = name;
+       memset(name, 0, 16);
+       sprintf(np, "%s%d", pi->up->devname, pi->portnum); /* IE pmcc4-01) */
 
 #ifdef RLD_RESTART_DEBUG
-    pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
-            __func__, name, pi->portnum); /* RLD DEBUG */
+       pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
+               __func__, name, pi->portnum); /* RLD DEBUG */
 #endif
-    if (!(pi->wq_port = create_singlethread_workqueue (name)))
-        return -ENOMEM;
-    return 0;                       /* success */
+       if (!(pi->wq_port = create_singlethread_workqueue(name)))
+               return -ENOMEM;
+       return 0;                       /* success */
 }
 
 void
-c4_wq_port_cleanup (mpi_t *pi)
+c4_wq_port_cleanup(mpi_t *pi)
 {
-    /*
-     * PORT POINT: cannot call this if WQ is statically allocated w/in
-     * structure since it calls kfree(wq);
-     */
-    if (pi->wq_port)
-    {
-        destroy_workqueue (pi->wq_port);        /* this also calls
-                                                 * flush_workqueue() */
-        pi->wq_port = NULL;
-    }
+       /*
+        * PORT POINT: cannot call this if WQ is statically allocated w/in
+        * structure since it calls kfree(wq);
+        */
+       if (pi->wq_port)
+       {
+               destroy_workqueue(pi->wq_port);        /* this also calls
+                                                       * flush_workqueue() */
+               pi->wq_port = NULL;
+       }
 }
 
 /***************************************************************************/
 
 irqreturn_t
-c4_linux_interrupt (int irq, void *dev_instance)
+c4_linux_interrupt(int irq, void *dev_instance)
 {
-    struct net_device *ndev = dev_instance;
+       struct net_device *ndev = dev_instance;
 
-    return musycc_intr_th_handler(netdev_priv(ndev));
+       return musycc_intr_th_handler(netdev_priv(ndev));
 }
 
 
 #ifdef CONFIG_SBE_PMCC4_NCOMM
 irqreturn_t
-c4_ebus_interrupt (int irq, void *dev_instance)
+c4_ebus_interrupt(int irq, void *dev_instance)
 {
-    struct net_device *ndev = dev_instance;
+       struct net_device *ndev = dev_instance;
 
-    return c4_ebus_intr_th_handler(netdev_priv(ndev));
+       return c4_ebus_intr_th_handler(netdev_priv(ndev));
 }
 #endif
 
 
 static int
-void_open (struct net_device *ndev)
+void_open(struct net_device *ndev)
 {
-    pr_info("%s: trying to open master device !\n", ndev->name);
-    return -1;
+       pr_info("%s: trying to open master device !\n", ndev->name);
+       return -1;
 }
 
 
 static int
-chan_open (struct net_device *ndev)
+chan_open(struct net_device *ndev)
 {
-    hdlc_device *hdlc = dev_to_hdlc (ndev);
-    const struct c4_priv *priv = hdlc->priv;
-    int         ret;
-
-    if ((ret = hdlc_open (ndev)))
-    {
-        pr_info("hdlc_open failure, err %d.\n", ret);
-        return ret;
-    }
-    if ((ret = c4_chan_up (priv->ci, priv->channum)))
-        return -ret;
-    try_module_get (THIS_MODULE);
-    netif_start_queue (ndev);
-    return 0;                       /* no error = success */
+       hdlc_device *hdlc = dev_to_hdlc(ndev);
+       const struct c4_priv *priv = hdlc->priv;
+       int         ret;
+
+       if ((ret = hdlc_open(ndev)))
+       {
+               pr_info("hdlc_open failure, err %d.\n", ret);
+               return ret;
+       }
+       if ((ret = c4_chan_up(priv->ci, priv->channum)))
+               return -ret;
+       try_module_get(THIS_MODULE);
+       netif_start_queue(ndev);
+       return 0;                       /* no error = success */
 }
 
 
 static int
-chan_close (struct net_device *ndev)
+chan_close(struct net_device *ndev)
 {
-    hdlc_device *hdlc = dev_to_hdlc (ndev);
-    const struct c4_priv *priv = hdlc->priv;
-
-    netif_stop_queue (ndev);
-    musycc_chan_down ((ci_t *) 0, priv->channum);
-    hdlc_close (ndev);
-    module_put (THIS_MODULE);
-    return 0;
+       hdlc_device *hdlc = dev_to_hdlc(ndev);
+       const struct c4_priv *priv = hdlc->priv;
+
+       netif_stop_queue(ndev);
+       musycc_chan_down((ci_t *) 0, priv->channum);
+       hdlc_close(ndev);
+       module_put(THIS_MODULE);
+       return 0;
 }
 
 
 static int
-chan_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+chan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-    return hdlc_ioctl (dev, ifr, cmd);
+       return hdlc_ioctl(dev, ifr, cmd);
 }
 
 
 static int
-chan_attach_noop (struct net_device *ndev, unsigned short foo_1, unsigned short foo_2)
+chan_attach_noop(struct net_device *ndev, unsigned short foo_1,
+                unsigned short foo_2)
 {
-    return 0;                   /* our driver has nothing to do here, show's
-                                 * over, go home */
+       /* our driver has nothing to do here, show's
+        * over, go home
+        */
+       return 0;
 }
 
 
 static struct net_device_stats *
-chan_get_stats (struct net_device *ndev)
+chan_get_stats(struct net_device *ndev)
 {
-    mch_t      *ch;
-    struct net_device_stats *nstats;
-    struct sbecom_chan_stats *stats;
-    int         channum;
-
-    {
-        struct c4_priv *priv;
-
-        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
-        channum = priv->channum;
-    }
-
-    ch = c4_find_chan (channum);
-    if (ch == NULL)
-        return NULL;
-
-    nstats = &ndev->stats;
-    stats = &ch->s;
-
-    memset (nstats, 0, sizeof (struct net_device_stats));
-    nstats->rx_packets = stats->rx_packets;
-    nstats->tx_packets = stats->tx_packets;
-    nstats->rx_bytes = stats->rx_bytes;
-    nstats->tx_bytes = stats->tx_bytes;
-    nstats->rx_errors = stats->rx_length_errors +
-        stats->rx_over_errors +
-        stats->rx_crc_errors +
-        stats->rx_frame_errors +
-        stats->rx_fifo_errors +
-        stats->rx_missed_errors;
-    nstats->tx_errors = stats->tx_dropped +
-        stats->tx_aborted_errors +
-        stats->tx_fifo_errors;
-    nstats->rx_dropped = stats->rx_dropped;
-    nstats->tx_dropped = stats->tx_dropped;
-
-    nstats->rx_length_errors = stats->rx_length_errors;
-    nstats->rx_over_errors = stats->rx_over_errors;
-    nstats->rx_crc_errors = stats->rx_crc_errors;
-    nstats->rx_frame_errors = stats->rx_frame_errors;
-    nstats->rx_fifo_errors = stats->rx_fifo_errors;
-    nstats->rx_missed_errors = stats->rx_missed_errors;
-
-    nstats->tx_aborted_errors = stats->tx_aborted_errors;
-    nstats->tx_fifo_errors = stats->tx_fifo_errors;
-
-    return nstats;
+       mch_t      *ch;
+       struct net_device_stats *nstats;
+       struct sbecom_chan_stats *stats;
+       int         channum;
+
+       {
+               struct c4_priv *priv;
+
+               priv = (struct c4_priv *)dev_to_hdlc(ndev)->priv;
+               channum = priv->channum;
+       }
+
+       ch = c4_find_chan(channum);
+       if (ch == NULL)
+               return NULL;
+
+       nstats = &ndev->stats;
+       stats = &ch->s;
+
+       memset(nstats, 0, sizeof(struct net_device_stats));
+       nstats->rx_packets = stats->rx_packets;
+       nstats->tx_packets = stats->tx_packets;
+       nstats->rx_bytes = stats->rx_bytes;
+       nstats->tx_bytes = stats->tx_bytes;
+       nstats->rx_errors = stats->rx_length_errors +
+               stats->rx_over_errors +
+               stats->rx_crc_errors +
+               stats->rx_frame_errors +
+               stats->rx_fifo_errors +
+               stats->rx_missed_errors;
+       nstats->tx_errors = stats->tx_dropped +
+               stats->tx_aborted_errors +
+               stats->tx_fifo_errors;
+       nstats->rx_dropped = stats->rx_dropped;
+       nstats->tx_dropped = stats->tx_dropped;
+
+       nstats->rx_length_errors = stats->rx_length_errors;
+       nstats->rx_over_errors = stats->rx_over_errors;
+       nstats->rx_crc_errors = stats->rx_crc_errors;
+       nstats->rx_frame_errors = stats->rx_frame_errors;
+       nstats->rx_fifo_errors = stats->rx_fifo_errors;
+       nstats->rx_missed_errors = stats->rx_missed_errors;
+
+       nstats->tx_aborted_errors = stats->tx_aborted_errors;
+       nstats->tx_fifo_errors = stats->tx_fifo_errors;
+
+       return nstats;
 }
 
 
 static ci_t *
-get_ci_by_dev (struct net_device *ndev)
+get_ci_by_dev(struct net_device *ndev)
 {
-    return (ci_t *)(netdev_priv(ndev));
+       return (ci_t *)(netdev_priv(ndev));
 }
 
 
 static int
-c4_linux_xmit (struct sk_buff *skb, struct net_device *ndev)
+c4_linux_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-    const struct c4_priv *priv;
-    int         rval;
+       const struct c4_priv *priv;
+       int         rval;
 
-    hdlc_device *hdlc = dev_to_hdlc (ndev);
+       hdlc_device *hdlc = dev_to_hdlc(ndev);
 
-    priv = hdlc->priv;
+       priv = hdlc->priv;
 
-    rval = musycc_start_xmit (priv->ci, priv->channum, skb);
-    return rval;
+       rval = musycc_start_xmit(priv->ci, priv->channum, skb);
+       return rval;
 }
 
 static const struct net_device_ops chan_ops = {
-       .ndo_open       = chan_open,
-       .ndo_stop       = chan_close,
-       .ndo_start_xmit = c4_linux_xmit,
-       .ndo_do_ioctl   = chan_dev_ioctl,
-       .ndo_get_stats  = chan_get_stats,
+       .ndo_open       = chan_open,
+       .ndo_stop       = chan_close,
+       .ndo_start_xmit = c4_linux_xmit,
+       .ndo_do_ioctl   = chan_dev_ioctl,
+       .ndo_get_stats  = chan_get_stats,
 };
 
 static struct net_device *
-create_chan (struct net_device *ndev, ci_t *ci,
-             struct sbecom_chan_param *cp)
+create_chan(struct net_device *ndev, ci_t *ci,
+           struct sbecom_chan_param *cp)
 {
-    hdlc_device *hdlc;
-    struct net_device *dev;
-    hdw_info_t *hi;
-    int         ret;
-
-    if (c4_find_chan (cp->channum))
-        return NULL;                   /* channel already exists */
-
-    {
-        struct c4_priv *priv;
-
-        /* allocate then fill in private data structure */
-        priv = OS_kmalloc (sizeof (struct c4_priv));
-        if (!priv)
-        {
-            pr_warning("%s: no memory for net_device !\n", ci->devname);
-           return NULL;
-        }
-        dev = alloc_hdlcdev (priv);
-        if (!dev)
-        {
-            pr_warning("%s: no memory for hdlc_device !\n", ci->devname);
-            OS_kfree (priv);
-           return NULL;
-        }
-        priv->ci = ci;
-        priv->channum = cp->channum;
-    }
-
-    hdlc = dev_to_hdlc (dev);
-
-    dev->base_addr = 0;             /* not I/O mapped */
-    dev->irq = ndev->irq;
-    dev->type = ARPHRD_RAWHDLC;
-    *dev->name = 0;                 /* default ifconfig name = "hdlc" */
-
-    hi = (hdw_info_t *) ci->hdw_info;
-    if (hi->mfg_info_sts == EEPROM_OK)
-    {
-        switch (hi->promfmt)
-        {
-        case PROM_FORMAT_TYPE1:
-            memcpy (dev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-            break;
-        case PROM_FORMAT_TYPE2:
-            memcpy (dev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-            break;
-        default:
-            memset (dev->dev_addr, 0, 6);
-            break;
-        }
-    } else
-    {
-        memset (dev->dev_addr, 0, 6);
-    }
-
-    hdlc->xmit = c4_linux_xmit;
-
-    dev->netdev_ops = &chan_ops;
-    /*
-     * The native hdlc stack calls this 'attach' routine during
-     * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
-     * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
-     * routine is actually registered or not, we supply a dummy routine which
-     * does nothing (since encoding and parity are setup for our driver via a
-     * special configuration application).
-     */
-
-    hdlc->attach = chan_attach_noop;
-
-    rtnl_unlock ();                 /* needed due to Ioctl calling sequence */
-    ret = register_hdlc_device (dev);
-    /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
-    dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
-
-    rtnl_lock ();                   /* needed due to Ioctl calling sequence */
-    if (ret)
-    {
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: create_chan[%d] registration error = %d.\n",
-                    ci->devname, cp->channum, ret);
-        free_netdev (dev);          /* cleanup */
-       return NULL;            /* failed to register */
-    }
-    return dev;
+       hdlc_device *hdlc;
+       struct net_device *dev;
+       hdw_info_t *hi;
+       int         ret;
+
+       if (c4_find_chan(cp->channum))
+               return NULL;                   /* channel already exists */
+
+       {
+               struct c4_priv *priv;
+
+               /* allocate then fill in private data structure */
+               priv = OS_kmalloc(sizeof(struct c4_priv));
+               if (!priv)
+               {
+                       pr_warning("%s: no memory for net_device !\n",
+                                  ci->devname);
+                       return NULL;
+               }
+               dev = alloc_hdlcdev(priv);
+               if (!dev)
+               {
+                       pr_warning("%s: no memory for hdlc_device !\n",
+                                  ci->devname);
+                       OS_kfree(priv);
+                       return NULL;
+               }
+               priv->ci = ci;
+               priv->channum = cp->channum;
+       }
+
+       hdlc = dev_to_hdlc(dev);
+
+       dev->base_addr = 0;             /* not I/O mapped */
+       dev->irq = ndev->irq;
+       dev->type = ARPHRD_RAWHDLC;
+       *dev->name = 0;                 /* default ifconfig name = "hdlc" */
+
+       hi = (hdw_info_t *)ci->hdw_info;
+       if (hi->mfg_info_sts == EEPROM_OK)
+       {
+               switch (hi->promfmt)
+               {
+               case PROM_FORMAT_TYPE1:
+                       memcpy(dev->dev_addr,
+                              (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+                       break;
+               case PROM_FORMAT_TYPE2:
+                       memcpy(dev->dev_addr,
+                              (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+                       break;
+               default:
+                       memset(dev->dev_addr, 0, 6);
+                       break;
+               }
+       } else
+       {
+               memset(dev->dev_addr, 0, 6);
+       }
+
+       hdlc->xmit = c4_linux_xmit;
+
+       dev->netdev_ops = &chan_ops;
+       /*
+        * The native hdlc stack calls this 'attach' routine during
+        * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
+        * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
+        * routine is actually registered or not, we supply a dummy routine which
+        * does nothing (since encoding and parity are setup for our driver via a
+        * special configuration application).
+        */
+
+       hdlc->attach = chan_attach_noop;
+
+       /* needed due to Ioctl calling sequence */
+       rtnl_unlock();
+       ret = register_hdlc_device(dev);
+       /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
+       dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
+
+       /* needed due to Ioctl calling sequence */
+       rtnl_lock();
+       if (ret)
+       {
+               if (cxt1e1_log_level >= LOG_WARN)
+                       pr_info("%s: create_chan[%d] registration error = %d.\n",
+                               ci->devname, cp->channum, ret);
+               /* cleanup */
+               free_netdev(dev);
+               /* failed to register */
+               return NULL;
+       }
+       return dev;
 }
 
 
 /* the idea here is to get port information and pass it back (using pointer) */
-static      status_t
-do_get_port (struct net_device *ndev, void *data)
+static status_t
+do_get_port(struct net_device *ndev, void *data)
 {
-    int         ret;
-    ci_t       *ci;             /* ci stands for card information */
-    struct sbecom_port_param pp;/* copy data to kernel land */
-
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    if (pp.portnum >= MUSYCC_NPORTS)
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;             /* get card info */
-
-    ret = mkret (c4_get_port (ci, pp.portnum));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &ci->port[pp.portnum].p,
-                      sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    return 0;
+       int         ret;
+       ci_t       *ci;             /* ci stands for card information */
+       struct sbecom_port_param pp;/* copy data to kernel land */
+
+       if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       if (pp.portnum >= MUSYCC_NPORTS)
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;             /* get card info */
+
+       ret = mkret(c4_get_port(ci, pp.portnum));
+       if (ret)
+               return ret;
+       if (copy_to_user(data, &ci->port[pp.portnum].p,
+                        sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       return 0;
 }
 
 /* this function copys the user data and then calls the real action function */
-static      status_t
-do_set_port (struct net_device *ndev, void *data)
+static status_t
+do_set_port(struct net_device *ndev, void *data)
 {
-    ci_t       *ci;             /* ci stands for card information */
-    struct sbecom_port_param pp;/* copy data to kernel land */
-
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    if (pp.portnum >= MUSYCC_NPORTS)
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;             /* get card info */
-
-    if (pp.portnum >= ci->max_port) /* sanity check */
-        return -ENXIO;
-
-    memcpy (&ci->port[pp.portnum].p, &pp, sizeof (struct sbecom_port_param));
-    return mkret (c4_set_port (ci, pp.portnum));
+       ci_t       *ci;             /* ci stands for card information */
+       struct sbecom_port_param pp;/* copy data to kernel land */
+
+       if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       if (pp.portnum >= MUSYCC_NPORTS)
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;             /* get card info */
+
+       if (pp.portnum >= ci->max_port) /* sanity check */
+               return -ENXIO;
+
+       memcpy(&ci->port[pp.portnum].p, &pp, sizeof(struct sbecom_port_param));
+       return mkret(c4_set_port(ci, pp.portnum));
 }
 
 /* work the port loopback mode as per directed */
-static      status_t
-do_port_loop (struct net_device *ndev, void *data)
+static status_t
+do_port_loop(struct net_device *ndev, void *data)
 {
-    struct sbecom_port_param pp;
-    ci_t       *ci;
-
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    return mkret (c4_loop_port (ci, pp.portnum, pp.port_mode));
+       struct sbecom_port_param pp;
+       ci_t       *ci;
+
+       if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;
+       return mkret(c4_loop_port(ci, pp.portnum, pp.port_mode));
 }
 
 /* set the specified register with the given value / or just read it */
-static      status_t
-do_framer_rw (struct net_device *ndev, void *data)
+static status_t
+do_framer_rw(struct net_device *ndev, void *data)
 {
-    struct sbecom_port_param pp;
-    ci_t       *ci;
-    int         ret;
-
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    ret = mkret (c4_frame_rw (ci, &pp));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    return 0;
+       struct sbecom_port_param pp;
+       ci_t       *ci;
+       int         ret;
+
+       if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;
+       ret = mkret(c4_frame_rw(ci, &pp));
+       if (ret)
+               return ret;
+       if (copy_to_user(data, &pp, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       return 0;
 }
 
 /* set the specified register with the given value / or just read it */
-static      status_t
-do_pld_rw (struct net_device *ndev, void *data)
+static status_t
+do_pld_rw(struct net_device *ndev, void *data)
 {
-    struct sbecom_port_param pp;
-    ci_t       *ci;
-    int         ret;
-
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    ret = mkret (c4_pld_rw (ci, &pp));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    return 0;
+       struct sbecom_port_param pp;
+       ci_t       *ci;
+       int         ret;
+
+       if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;
+       ret = mkret(c4_pld_rw(ci, &pp));
+       if (ret)
+               return ret;
+       if (copy_to_user(data, &pp, sizeof(struct sbecom_port_param)))
+               return -EFAULT;
+       return 0;
 }
 
 /* set the specified register with the given value / or just read it */
-static      status_t
-do_musycc_rw (struct net_device *ndev, void *data)
+static status_t
+do_musycc_rw(struct net_device *ndev, void *data)
 {
-    struct c4_musycc_param mp;
-    ci_t       *ci;
-    int         ret;
-
-    if (copy_from_user (&mp, data, sizeof (struct c4_musycc_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    ret = mkret (c4_musycc_rw (ci, &mp));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &mp, sizeof (struct c4_musycc_param)))
-        return -EFAULT;
-    return 0;
+       struct c4_musycc_param mp;
+       ci_t       *ci;
+       int         ret;
+
+       if (copy_from_user(&mp, data, sizeof(struct c4_musycc_param)))
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;
+       ret = mkret(c4_musycc_rw(ci, &mp));
+       if (ret)
+               return ret;
+       if (copy_to_user(data, &mp, sizeof(struct c4_musycc_param)))
+               return -EFAULT;
+       return 0;
 }
 
-static      status_t
-do_get_chan (struct net_device *ndev, void *data)
+static status_t
+do_get_chan(struct net_device *ndev, void *data)
 {
-    struct sbecom_chan_param cp;
-    int         ret;
+       struct sbecom_chan_param cp;
+       int         ret;
 
-    if (copy_from_user (&cp, data,
-                        sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
+       if (copy_from_user(&cp, data,
+                               sizeof(struct sbecom_chan_param)))
+               return -EFAULT;
 
-    if ((ret = mkret (c4_get_chan (cp.channum, &cp))))
-        return ret;
+       if ((ret = mkret(c4_get_chan(cp.channum, &cp))))
+               return ret;
 
-    if (copy_to_user (data, &cp, sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    return 0;
+       if (copy_to_user(data, &cp, sizeof(struct sbecom_chan_param)))
+               return -EFAULT;
+       return 0;
 }
 
-static      status_t
-do_set_chan (struct net_device *ndev, void *data)
+static status_t
+do_set_chan(struct net_device *ndev, void *data)
 {
-    struct sbecom_chan_param cp;
-    int         ret;
-    ci_t       *ci;
-
-    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    switch (ret = mkret (c4_set_chan (cp.channum, &cp)))
-    {
-    case 0:
-        return 0;
-    default:
-        return ret;
-    }
+       struct sbecom_chan_param cp;
+       int         ret;
+       ci_t       *ci;
+
+       if (copy_from_user(&cp, data, sizeof(struct sbecom_chan_param)))
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;
+       switch (ret = mkret(c4_set_chan(cp.channum, &cp)))
+       {
+       case 0:
+               return 0;
+       default:
+               return ret;
+       }
 }
 
-static      status_t
-do_create_chan (struct net_device *ndev, void *data)
+static status_t
+do_create_chan(struct net_device *ndev, void *data)
 {
-    ci_t       *ci;
-    struct net_device *dev;
-    struct sbecom_chan_param cp;
-    int         ret;
-
-    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    dev = create_chan (ndev, ci, &cp);
-    if (!dev)
-        return -EBUSY;
-    ret = mkret (c4_new_chan (ci, cp.port, cp.channum, dev));
-    if (ret)
-    {
-        rtnl_unlock ();             /* needed due to Ioctl calling sequence */
-        unregister_hdlc_device (dev);
-        rtnl_lock ();               /* needed due to Ioctl calling sequence */
-        free_netdev (dev);
-    }
-    return ret;
+       ci_t       *ci;
+       struct net_device *dev;
+       struct sbecom_chan_param cp;
+       int         ret;
+
+       if (copy_from_user(&cp, data, sizeof(struct sbecom_chan_param)))
+               return -EFAULT;
+       ci = get_ci_by_dev(ndev);
+       if (!ci)
+               return -EINVAL;
+       dev = create_chan(ndev, ci, &cp);
+       if (!dev)
+               return -EBUSY;
+       ret = mkret(c4_new_chan(ci, cp.port, cp.channum, dev));
+       if (ret)
+       {
+               /* needed due to Ioctl calling sequence */
+               rtnl_unlock();
+               unregister_hdlc_device(dev);
+               /* needed due to Ioctl calling sequence */
+               rtnl_lock();
+               free_netdev(dev);
+       }
+       return ret;
 }
 
-static      status_t
-do_get_chan_stats (struct net_device *ndev, void *data)
+static status_t
+do_get_chan_stats(struct net_device *ndev, void *data)
 {
-    struct c4_chan_stats_wrap ccs;
-    int         ret;
-
-    if (copy_from_user (&ccs, data,
-                        sizeof (struct c4_chan_stats_wrap)))
-        return -EFAULT;
-    switch (ret = mkret (c4_get_chan_stats (ccs.channum, &ccs.stats)))
-    {
-    case 0:
-        break;
-    default:
-        return ret;
-    }
-    if (copy_to_user (data, &ccs,
-                      sizeof (struct c4_chan_stats_wrap)))
-        return -EFAULT;
-    return 0;
+       struct c4_chan_stats_wrap ccs;
+       int         ret;
+
+       if (copy_from_user(&ccs, data,
+                          sizeof(struct c4_chan_stats_wrap)))
+               return -EFAULT;
+       switch (ret = mkret(c4_get_chan_stats(ccs.channum, &ccs.stats)))
+       {
+       case 0:
+               break;
+       default:
+               return ret;
+       }
+       if (copy_to_user(data, &ccs,
+                        sizeof(struct c4_chan_stats_wrap)))
+               return -EFAULT;
+       return 0;
 }
-static      status_t
-do_set_loglevel (struct net_device *ndev, void *data)
+static status_t
+do_set_loglevel(struct net_device *ndev, void *data)
 {
-    unsigned int cxt1e1_log_level;
+       unsigned int cxt1e1_log_level;
 
-    if (copy_from_user (&cxt1e1_log_level, data, sizeof (int)))
-        return -EFAULT;
-    sbecom_set_loglevel (cxt1e1_log_level);
-    return 0;
+       if (copy_from_user(&cxt1e1_log_level, data, sizeof(int)))
+               return -EFAULT;
+       sbecom_set_loglevel(cxt1e1_log_level);
+       return 0;
 }
 
-static      status_t
-do_deluser (struct net_device *ndev, int lockit)
+static status_t
+do_deluser(struct net_device *ndev, int lockit)
 {
-    if (ndev->flags & IFF_UP)
-        return -EBUSY;
-
-    {
-        ci_t       *ci;
-        mch_t      *ch;
-        const struct c4_priv *priv;
-        int         channum;
-
-        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
-        ci = priv->ci;
-        channum = priv->channum;
-
-        ch = c4_find_chan (channum);
-        if (ch == NULL)
-            return -ENOENT;
-       ch->user = NULL;        /* will be freed, below */
-    }
-
-    if (lockit)
-        rtnl_unlock ();             /* needed if Ioctl calling sequence */
-    unregister_hdlc_device (ndev);
-    if (lockit)
-        rtnl_lock ();               /* needed if Ioctl calling sequence */
-    free_netdev (ndev);
-    return 0;
+       if (ndev->flags & IFF_UP)
+               return -EBUSY;
+
+       {
+               ci_t       *ci;
+               mch_t      *ch;
+               const struct c4_priv *priv;
+               int         channum;
+
+               priv = (struct c4_priv *)dev_to_hdlc(ndev)->priv;
+               ci = priv->ci;
+               channum = priv->channum;
+
+               ch = c4_find_chan(channum);
+               if (ch == NULL)
+                       return -ENOENT;
+               ch->user = NULL;        /* will be freed, below */
+       }
+
+       /* needed if Ioctl calling sequence */
+       if (lockit)
+               rtnl_unlock();
+       unregister_hdlc_device(ndev);
+       /* needed if Ioctl calling sequence */
+       if (lockit)
+               rtnl_lock();
+       free_netdev(ndev);
+       return 0;
 }
 
 int
-do_del_chan (struct net_device *musycc_dev, void *data)
+do_del_chan(struct net_device *musycc_dev, void *data)
 {
-    struct sbecom_chan_param cp;
-    char        buf[sizeof (CHANNAME) + 3];
-    struct net_device *dev;
-    int         ret;
-
-    if (copy_from_user (&cp, data,
-                        sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    if (cp.channum > 999)
-        return -EINVAL;
-    snprintf (buf, sizeof(buf), CHANNAME "%d", cp.channum);
+       struct sbecom_chan_param cp;
+       char        buf[sizeof(CHANNAME) + 3];
+       struct net_device *dev;
+       int         ret;
+
+       if (copy_from_user(&cp, data,
+                          sizeof(struct sbecom_chan_param)))
+               return -EFAULT;
+       if (cp.channum > 999)
+               return -EINVAL;
+       snprintf(buf, sizeof(buf), CHANNAME "%d", cp.channum);
        dev = __dev_get_by_name(&init_net, buf);
        if (!dev)
                return -ENODEV;
-    ret = do_deluser (dev, 1);
-    if (ret)
-        return ret;
-    return c4_del_chan (cp.channum);
+       ret = do_deluser(dev, 1);
+       if (ret)
+               return ret;
+       return c4_del_chan(cp.channum);
 }
-int         c4_reset_board (void *);
+int c4_reset_board(void *);
 
 int
-do_reset (struct net_device *musycc_dev, void *data)
+do_reset(struct net_device *musycc_dev, void *data)
 {
-    const struct c4_priv *priv;
-    int         i;
-
-    for (i = 0; i < 128; i++)
-    {
-        struct net_device *ndev;
-        char        buf[sizeof (CHANNAME) + 3];
-
-        sprintf (buf, CHANNAME "%d", i);
-       ndev = __dev_get_by_name(&init_net, buf);
-       if (!ndev)
-               continue;
-        priv = dev_to_hdlc (ndev)->priv;
-
-        if ((unsigned long) (priv->ci) ==
-            (unsigned long) (netdev_priv(musycc_dev)))
-        {
-            ndev->flags &= ~IFF_UP;
-            netif_stop_queue (ndev);
-            do_deluser (ndev, 1);
+       const struct c4_priv *priv;
+       int         i;
+
+       for (i = 0; i < 128; i++)
+       {
+               struct net_device *ndev;
+               char        buf[sizeof(CHANNAME) + 3];
+
+               sprintf(buf, CHANNAME "%d", i);
+               ndev = __dev_get_by_name(&init_net, buf);
+               if (!ndev)
+                       continue;
+               priv = dev_to_hdlc(ndev)->priv;
+
+               if ((unsigned long) (priv->ci) ==
+                       (unsigned long) (netdev_priv(musycc_dev)))
+               {
+                       ndev->flags &= ~IFF_UP;
+                       netif_stop_queue(ndev);
+                       do_deluser(ndev, 1);
+               }
        }
-    }
-    return 0;
+       return 0;
 }
 
 int
-do_reset_chan_stats (struct net_device *musycc_dev, void *data)
+do_reset_chan_stats(struct net_device *musycc_dev, void *data)
 {
-    struct sbecom_chan_param cp;
+       struct sbecom_chan_param cp;
 
-    if (copy_from_user (&cp, data,
-                        sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    return mkret (c4_del_chan_stats (cp.channum));
+       if (copy_from_user(&cp, data,
+                          sizeof(struct sbecom_chan_param)))
+               return -EFAULT;
+       return mkret(c4_del_chan_stats(cp.channum));
 }
 
-static      status_t
-c4_ioctl (struct net_device *ndev, struct ifreq *ifr, int cmd)
+static status_t
+c4_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
 {
-    ci_t       *ci;
-    void       *data;
-    int         iocmd, iolen;
-    status_t    ret;
-    static struct data
-    {
-        union
-        {
-            u_int8_t c;
-            u_int32_t i;
-            struct sbe_brd_info bip;
-            struct sbe_drv_info dip;
-            struct sbe_iid_info iip;
-            struct sbe_brd_addr bap;
-            struct sbecom_chan_stats stats;
-            struct sbecom_chan_param param;
-            struct temux_card_stats cards;
-            struct sbecom_card_param cardp;
-            struct sbecom_framer_param frp;
-        }           u;
-    }           arg;
-
-
-    if (!capable (CAP_SYS_ADMIN))
-        return -EPERM;
-    if (cmd != SIOCDEVPRIVATE + 15)
-        return -EINVAL;
-    if (!(ci = get_ci_by_dev (ndev)))
-        return -EINVAL;
-    if (ci->state != C_RUNNING)
-        return -ENODEV;
-    if (copy_from_user (&iocmd, ifr->ifr_data, sizeof (iocmd)))
-        return -EFAULT;
+       ci_t       *ci;
+       void       *data;
+       int         iocmd, iolen;
+       status_t    ret;
+       static struct data
+       {
+               union
+               {
+                       u_int8_t c;
+                       u_int32_t i;
+                       struct sbe_brd_info bip;
+                       struct sbe_drv_info dip;
+                       struct sbe_iid_info iip;
+                       struct sbe_brd_addr bap;
+                       struct sbecom_chan_stats stats;
+                       struct sbecom_chan_param param;
+                       struct temux_card_stats cards;
+                       struct sbecom_card_param cardp;
+                       struct sbecom_framer_param frp;
+               } u;
+       } arg;
+
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       if (cmd != SIOCDEVPRIVATE + 15)
+               return -EINVAL;
+       if (!(ci = get_ci_by_dev(ndev)))
+               return -EINVAL;
+       if (ci->state != C_RUNNING)
+               return -ENODEV;
+       if (copy_from_user(&iocmd, ifr->ifr_data, sizeof(iocmd)))
+               return -EFAULT;
 #if 0
-    if (copy_from_user (&len, ifr->ifr_data + sizeof (iocmd), sizeof (len)))
-        return -EFAULT;
+       if (copy_from_user(&len, ifr->ifr_data + sizeof(iocmd), sizeof(len)))
+               return -EFAULT;
 #endif
 
 #if 0
-    pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
-            _IOC_DIR (iocmd), _IOC_TYPE (iocmd), _IOC_NR (iocmd),
-            _IOC_SIZE (iocmd));
+       pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
+               _IOC_DIR(iocmd), _IOC_TYPE(iocmd), _IOC_NR(iocmd),
+               _IOC_SIZE(iocmd));
 #endif
-    iolen = _IOC_SIZE (iocmd);
-    data = ifr->ifr_data + sizeof (iocmd);
-    if (copy_from_user (&arg, data, iolen))
-        return -EFAULT;
-
-    ret = 0;
-    switch (iocmd)
-    {
-    case SBE_IOC_PORT_GET:
-        //pr_info(">> SBE_IOC_PORT_GET Ioctl...\n");
-        ret = do_get_port (ndev, data);
-        break;
-    case SBE_IOC_PORT_SET:
-        //pr_info(">> SBE_IOC_PORT_SET Ioctl...\n");
-        ret = do_set_port (ndev, data);
-        break;
-    case SBE_IOC_CHAN_GET:
-        //pr_info(">> SBE_IOC_CHAN_GET Ioctl...\n");
-        ret = do_get_chan (ndev, data);
-        break;
-    case SBE_IOC_CHAN_SET:
-        //pr_info(">> SBE_IOC_CHAN_SET Ioctl...\n");
-        ret = do_set_chan (ndev, data);
-        break;
-    case C4_DEL_CHAN:
-        //pr_info(">> C4_DEL_CHAN Ioctl...\n");
-        ret = do_del_chan (ndev, data);
-        break;
-    case SBE_IOC_CHAN_NEW:
-        ret = do_create_chan (ndev, data);
-        break;
-    case SBE_IOC_CHAN_GET_STAT:
-        ret = do_get_chan_stats (ndev, data);
-        break;
-    case SBE_IOC_LOGLEVEL:
-        ret = do_set_loglevel (ndev, data);
-        break;
-    case SBE_IOC_RESET_DEV:
-        ret = do_reset (ndev, data);
-        break;
-    case SBE_IOC_CHAN_DEL_STAT:
-        ret = do_reset_chan_stats (ndev, data);
-        break;
-    case C4_LOOP_PORT:
-        ret = do_port_loop (ndev, data);
-        break;
-    case C4_RW_FRMR:
-        ret = do_framer_rw (ndev, data);
-        break;
-    case C4_RW_MSYC:
-        ret = do_musycc_rw (ndev, data);
-        break;
-    case C4_RW_PLD:
-        ret = do_pld_rw (ndev, data);
-        break;
-    case SBE_IOC_IID_GET:
-        ret = (iolen == sizeof (struct sbe_iid_info)) ? c4_get_iidinfo (ci, &arg.u.iip) : -EFAULT;
-        if (ret == 0)               /* no error, copy data */
-            if (copy_to_user (data, &arg, iolen))
-                return -EFAULT;
-        break;
-    default:
-        //pr_info(">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
-        ret = -EINVAL;
-        break;
-    }
-    return mkret (ret);
+       iolen = _IOC_SIZE(iocmd);
+       data = ifr->ifr_data + sizeof(iocmd);
+       if (copy_from_user(&arg, data, iolen))
+               return -EFAULT;
+
+       ret = 0;
+       switch (iocmd)
+       {
+       case SBE_IOC_PORT_GET:
+               //pr_info(">> SBE_IOC_PORT_GET Ioctl...\n");
+               ret = do_get_port(ndev, data);
+               break;
+       case SBE_IOC_PORT_SET:
+               //pr_info(">> SBE_IOC_PORT_SET Ioctl...\n");
+               ret = do_set_port(ndev, data);
+               break;
+       case SBE_IOC_CHAN_GET:
+               //pr_info(">> SBE_IOC_CHAN_GET Ioctl...\n");
+               ret = do_get_chan(ndev, data);
+               break;
+       case SBE_IOC_CHAN_SET:
+               //pr_info(">> SBE_IOC_CHAN_SET Ioctl...\n");
+               ret = do_set_chan(ndev, data);
+               break;
+       case C4_DEL_CHAN:
+               //pr_info(">> C4_DEL_CHAN Ioctl...\n");
+               ret = do_del_chan(ndev, data);
+               break;
+       case SBE_IOC_CHAN_NEW:
+               ret = do_create_chan(ndev, data);
+               break;
+       case SBE_IOC_CHAN_GET_STAT:
+               ret = do_get_chan_stats(ndev, data);
+               break;
+       case SBE_IOC_LOGLEVEL:
+               ret = do_set_loglevel(ndev, data);
+               break;
+       case SBE_IOC_RESET_DEV:
+               ret = do_reset(ndev, data);
+               break;
+       case SBE_IOC_CHAN_DEL_STAT:
+               ret = do_reset_chan_stats(ndev, data);
+               break;
+       case C4_LOOP_PORT:
+               ret = do_port_loop(ndev, data);
+               break;
+       case C4_RW_FRMR:
+               ret = do_framer_rw(ndev, data);
+               break;
+       case C4_RW_MSYC:
+               ret = do_musycc_rw(ndev, data);
+               break;
+       case C4_RW_PLD:
+               ret = do_pld_rw(ndev, data);
+               break;
+       case SBE_IOC_IID_GET:
+               ret = (iolen == sizeof(struct sbe_iid_info)) ?
+                      c4_get_iidinfo(ci, &arg.u.iip) : -EFAULT;
+               if (ret == 0)               /* no error, copy data */
+                       if (copy_to_user(data, &arg, iolen))
+                               return -EFAULT;
+               break;
+       default:
+               //pr_info(">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
+               ret = -EINVAL;
+               break;
+       }
+       return mkret(ret);
 }
 
 static const struct net_device_ops c4_ops = {
-       .ndo_open       = void_open,
-       .ndo_start_xmit = c4_linux_xmit,
-       .ndo_do_ioctl   = c4_ioctl,
+       .ndo_open       = void_open,
+       .ndo_start_xmit = c4_linux_xmit,
+       .ndo_do_ioctl   = c4_ioctl,
 };
 
 static void c4_setup(struct net_device *dev)
 {
-       dev->type = ARPHRD_VOID;
-       dev->netdev_ops = &c4_ops;
+       dev->type = ARPHRD_VOID;
+       dev->netdev_ops = &c4_ops;
 }
 
 struct net_device *__init
-c4_add_dev (hdw_info_t *hi, int brdno, unsigned long f0, unsigned long f1,
-            int irq0, int irq1)
+c4_add_dev(hdw_info_t *hi, int brdno, unsigned long f0, unsigned long f1,
+          int irq0, int irq1)
 {
-    struct net_device *ndev;
-    ci_t       *ci;
-
-    ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
-    if (!ndev)
-    {
-        pr_warning("%s: no memory for struct net_device !\n", hi->devname);
-        error_flag = ENOMEM;
-       return NULL;
-    }
-    ci = (ci_t *)(netdev_priv(ndev));
-    ndev->irq = irq0;
-
-    ci->hdw_info = hi;
-    ci->state = C_INIT;         /* mark as hardware not available */
-    ci->next = c4_list;
-    c4_list = ci;
-    ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
-
-    if (!CI)
-        CI = ci;                    /* DEBUG, only board 0 usage */
-
-    strcpy (ci->devname, hi->devname);
-    ci->release = &pmcc4_OSSI_release[0];
-
-    /* tasklet */
+       struct net_device *ndev;
+       ci_t       *ci;
+
+       ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
+       if (!ndev)
+       {
+               pr_warning("%s: no memory for struct net_device !\n",
+                          hi->devname);
+               error_flag = ENOMEM;
+               return NULL;
+       }
+       ci = (ci_t *)(netdev_priv(ndev));
+       ndev->irq = irq0;
+
+       ci->hdw_info = hi;
+       ci->state = C_INIT;         /* mark as hardware not available */
+       ci->next = c4_list;
+       c4_list = ci;
+       ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
+
+       if (!CI)
+               CI = ci;                    /* DEBUG, only board 0 usage */
+
+       strcpy(ci->devname, hi->devname);
+       ci->release = &pmcc4_OSSI_release[0];
+
+       /* tasklet */
 #if defined(SBE_ISR_TASKLET)
-    tasklet_init (&ci->ci_musycc_isr_tasklet,
-                  (void (*) (unsigned long)) musycc_intr_bh_tasklet,
-                  (unsigned long) ci);
+       tasklet_init(&ci->ci_musycc_isr_tasklet,
+                    (void (*) (unsigned long)) musycc_intr_bh_tasklet,
+                    (unsigned long) ci);
 
-    if (atomic_read (&ci->ci_musycc_isr_tasklet.count) == 0)
-        tasklet_disable_nosync (&ci->ci_musycc_isr_tasklet);
+       if (atomic_read(&ci->ci_musycc_isr_tasklet.count) == 0)
+               tasklet_disable_nosync(&ci->ci_musycc_isr_tasklet);
 #elif defined(SBE_ISR_IMMEDIATE)
-    ci->ci_musycc_isr_tq.routine = (void *) (unsigned long) musycc_intr_bh_tasklet;
-    ci->ci_musycc_isr_tq.data = ci;
+       ci->ci_musycc_isr_tq.routine = (void *)(unsigned long)musycc_intr_bh_tasklet;
+       ci->ci_musycc_isr_tq.data = ci;
 #endif
 
 
-    if (register_netdev (ndev) ||
-        (c4_init (ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
-    {
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-        error_flag = ENODEV;
-       return NULL;
-    }
-    /*************************************************************
-     *  int request_irq(unsigned int irq,
-     *                  void (*handler)(int, void *, struct pt_regs *),
-     *                  unsigned long flags, const char *dev_name, void *dev_id);
-     *  wherein:
-     *  irq      -> The interrupt number that is being requested.
-     *  handler  -> Pointer to handling function being installed.
-     *  flags    -> A bit mask of options related to interrupt management.
-     *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
-     *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
-     *              private data area (to identify which device is interrupting).
-     *
-     *  extern void free_irq(unsigned int irq, void *dev_id);
-     **************************************************************/
-
-    if (request_irq (irq0, &c4_linux_interrupt,
-                     IRQF_SHARED,
-                     ndev->name, ndev))
-    {
-        pr_warning("%s: MUSYCC could not get irq: %d\n", ndev->name, irq0);
-        unregister_netdev (ndev);
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-        error_flag = EIO;
-       return NULL;
-    }
+       if (register_netdev(ndev) ||
+               (c4_init(ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
+       {
+               OS_kfree(netdev_priv(ndev));
+               OS_kfree(ndev);
+               error_flag = ENODEV;
+               return NULL;
+       }
+       /*************************************************************
+        *  int request_irq(unsigned int irq,
+        *                  void (*handler)(int, void *, struct pt_regs *),
+        *                  unsigned long flags, const char *dev_name, void *dev_id);
+        *  wherein:
+        *  irq      -> The interrupt number that is being requested.
+        *  handler  -> Pointer to handling function being installed.
+        *  flags    -> A bit mask of options related to interrupt management.
+        *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
+        *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
+        *              private data area (to identify which device is interrupting).
+        *
+        *  extern void free_irq(unsigned int irq, void *dev_id);
+        **************************************************************/
+
+       if (request_irq(irq0, &c4_linux_interrupt,
+                       IRQF_SHARED,
+                       ndev->name, ndev))
+       {
+               pr_warning("%s: MUSYCC could not get irq: %d\n",
+                          ndev->name, irq0);
+               unregister_netdev(ndev);
+               OS_kfree(netdev_priv(ndev));
+               OS_kfree(ndev);
+               error_flag = EIO;
+               return NULL;
+       }
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-    if (request_irq (irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
-    {
-        pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
-        unregister_netdev (ndev);
-        free_irq (irq0, ndev);
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-        error_flag = EIO;
-       return NULL;
-    }
+       if (request_irq(irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
+       {
+               pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
+               unregister_netdev(ndev);
+               free_irq(irq0, ndev);
+               OS_kfree(netdev_priv(ndev));
+               OS_kfree(ndev);
+               error_flag = EIO;
+               return NULL;
+       }
 #endif
 
-    /* setup board identification information */
-
-    {
-        u_int32_t   tmp;
-
-        hdw_sn_get (hi, brdno);     /* also sets PROM format type (promfmt)
-                                     * for later usage */
-
-        switch (hi->promfmt)
-        {
-        case PROM_FORMAT_TYPE1:
-            memcpy (ndev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-            memcpy (&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);     /* unaligned data
-                                                                         * acquisition */
-            ci->brd_id = cpu_to_be32 (tmp);
-            break;
-        case PROM_FORMAT_TYPE2:
-            memcpy (ndev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-            memcpy (&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);     /* unaligned data
-                                                                         * acquisition */
-            ci->brd_id = cpu_to_be32 (tmp);
-            break;
-        default:
-            ci->brd_id = 0;
-            memset (ndev->dev_addr, 0, 6);
-            break;
-        }
+       /* setup board identification information */
+
+       {
+               u_int32_t   tmp;
+
+               /* also sets PROM format type (promfmt) for later usage */
+               hdw_sn_get(hi, brdno);
+
+               switch (hi->promfmt)
+               {
+               case PROM_FORMAT_TYPE1:
+                       memcpy(ndev->dev_addr,
+                              (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+                       /* unaligned data acquisition */
+                       memcpy(&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);
+                       ci->brd_id = cpu_to_be32(tmp);
+                       break;
+               case PROM_FORMAT_TYPE2:
+                       memcpy(ndev->dev_addr,
+                              (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+                       /* unaligned data acquisition */
+                       memcpy(&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);
+                       ci->brd_id = cpu_to_be32(tmp);
+                       break;
+               default:
+                       ci->brd_id = 0;
+                       memset(ndev->dev_addr, 0, 6);
+                       break;
+               }
 
 #if 1
-        sbeid_set_hdwbid (ci);      /* requires bid to be preset */
+               /* requires bid to be preset */
+               sbeid_set_hdwbid(ci);
 #else
-        sbeid_set_bdtype (ci);      /* requires hdw_bid to be preset */
+               /* requires hdw_bid to be preset */
+               sbeid_set_bdtype(ci);
 #endif
-
-    }
+       }
 
 #ifdef CONFIG_PROC_FS
-    sbecom_proc_brd_init (ci);
+       sbecom_proc_brd_init(ci);
 #endif
 #if defined(SBE_ISR_TASKLET)
-    tasklet_enable (&ci->ci_musycc_isr_tasklet);
+       tasklet_enable(&ci->ci_musycc_isr_tasklet);
 #endif
 
 
-    if ((error_flag = c4_init2 (ci)) != SBE_DRVR_SUCCESS)
-    {
+       if ((error_flag = c4_init2(ci)) != SBE_DRVR_SUCCESS)
+       {
 #ifdef CONFIG_PROC_FS
-        sbecom_proc_brd_cleanup (ci);
+               sbecom_proc_brd_cleanup(ci);
 #endif
-        unregister_netdev (ndev);
-        free_irq (irq1, ndev);
-        free_irq (irq0, ndev);
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-       return NULL;            /* failure, error_flag is set */
-    }
-    return ndev;
+               unregister_netdev(ndev);
+               free_irq(irq1, ndev);
+               free_irq(irq0, ndev);
+               OS_kfree(netdev_priv(ndev));
+               OS_kfree(ndev);
+               /* failure, error_flag is set */
+               return NULL;
+       }
+       return ndev;
 }
 
 static int  __init
-c4_mod_init (void)
+c4_mod_init(void)
 {
-    int         rtn;
-
-    pr_warning("%s\n", pmcc4_OSSI_release);
-    if ((rtn = c4hw_attach_all ()))
-        return -rtn;                /* installation failure - see system log */
-
-    /* housekeeping notifications */
-    if (cxt1e1_log_level != log_level_default)
-        pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
-                log_level_default, cxt1e1_log_level);
-       if (cxt1e1_max_mru != max_mru_default)
-               pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
-                               max_mru_default, cxt1e1_max_mru);
-       if (cxt1e1_max_mtu != max_mtu_default)
-               pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
-                               max_mtu_default, cxt1e1_max_mtu);
-    if (max_rxdesc_used != max_rxdesc_default)
-    {
-        if (max_rxdesc_used > 2000)
-            max_rxdesc_used = 2000; /* out-of-bounds reset */
-        pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
-                max_rxdesc_default, max_rxdesc_used);
-    }
-    if (max_txdesc_used != max_txdesc_default)
-    {
-        if (max_txdesc_used > 1000)
-            max_txdesc_used = 1000; /* out-of-bounds reset */
-        pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
-                max_txdesc_default, max_txdesc_used);
-    }
-    return 0;                       /* installation success */
+       int         rtn;
+
+       pr_warning("%s\n", pmcc4_OSSI_release);
+       if ((rtn = c4hw_attach_all()))
+               return -rtn; /* installation failure - see system log */
+
+       /* housekeeping notifications */
+       if (cxt1e1_log_level != log_level_default)
+               pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
+                       log_level_default, cxt1e1_log_level);
+       if (cxt1e1_max_mru != max_mru_default)
+               pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
+                       max_mru_default, cxt1e1_max_mru);
+       if (cxt1e1_max_mtu != max_mtu_default)
+               pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
+                       max_mtu_default, cxt1e1_max_mtu);
+       if (max_rxdesc_used != max_rxdesc_default)
+       {
+               if (max_rxdesc_used > 2000)
+                       max_rxdesc_used = 2000; /* out-of-bounds reset */
+               pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
+                       max_rxdesc_default, max_rxdesc_used);
+       }
+       if (max_txdesc_used != max_txdesc_default)
+       {
+               if (max_txdesc_used > 1000)
+                       max_txdesc_used = 1000; /* out-of-bounds reset */
+               pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
+                       max_txdesc_default, max_txdesc_used);
+       }
+       return 0;                       /* installation success */
 }
 
 
@@ -1138,31 +1160,31 @@ c4_mod_init (void)
   */
 
 static void __exit
-cleanup_hdlc (void)
+cleanup_hdlc(void)
 {
-    hdw_info_t *hi;
-    ci_t       *ci;
-    struct net_device *ndev;
-    int         i, j, k;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->ndev)               /* a board has been attached */
-        {
-            ci = (ci_t *)(netdev_priv(hi->ndev));
-            for (j = 0; j < ci->max_port; j++)
-                for (k = 0; k < MUSYCC_NCHANS; k++)
-                    if ((ndev = ci->port[j].chan[k]->user))
-                    {
-                        do_deluser (ndev, 0);
-                    }
-        }
-    }
+       hdw_info_t *hi;
+       ci_t       *ci;
+       struct net_device *ndev;
+       int         i, j, k;
+
+       for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+       {
+               if (hi->ndev)               /* a board has been attached */
+               {
+                       ci = (ci_t *)(netdev_priv(hi->ndev));
+                       for (j = 0; j < ci->max_port; j++)
+                               for (k = 0; k < MUSYCC_NCHANS; k++)
+                                       if ((ndev = ci->port[j].chan[k]->user))
+                                       {
+                                               do_deluser(ndev, 0);
+                                       }
+               }
+       }
 }
 
 
 static void __exit
-c4_mod_remove (void)
+c4_mod_remove(void)
 {
        cleanup_hdlc();            /* delete any missed channels */
        cleanup_devs();
@@ -1171,13 +1193,13 @@ c4_mod_remove (void)
        pr_info("SBE - driver removed.\n");
 }
 
-module_init (c4_mod_init);
-module_exit (c4_mod_remove);
+module_init(c4_mod_init);
+module_exit(c4_mod_remove);
 
-MODULE_AUTHOR ("SBE Technical Services <support@sbei.com>");
-MODULE_DESCRIPTION ("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
+MODULE_AUTHOR("SBE Technical Services <support@sbei.com>");
+MODULE_DESCRIPTION("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
 #ifdef MODULE_LICENSE
-MODULE_LICENSE ("GPL");
+MODULE_LICENSE("GPL");
 #endif
 
 /***  End-of-File  ***/
index 3abe8d2bb748b3794c2c15430fb7a81b9b8464ab..0063d044ca7155713c2c65e04ceb54a4cb463f97 100644 (file)
@@ -1,7 +1 @@
 obj-$(CONFIG_DGAP) += dgap.o
-
-
-dgap-objs :=   dgap_driver.o   dgap_fep5.o \
-               dgap_parse.o    dgap_trace.o \
-               dgap_tty.o      dgap_sysfs.o
-
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
new file mode 100644 (file)
index 0000000..cbce457
--- /dev/null
@@ -0,0 +1,7857 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
+ *
+ *
+ *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *     This is shared code between Digi's CVS archive and the
+ *     Linux Kernel sources.
+ *     Changing the source just for reformatting needlessly breaks
+ *     our CVS diff history.
+ *
+ *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *     Thank you.
+ *
+ */
+
+/*
+ *      In the original out of kernel Digi dgap driver, firmware
+ *      loading was done via user land to driver handshaking.
+ *
+ *      For cards that support a concentrator (port expander),
+ *      I believe the concentrator its self told the card which
+ *      concentrator is actually attached and then that info
+ *      was used to tell user land which concentrator firmware
+ *      image was to be downloaded. I think even the BIOS or
+ *      FEP images required could change with the connection
+ *      of a particular concentrator.
+ *
+ *      Since I have no access to any of these cards or
+ *      concentrators, I cannot put the correct concentrator
+ *      firmware file names into the firmware_info structure
+ *      as is now done for the BIOS and FEP images.
+ *
+ *      I think, but am not certain, that the cards supporting
+ *      concentrators will function without them. So support
+ *      of these cards has been left in this driver.
+ *
+ *      In order to fully support those cards, they would
+ *      either have to be acquired for dissection or maybe
+ *      Digi International could provide some assistance.
+ */
+#undef DIGI_CONCENTRATORS_SUPPORTED
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>       /* For udelay */
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+
+#include <linux/interrupt.h>   /* For tasklet and interrupt structs/defines */
+#include <linux/ctype.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/io.h>          /* For read[bwl]/write[bwl] */
+
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+#include <linux/firmware.h>
+
+#include "dgap.h"
+
+#define init_MUTEX(sem)         sema_init(sem, 1)
+#define DECLARE_MUTEX(name)     \
+       struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Digi International, http://www.digi.com");
+MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line");
+MODULE_SUPPORTED_DEVICE("dgap");
+
+/*
+ * insmod command line overrideable parameters
+ *
+ * NOTE: we use a set of macros to create the variables, which allows
+ * us to specify the variable type, name, initial value, and description.
+ */
+PARM_INT(rawreadok,    1,              0644,   "Bypass flip buffers on input");
+
+
+/**************************************************************************
+ *
+ * protos for this file
+ *
+ */
+
+static int dgap_start(void);
+static void dgap_init_globals(void);
+static int dgap_found_board(struct pci_dev *pdev, int id);
+static void dgap_cleanup_board(struct board_t *brd);
+static void dgap_poll_handler(ulong dummy);
+static int dgap_init_pci(void);
+static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void dgap_remove_one(struct pci_dev *dev);
+static int dgap_probe1(struct pci_dev *pdev, int card_type);
+static int dgap_do_remap(struct board_t *brd);
+static irqreturn_t dgap_intr(int irq, void *voidbrd);
+
+/* Our function prototypes */
+static int dgap_tty_open(struct tty_struct *tty, struct file *file);
+static void dgap_tty_close(struct tty_struct *tty, struct file *file);
+static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch);
+static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
+static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
+static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
+static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_write_room(struct tty_struct *tty);
+static int dgap_tty_chars_in_buffer(struct tty_struct *tty);
+static void dgap_tty_start(struct tty_struct *tty);
+static void dgap_tty_stop(struct tty_struct *tty);
+static void dgap_tty_throttle(struct tty_struct *tty);
+static void dgap_tty_unthrottle(struct tty_struct *tty);
+static void dgap_tty_flush_chars(struct tty_struct *tty);
+static void dgap_tty_flush_buffer(struct tty_struct *tty);
+static void dgap_tty_hangup(struct tty_struct *tty);
+static int dgap_wait_for_drain(struct tty_struct *tty);
+static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
+static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value);
+static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo);
+static int dgap_tty_tiocmget(struct tty_struct *tty);
+static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
+static int dgap_tty_send_break(struct tty_struct *tty, int msec);
+static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout);
+static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
+static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c);
+static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
+
+static int dgap_tty_register(struct board_t *brd);
+static int dgap_tty_preinit(void);
+static int dgap_tty_init(struct board_t *);
+static void dgap_tty_post_uninit(void);
+static void dgap_tty_uninit(struct board_t *);
+static void dgap_carrier(struct channel_t *ch);
+static void dgap_input(struct channel_t *ch);
+
+/*
+ * Our function prototypes from dgap_fep5
+ */
+static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds);
+static int dgap_event(struct board_t *bd);
+
+static void dgap_poll_tasklet(unsigned long data);
+static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds);
+static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
+static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
+static int dgap_param(struct tty_struct *tty);
+static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len);
+static uint dgap_get_custom_baud(struct channel_t *ch);
+static void dgap_firmware_reset_port(struct channel_t *ch);
+
+/*
+ * Function prototypes from dgap_parse.c.
+ */
+static int dgap_gettok(char **in, struct cnode *p);
+static char *dgap_getword(char **in);
+static char *dgap_savestring(char *s);
+static struct cnode *dgap_newnode(int t);
+static int dgap_checknode(struct cnode *p);
+static void dgap_err(char *s);
+
+/*
+ * Function prototypes from dgap_sysfs.h
+ */
+struct board_t;
+struct channel_t;
+struct un_t;
+struct pci_driver;
+struct class_device;
+
+static void dgap_create_ports_sysfiles(struct board_t *bd);
+static void dgap_remove_ports_sysfiles(struct board_t *bd);
+
+static void dgap_create_driver_sysfiles(struct pci_driver *);
+static void dgap_remove_driver_sysfiles(struct pci_driver *);
+
+static void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
+static void dgap_remove_tty_sysfs(struct device *c);
+
+/*
+ * Function prototypes from dgap_parse.h
+ */
+static int dgap_parsefile(char **in, int Remove);
+static struct cnode *dgap_find_config(int type, int bus, int slot);
+static uint dgap_config_get_number_of_ports(struct board_t *bd);
+static char *dgap_create_config_string(struct board_t *bd, char *string);
+static uint dgap_config_get_useintr(struct board_t *bd);
+static uint dgap_config_get_altpin(struct board_t *bd);
+
+static int dgap_ms_sleep(ulong ms);
+static void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len);
+static void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
+#endif
+static int dgap_after_config_loaded(int board);
+static int dgap_finalize_board_init(struct board_t *brd);
+
+static void dgap_get_vpd(struct board_t *brd);
+static void dgap_do_reset_board(struct board_t *brd);
+static void dgap_do_wait_for_bios(struct board_t *brd);
+static void dgap_do_wait_for_fep(struct board_t *brd);
+static int dgap_tty_register_ports(struct board_t *brd);
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type);
+
+/* Driver load/unload functions */
+int                    dgap_init_module(void);
+void                   dgap_cleanup_module(void);
+
+module_init(dgap_init_module);
+module_exit(dgap_cleanup_module);
+
+/*
+ * File operations permitted on Control/Management major.
+ */
+static const struct file_operations DgapBoardFops = {
+       .owner  = THIS_MODULE,
+};
+
+/*
+ * Globals
+ */
+static uint dgap_NumBoards;
+static struct board_t *dgap_Board[MAXBOARDS];
+DEFINE_SPINLOCK(dgap_global_lock);
+static ulong dgap_poll_counter;
+static char *dgap_config_buf;
+static int dgap_driver_state = DRIVER_INITIALIZED;
+DEFINE_SPINLOCK(dgap_dl_lock);
+static wait_queue_head_t dgap_dl_wait;
+static int dgap_dl_action;
+static int dgap_poll_tick = 20;        /* Poll interval - 20 ms */
+
+/*
+ * Static vars.
+ */
+static int dgap_Major_Control_Registered = FALSE;
+static uint dgap_driver_start = FALSE;
+
+static struct class *dgap_class;
+
+static struct board_t *dgap_BoardsByMajor[256];
+static uchar *dgap_TmpWriteBuf = NULL;
+DECLARE_MUTEX(dgap_TmpWriteSem);
+static uint dgap_count = 500;
+
+/*
+ * Poller stuff
+ */
+DEFINE_SPINLOCK(dgap_poll_lock);       /* Poll scheduling lock */
+static ulong dgap_poll_time;           /* Time of next poll */
+static uint dgap_poll_stop;            /* Used to tell poller to stop */
+static struct timer_list dgap_poll_timer;
+
+/*
+     SUPPORTED PRODUCTS
+
+     Card Model               Number of Ports      Interface
+     ----------------------------------------------------------------
+     Acceleport Xem           4 - 64              (EIA232 & EIA422)
+     Acceleport Xr            4 & 8               (EIA232)
+     Acceleport Xr 920        4 & 8               (EIA232)
+     Acceleport C/X           8 - 128             (EIA232)
+     Acceleport EPC/X         8 - 224             (EIA232)
+     Acceleport Xr/422        4 & 8               (EIA422)
+     Acceleport 2r/920        2                   (EIA232)
+     Acceleport 4r/920        4                   (EIA232)
+     Acceleport 8r/920        8                   (EIA232)
+
+     IBM 8-Port Asynchronous PCI Adapter          (EIA232)
+     IBM 128-Port Asynchronous PCI Adapter        (EIA232 & EIA422)
+*/
+
+static struct pci_device_id dgap_pci_tbl[] = {
+       {       DIGI_VID, PCI_DEVICE_XEM_DID,   PCI_ANY_ID, PCI_ANY_ID, 0, 0,   0 },
+       {       DIGI_VID, PCI_DEVICE_CX_DID,    PCI_ANY_ID, PCI_ANY_ID, 0, 0,   1 },
+       {       DIGI_VID, PCI_DEVICE_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  2 },
+       {       DIGI_VID, PCI_DEVICE_EPCJ_DID,  PCI_ANY_ID, PCI_ANY_ID, 0, 0,   3 },
+       {       DIGI_VID, PCI_DEVICE_920_2_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,   4 },
+       {       DIGI_VID, PCI_DEVICE_920_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,   5 },
+       {       DIGI_VID, PCI_DEVICE_920_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,   6 },
+       {       DIGI_VID, PCI_DEVICE_XR_DID,    PCI_ANY_ID, PCI_ANY_ID, 0, 0,   7 },
+       {       DIGI_VID, PCI_DEVICE_XRJ_DID,   PCI_ANY_ID, PCI_ANY_ID, 0, 0,   8 },
+       {       DIGI_VID, PCI_DEVICE_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  9 },
+       {       DIGI_VID, PCI_DEVICE_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  10 },
+       {       DIGI_VID, PCI_DEVICE_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
+       {       DIGI_VID, PCI_DEVICE_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+       {       DIGI_VID, PCI_DEVICE_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
+       {       DIGI_VID, PCI_DEVICE_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  14 },
+       {0,}                                    /* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
+
+/*
+ * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
+ */
+struct board_id {
+       uint config_type;
+       uchar *name;
+       uint maxports;
+       uint dpatype;
+};
+
+static struct board_id dgap_Ids[] = {
+       {       PPCM,           PCI_DEVICE_XEM_NAME,    64,     (T_PCXM | T_PCLITE | T_PCIBUS)  },
+       {       PCX,            PCI_DEVICE_CX_NAME,     128,    (T_CX | T_PCIBUS)               },
+       {       PCX,            PCI_DEVICE_CX_IBM_NAME, 128,    (T_CX | T_PCIBUS)               },
+       {       PEPC,           PCI_DEVICE_EPCJ_NAME,   224,    (T_EPC  | T_PCIBUS)             },
+       {       APORT2_920P,    PCI_DEVICE_920_2_NAME,  2,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       APORT4_920P,    PCI_DEVICE_920_4_NAME,  4,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       APORT8_920P,    PCI_DEVICE_920_8_NAME,  8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PAPORT8,        PCI_DEVICE_XR_NAME,     8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PAPORT8,        PCI_DEVICE_XRJ_NAME,    8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PAPORT8,        PCI_DEVICE_XR_422_NAME, 8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PAPORT8,        PCI_DEVICE_XR_IBM_NAME, 8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PAPORT8,        PCI_DEVICE_XR_SAIP_NAME, 8,     (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PAPORT8,        PCI_DEVICE_XR_BULL_NAME, 8,     (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       APORT8_920P,    PCI_DEVICE_920_8_HP_NAME, 8,    (T_PCXR | T_PCLITE | T_PCIBUS)  },
+       {       PPCM,           PCI_DEVICE_XEM_HP_NAME, 64,     (T_PCXM | T_PCLITE | T_PCIBUS)  },
+       {0,}                                            /* 0 terminated list. */
+};
+
+static struct pci_driver dgap_driver = {
+       .name           = "dgap",
+       .probe          = dgap_init_one,
+       .id_table       = dgap_pci_tbl,
+       .remove         = dgap_remove_one,
+};
+
+struct firmware_info {
+       uchar *conf_name;       /* dgap.conf */
+       uchar *bios_name;       /* BIOS filename */
+       uchar *fep_name;        /* FEP  filename */
+       uchar *con_name;        /* Concentrator filename  FIXME*/
+       int num;                /* sequence number */
+};
+
+/*
+ * Firmware - BIOS, FEP, and CONC filenames
+ */
+static struct firmware_info fw_info[] = {
+       { "dgap/dgap.conf", "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 0 },
+       { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 1 },
+       { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 2 },
+       { "dgap/dgap.conf", "dgap/pcibios.bin", "dgap/pcifep.bin", 0, 3 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 4 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 5 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 6 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 7 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 8 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 9 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 10 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 11 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 12 },
+       { "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 13 },
+       { "dgap/dgap.conf", "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 14 },
+       {0,}
+};
+
+static char *dgap_driver_state_text[] = {
+       "Driver Initialized",
+       "Driver needs configuration load.",
+       "Driver requested configuration from download daemon.",
+       "Driver Ready."
+};
+
+/*
+ * Default transparent print information.
+ */
+static struct digi_t dgap_digi_init = {
+       .digi_flags =   DIGI_COOK,      /* Flags                        */
+       .digi_maxcps =  100,            /* Max CPS                      */
+       .digi_maxchar = 50,             /* Max chars in print queue     */
+       .digi_bufsize = 100,            /* Printer buffer size          */
+       .digi_onlen =   4,              /* size of printer on string    */
+       .digi_offlen =  4,              /* size of printer off string   */
+       .digi_onstr =   "\033[5i",      /* ANSI printer on string ]     */
+       .digi_offstr =  "\033[4i",      /* ANSI printer off string ]    */
+       .digi_term =    "ansi"          /* default terminal type        */
+};
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.
+ *
+ * This defines a raw port at 9600 baud, 8 data bits, no parity,
+ * 1 stop bit.
+ */
+
+static struct ktermios DgapDefaultTermios = {
+       .c_iflag =      (DEFAULT_IFLAGS),       /* iflags */
+       .c_oflag =      (DEFAULT_OFLAGS),       /* oflags */
+       .c_cflag =      (DEFAULT_CFLAGS),       /* cflags */
+       .c_lflag =      (DEFAULT_LFLAGS),       /* lflags */
+       .c_cc =         INIT_C_CC,
+       .c_line =       0,
+};
+
+static const struct tty_operations dgap_tty_ops = {
+       .open = dgap_tty_open,
+       .close = dgap_tty_close,
+       .write = dgap_tty_write,
+       .write_room = dgap_tty_write_room,
+       .flush_buffer = dgap_tty_flush_buffer,
+       .chars_in_buffer = dgap_tty_chars_in_buffer,
+       .flush_chars = dgap_tty_flush_chars,
+       .ioctl = dgap_tty_ioctl,
+       .set_termios = dgap_tty_set_termios,
+       .stop = dgap_tty_stop,
+       .start = dgap_tty_start,
+       .throttle = dgap_tty_throttle,
+       .unthrottle = dgap_tty_unthrottle,
+       .hangup = dgap_tty_hangup,
+       .put_char = dgap_tty_put_char,
+       .tiocmget = dgap_tty_tiocmget,
+       .tiocmset = dgap_tty_tiocmset,
+       .break_ctl = dgap_tty_send_break,
+       .wait_until_sent = dgap_tty_wait_until_sent,
+       .send_xchar = dgap_tty_send_xchar
+};
+
+/*
+ * Our needed internal static variables from dgap_parse.c
+ */
+static struct cnode dgap_head;
+#define MAXCWORD 200
+static char dgap_cword[MAXCWORD];
+
+struct toklist {
+       int     token;
+       char    *string;
+};
+
+static struct toklist dgap_tlist[] = {
+       {       BEGIN,          "config_begin"                  },
+       {       END,            "config_end"                    },
+       {       BOARD,          "board"                         },
+       {       PCX,            "Digi_AccelePort_C/X_PCI"       },      /* C/X_PCI */
+       {       PEPC,           "Digi_AccelePort_EPC/X_PCI"     },      /* EPC/X_PCI */
+       {       PPCM,           "Digi_AccelePort_Xem_PCI"       },      /* PCI/Xem */
+       {       APORT2_920P,    "Digi_AccelePort_2r_920_PCI"    },
+       {       APORT4_920P,    "Digi_AccelePort_4r_920_PCI"    },
+       {       APORT8_920P,    "Digi_AccelePort_8r_920_PCI"    },
+       {       PAPORT4,        "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
+       {       PAPORT8,        "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
+       {       IO,             "io"                            },
+       {       PCIINFO,        "pciinfo"                       },
+       {       LINE,           "line"                          },
+       {       CONC,           "conc"                          },
+       {       CONC,           "concentrator"                  },
+       {       CX,             "cx"                            },
+       {       CX,             "ccon"                          },
+       {       EPC,            "epccon"                        },
+       {       EPC,            "epc"                           },
+       {       MOD,            "module"                        },
+       {       ID,             "id"                            },
+       {       STARTO,         "start"                         },
+       {       SPEED,          "speed"                         },
+       {       CABLE,          "cable"                         },
+       {       CONNECT,        "connect"                       },
+       {       METHOD,         "method"                        },
+       {       STATUS,         "status"                        },
+       {       CUSTOM,         "Custom"                        },
+       {       BASIC,          "Basic"                         },
+       {       MEM,            "mem"                           },
+       {       MEM,            "memory"                        },
+       {       PORTS,          "ports"                         },
+       {       MODEM,          "modem"                         },
+       {       NPORTS,         "nports"                        },
+       {       TTYN,           "ttyname"                       },
+       {       CU,             "cuname"                        },
+       {       PRINT,          "prname"                        },
+       {       CMAJOR,         "major"                         },
+       {       ALTPIN,         "altpin"                        },
+       {       USEINTR,        "useintr"                       },
+       {       TTSIZ,          "ttysize"                       },
+       {       CHSIZ,          "chsize"                        },
+       {       BSSIZ,          "boardsize"                     },
+       {       UNTSIZ,         "schedsize"                     },
+       {       F2SIZ,          "f2200size"                     },
+       {       VPSIZ,          "vpixsize"                      },
+       {       0,              NULL                            }
+};
+
+/************************************************************************
+ *
+ * Driver load/unload functions
+ *
+ ************************************************************************/
+
+/*
+ * init_module()
+ *
+ * Module load.  This is where it all starts.
+ */
+int dgap_init_module(void)
+{
+       int rc = 0;
+
+       pr_info("%s, Digi International Part Number %s\n", DG_NAME, DG_PART);
+
+       dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+
+       /*
+        * Initialize global stuff
+        */
+       rc = dgap_start();
+
+       if (rc < 0)
+               return rc;
+
+       /*
+        * Find and configure all the cards
+        */
+       rc = dgap_init_pci();
+
+       /*
+        * If something went wrong in the scan, bail out of driver.
+        */
+       if (rc < 0) {
+               /* Only unregister the pci driver if it was actually registered. */
+               if (dgap_NumBoards)
+                       pci_unregister_driver(&dgap_driver);
+               else
+                       printk("WARNING: dgap driver load failed.  No DGAP boards found.\n");
+
+               dgap_cleanup_module();
+       } else {
+               dgap_create_driver_sysfiles(&dgap_driver);
+               dgap_driver_state = DRIVER_READY;
+       }
+
+       return rc;
+}
+
+/*
+ * Start of driver.
+ */
+static int dgap_start(void)
+{
+       int rc = 0;
+       unsigned long flags;
+
+       if (dgap_driver_start == FALSE) {
+
+               dgap_driver_start = TRUE;
+
+               /*
+                * make sure that the globals are
+                * init'd before we do anything else
+                */
+               dgap_init_globals();
+
+               dgap_NumBoards = 0;
+
+               pr_info("For the tools package please visit http://www.digi.com\n");
+
+               /*
+                * Register our base character device into the kernel.
+                * This allows the download daemon to connect to the downld device
+                * before any of the boards are init'ed.
+                */
+               if (!dgap_Major_Control_Registered) {
+                       /*
+                        * Register management/dpa devices
+                        */
+                       rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops);
+                       if (rc < 0)
+                               return rc;
+
+                       dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
+                       device_create(dgap_class, NULL,
+                               MKDEV(DIGI_DGAP_MAJOR, 0),
+                               NULL, "dgap_mgmt");
+                       dgap_Major_Control_Registered = TRUE;
+               }
+
+               /*
+                * Init any global tty stuff.
+                */
+               rc = dgap_tty_preinit();
+
+               if (rc < 0)
+                       return rc;
+
+               /* Start the poller */
+               DGAP_LOCK(dgap_poll_lock, flags);
+               init_timer(&dgap_poll_timer);
+               dgap_poll_timer.function = dgap_poll_handler;
+               dgap_poll_timer.data = 0;
+               dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
+               dgap_poll_timer.expires = dgap_poll_time;
+               DGAP_UNLOCK(dgap_poll_lock, flags);
+
+               add_timer(&dgap_poll_timer);
+
+               dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+       }
+
+       return rc;
+}
+
+/*
+ * Register pci driver, and return how many boards we have.
+ */
+static int dgap_init_pci(void)
+{
+       return pci_register_driver(&dgap_driver);
+}
+
+/* returns count (>= 0), or negative on error */
+static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int rc;
+
+       /* wake up and enable device */
+       rc = pci_enable_device(pdev);
+
+       if (rc < 0) {
+               rc = -EIO;
+       } else {
+               rc = dgap_probe1(pdev, ent->driver_data);
+               if (rc == 0) {
+                       dgap_NumBoards++;
+                       rc = dgap_firmware_load(pdev, ent->driver_data);
+               }
+       }
+       return rc;
+}
+
+static int dgap_probe1(struct pci_dev *pdev, int card_type)
+{
+       return dgap_found_board(pdev, card_type);
+}
+
+static void dgap_remove_one(struct pci_dev *dev)
+{
+       /* Do Nothing */
+}
+
+/*
+ * dgap_cleanup_module()
+ *
+ * Module unload.  This is where it all ends.
+ */
+void dgap_cleanup_module(void)
+{
+       int i;
+       ulong lock_flags;
+
+       DGAP_LOCK(dgap_poll_lock, lock_flags);
+       dgap_poll_stop = 1;
+       DGAP_UNLOCK(dgap_poll_lock, lock_flags);
+
+       /* Turn off poller right away. */
+       del_timer_sync(&dgap_poll_timer);
+
+       dgap_remove_driver_sysfiles(&dgap_driver);
+
+
+       if (dgap_Major_Control_Registered) {
+               device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
+               device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1));
+               class_destroy(dgap_class);
+               unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
+       }
+
+       kfree(dgap_config_buf);
+
+       for (i = 0; i < dgap_NumBoards; ++i) {
+               dgap_remove_ports_sysfiles(dgap_Board[i]);
+               dgap_tty_uninit(dgap_Board[i]);
+               dgap_cleanup_board(dgap_Board[i]);
+       }
+
+       dgap_tty_post_uninit();
+
+#if defined(DGAP_TRACER)
+       /* last thing, make sure we release the tracebuffer */
+       dgap_tracer_free();
+#endif
+       if (dgap_NumBoards)
+               pci_unregister_driver(&dgap_driver);
+}
+
+/*
+ * dgap_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void dgap_cleanup_board(struct board_t *brd)
+{
+       int i = 0;
+
+       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       if (brd->intr_used && brd->irq)
+               free_irq(brd->irq, brd);
+
+       tasklet_kill(&brd->helper_tasklet);
+
+       if (brd->re_map_port) {
+               release_mem_region(brd->membase + 0x200000, 0x200000);
+               iounmap(brd->re_map_port);
+               brd->re_map_port = NULL;
+       }
+
+       if (brd->re_map_membase) {
+               release_mem_region(brd->membase, 0x200000);
+               iounmap(brd->re_map_membase);
+               brd->re_map_membase = NULL;
+       }
+
+       if (brd->msgbuf_head) {
+               unsigned long flags;
+
+               DGAP_LOCK(dgap_global_lock, flags);
+               brd->msgbuf = NULL;
+               printk("%s", brd->msgbuf_head);
+               kfree(brd->msgbuf_head);
+               brd->msgbuf_head = NULL;
+               DGAP_UNLOCK(dgap_global_lock, flags);
+       }
+
+       /* Free all allocated channels structs */
+       for (i = 0; i < MAXPORTS ; i++) {
+               if (brd->channels[i]) {
+                       kfree(brd->channels[i]);
+                       brd->channels[i] = NULL;
+               }
+       }
+
+       kfree(brd->flipbuf);
+       kfree(brd->flipflagbuf);
+
+       dgap_Board[brd->boardnum] = NULL;
+
+       kfree(brd);
+}
+
+/*
+ * dgap_found_board()
+ *
+ * A board has been found, init it.
+ */
+static int dgap_found_board(struct pci_dev *pdev, int id)
+{
+       struct board_t *brd;
+       unsigned int pci_irq;
+       int i = 0;
+       unsigned long flags;
+
+       /* get the board structure and prep it */
+       brd = dgap_Board[dgap_NumBoards] =
+       (struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
+       if (!brd)
+               return -ENOMEM;
+
+       /* make a temporary message buffer for the boot messages */
+       brd->msgbuf = brd->msgbuf_head =
+               (char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
+       if (!brd->msgbuf) {
+               kfree(brd);
+               return -ENOMEM;
+       }
+
+       /* store the info for the board we've found */
+       brd->magic = DGAP_BOARD_MAGIC;
+       brd->boardnum = dgap_NumBoards;
+       brd->firstminor = 0;
+       brd->vendor = dgap_pci_tbl[id].vendor;
+       brd->device = dgap_pci_tbl[id].device;
+       brd->pdev = pdev;
+       brd->pci_bus = pdev->bus->number;
+       brd->pci_slot = PCI_SLOT(pdev->devfn);
+       brd->name = dgap_Ids[id].name;
+       brd->maxports = dgap_Ids[id].maxports;
+       brd->type = dgap_Ids[id].config_type;
+       brd->dpatype = dgap_Ids[id].dpatype;
+       brd->dpastatus = BD_NOFEP;
+       init_waitqueue_head(&brd->state_wait);
+
+       DGAP_SPINLOCK_INIT(brd->bd_lock);
+
+       brd->state              = BOARD_FOUND;
+       brd->runwait            = 0;
+       brd->inhibit_poller     = FALSE;
+       brd->wait_for_bios      = 0;
+       brd->wait_for_fep       = 0;
+
+       for (i = 0; i < MAXPORTS; i++)
+               brd->channels[i] = NULL;
+
+       /* store which card & revision we have */
+       pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
+       pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+
+       pci_irq = pdev->irq;
+       brd->irq = pci_irq;
+
+       /* get the PCI Base Address Registers */
+
+       /* Xr Jupiter and EPC use BAR 2 */
+       if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == PCI_DEVICE_EPCJ_DID) {
+               brd->membase     = pci_resource_start(pdev, 2);
+               brd->membase_end = pci_resource_end(pdev, 2);
+       }
+       /* Everyone else uses BAR 0 */
+       else {
+               brd->membase     = pci_resource_start(pdev, 0);
+               brd->membase_end = pci_resource_end(pdev, 0);
+       }
+
+       if (!brd->membase)
+               return -ENODEV;
+
+       if (brd->membase & 1)
+               brd->membase &= ~3;
+       else
+               brd->membase &= ~15;
+
+       /*
+        * On the PCI boards, there is no IO space allocated
+        * The I/O registers will be in the first 3 bytes of the
+        * upper 2MB of the 4MB memory space.  The board memory
+        * will be mapped into the low 2MB of the 4MB memory space
+        */
+       brd->port = brd->membase + PCI_IO_OFFSET;
+       brd->port_end = brd->port + PCI_IO_SIZE;
+
+       /*
+        * Special initialization for non-PLX boards
+        */
+       if (brd->device != PCI_DEVICE_XRJ_DID && brd->device != PCI_DEVICE_EPCJ_DID) {
+               unsigned short cmd;
+
+               pci_write_config_byte(pdev, 0x40, 0);
+               pci_write_config_byte(pdev, 0x46, 0);
+
+               /* Limit burst length to 2 doubleword transactions */
+               pci_write_config_byte(pdev, 0x42, 1);
+
+               /*
+                * Enable IO and mem if not already done.
+                * This was needed for support on Itanium.
+                */
+               pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+               cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+               pci_write_config_word(pdev, PCI_COMMAND, cmd);
+       }
+
+       /* init our poll helper tasklet */
+       tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd);
+
+       DGAP_LOCK(dgap_global_lock, flags);
+       brd->msgbuf = NULL;
+       printk("%s", brd->msgbuf_head);
+       kfree(brd->msgbuf_head);
+       brd->msgbuf_head = NULL;
+       DGAP_UNLOCK(dgap_global_lock, flags);
+
+       i = dgap_do_remap(brd);
+       if (i)
+               brd->state = BOARD_FAILED;
+       else
+               brd->state = NEED_RESET;
+
+       return 0;
+}
+
+
+static int dgap_finalize_board_init(struct board_t *brd)
+{
+       int rc;
+
+       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+               return -ENODEV;
+
+       brd->use_interrupts = dgap_config_get_useintr(brd);
+
+       /*
+        * Set up our interrupt handler if we are set to do interrupts.
+        */
+       if (brd->use_interrupts && brd->irq) {
+
+               rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
+
+               if (rc)
+                       brd->intr_used = 0;
+               else
+                       brd->intr_used = 1;
+       } else {
+               brd->intr_used = 0;
+       }
+
+       return 0;
+}
+
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
+{
+       struct board_t *brd = dgap_Board[dgap_NumBoards - 1];
+       const struct firmware *fw;
+       int ret;
+
+       dgap_get_vpd(brd);
+       dgap_do_reset_board(brd);
+
+       if ((fw_info[card_type].conf_name) &&
+           (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD)) {
+               ret = request_firmware(&fw, fw_info[card_type].conf_name,
+                                        &pdev->dev);
+               if (ret) {
+                       pr_err("dgap: config file %s not found\n",
+                               fw_info[card_type].conf_name);
+                       return ret;
+               }
+               if (!dgap_config_buf) {
+                       dgap_config_buf = kmalloc(fw->size + 1, GFP_ATOMIC);
+                       if (!dgap_config_buf) {
+                               release_firmware(fw);
+                               return -ENOMEM;
+                       }
+               }
+
+               memcpy(dgap_config_buf, fw->data, fw->size);
+               release_firmware(fw);
+               dgap_config_buf[fw->size + 1] = '\0';
+
+               if (dgap_parsefile(&dgap_config_buf, TRUE) != 0)
+                       return -EINVAL;
+
+               dgap_driver_state = -1;
+       }
+
+       ret = dgap_after_config_loaded(brd->boardnum);
+       if (ret)
+               return ret;
+       /*
+        * Match this board to a config the user created for us.
+        */
+       brd->bd_config =
+               dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot);
+
+       /*
+        * Because the 4 port Xr products share the same PCI ID
+        * as the 8 port Xr products, if we receive a NULL config
+        * back, and this is a PAPORT8 board, retry with a
+        * PAPORT4 attempt as well.
+        */
+       if (brd->type == PAPORT8 && !brd->bd_config)
+               brd->bd_config =
+                       dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot);
+
+       if (!brd->bd_config) {
+               pr_err("dgap: No valid configuration found\n");
+               return -EINVAL;
+       }
+
+       dgap_tty_register(brd);
+       dgap_finalize_board_init(brd);
+
+       if (fw_info[card_type].bios_name) {
+               ret = request_firmware(&fw, fw_info[card_type].bios_name,
+                                       &pdev->dev);
+               if (ret) {
+                       pr_err("dgap: bios file %s not found\n",
+                               fw_info[card_type].bios_name);
+                       return ret;
+               }
+               dgap_do_bios_load(brd, (char *)fw->data, fw->size);
+               release_firmware(fw);
+
+               /* Wait for BIOS to test board... */
+               dgap_do_wait_for_bios(brd);
+
+               if (brd->state != FINISHED_BIOS_LOAD)
+                       return -ENXIO;
+       }
+
+       if (fw_info[card_type].fep_name) {
+               ret = request_firmware(&fw, fw_info[card_type].fep_name,
+                                       &pdev->dev);
+               if (ret) {
+                       pr_err("dgap: fep file %s not found\n",
+                               fw_info[card_type].fep_name);
+                       return ret;
+               }
+               dgap_do_fep_load(brd, (char *)fw->data, fw->size);
+               release_firmware(fw);
+
+               /* Wait for FEP to load on board... */
+               dgap_do_wait_for_fep(brd);
+
+               if (brd->state != FINISHED_FEP_LOAD)
+                       return -ENXIO;
+       }
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+       /*
+        * If this is a CX or EPCX, we need to see if the firmware
+        * is requesting a concentrator image from us.
+        */
+       if ((bd->type == PCX) || (bd->type == PEPC)) {
+               chk_addr = (u16 *) (vaddr + DOWNREQ);
+               /* Nonzero if FEP is requesting concentrator image. */
+               check = readw(chk_addr);
+               vaddr = brd->re_map_membase;
+       }
+
+       if (fw_info[card_type].con_name && check && vaddr) {
+               ret = request_firmware(&fw, fw_info[card_type].con_name,
+                                       &pdev->dev);
+               if (ret) {
+                       pr_err("dgap: conc file %s not found\n",
+                               fw_info[card_type].con_name);
+                       return ret;
+               }
+               /* Put concentrator firmware loading code here */
+               offset = readw((u16 *) (vaddr + DOWNREQ));
+               memcpy_toio(offset, fw->data, fw->size);
+
+               dgap_do_conc_load(brd, (char *)fw->data, fw->size)
+               release_firmware(fw);
+       }
+#endif
+       /*
+        * Do tty device initialization.
+        */
+       ret = dgap_tty_init(brd);
+       if (ret < 0) {
+               dgap_tty_uninit(brd);
+               return ret;
+       }
+
+       ret = dgap_tty_register_ports(brd);
+       if (ret)
+               return ret;
+
+       brd->state = BOARD_READY;
+       brd->dpastatus = BD_RUNNING;
+
+       return 0;
+}
+
+/*
+ * Remap PCI memory.
+ */
+static int dgap_do_remap(struct board_t *brd)
+{
+       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+               return -ENXIO;
+
+       if (!request_mem_region(brd->membase, 0x200000, "dgap"))
+               return -ENOMEM;
+
+       if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) {
+               release_mem_region(brd->membase, 0x200000);
+               return -ENOMEM;
+       }
+
+       brd->re_map_membase = ioremap(brd->membase, 0x200000);
+       if (!brd->re_map_membase) {
+               release_mem_region(brd->membase, 0x200000);
+               release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+               return -ENOMEM;
+       }
+
+       brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
+       if (!brd->re_map_port) {
+               release_mem_region(brd->membase, 0x200000);
+               release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+               iounmap(brd->re_map_membase);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/*****************************************************************************
+*
+* Function:
+*
+*    dgap_poll_handler
+*
+* Author:
+*
+*    Scott H Kilau
+*
+* Parameters:
+*
+*    dummy -- ignored
+*
+* Return Values:
+*
+*    none
+*
+* Description:
+*
+*    As each timer expires, it determines (a) whether the "transmit"
+*    waiter needs to be woken up, and (b) whether the poller needs to
+*    be rescheduled.
+*
+******************************************************************************/
+
+static void dgap_poll_handler(ulong dummy)
+{
+       int i;
+       struct board_t *brd;
+       unsigned long lock_flags;
+       ulong new_time;
+
+       dgap_poll_counter++;
+
+       /*
+        * Do not start the board state machine until
+        * driver tells us its up and running, and has
+        * everything it needs.
+        */
+       if (dgap_driver_state != DRIVER_READY)
+               goto schedule_poller;
+
+       /*
+        * If we have just 1 board, or the system is not SMP,
+        * then use the typical old style poller.
+        * Otherwise, use our new tasklet based poller, which should
+        * speed things up for multiple boards.
+        */
+       if ((dgap_NumBoards == 1) || (num_online_cpus() <= 1)) {
+               for (i = 0; i < dgap_NumBoards; i++) {
+
+                       brd = dgap_Board[i];
+
+                       if (brd->state == BOARD_FAILED)
+                               continue;
+                       if (!brd->intr_running)
+                               /* Call the real board poller directly */
+                               dgap_poll_tasklet((unsigned long) brd);
+               }
+       } else {
+               /* Go thru each board, kicking off a tasklet for each if needed */
+               for (i = 0; i < dgap_NumBoards; i++) {
+                       brd = dgap_Board[i];
+
+                       /*
+                        * Attempt to grab the board lock.
+                        *
+                        * If we can't get it, no big deal, the next poll will get it.
+                        * Basically, I just really don't want to spin in here, because I want
+                        * to kick off my tasklets as fast as I can, and then get out the poller.
+                        */
+                       if (!spin_trylock(&brd->bd_lock))
+                               continue;
+
+                       /* If board is in a failed state, don't bother scheduling a tasklet */
+                       if (brd->state == BOARD_FAILED) {
+                               spin_unlock(&brd->bd_lock);
+                               continue;
+                       }
+
+                       /* Schedule a poll helper task */
+                       if (!brd->intr_running)
+                               tasklet_schedule(&brd->helper_tasklet);
+
+                       /*
+                        * Can't do DGAP_UNLOCK here, as we don't have
+                        * lock_flags because we did a trylock above.
+                        */
+                       spin_unlock(&brd->bd_lock);
+               }
+       }
+
+schedule_poller:
+
+       /*
+        * Schedule ourself back at the nominal wakeup interval.
+        */
+       DGAP_LOCK(dgap_poll_lock, lock_flags);
+       dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
+
+       new_time = dgap_poll_time - jiffies;
+
+       if ((ulong) new_time >= 2 * dgap_poll_tick)
+               dgap_poll_time = jiffies +  dgap_jiffies_from_ms(dgap_poll_tick);
+
+       dgap_poll_timer.function = dgap_poll_handler;
+       dgap_poll_timer.data = 0;
+       dgap_poll_timer.expires = dgap_poll_time;
+       DGAP_UNLOCK(dgap_poll_lock, lock_flags);
+
+       if (!dgap_poll_stop)
+               add_timer(&dgap_poll_timer);
+}
+
+/*
+ * dgap_intr()
+ *
+ * Driver interrupt handler.
+ */
+static irqreturn_t dgap_intr(int irq, void *voidbrd)
+{
+       struct board_t *brd = (struct board_t *) voidbrd;
+
+       if (!brd)
+               return IRQ_NONE;
+
+       /*
+        * Check to make sure its for us.
+        */
+       if (brd->magic != DGAP_BOARD_MAGIC)
+               return IRQ_NONE;
+
+       brd->intr_count++;
+
+       /*
+        * Schedule tasklet to run at a better time.
+        */
+       tasklet_schedule(&brd->helper_tasklet);
+       return IRQ_HANDLED;
+}
+
+/*
+ * dgap_init_globals()
+ *
+ * This is where we initialize the globals from the static insmod
+ * configuration variables.  These are declared near the head of
+ * this file.
+ */
+static void dgap_init_globals(void)
+{
+       int i = 0;
+
+       dgap_rawreadok          = rawreadok;
+
+       for (i = 0; i < MAXBOARDS; i++)
+               dgap_Board[i] = NULL;
+
+       init_timer(&dgap_poll_timer);
+
+       init_waitqueue_head(&dgap_dl_wait);
+       dgap_dl_action = 0;
+}
+
+/************************************************************************
+ *
+ * Utility functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_ms_sleep()
+ *
+ * Put the driver to sleep for x ms's
+ *
+ * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
+ */
+static int dgap_ms_sleep(ulong ms)
+{
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout((ms * HZ) / 1000);
+       return signal_pending(current);
+}
+
+/************************************************************************
+ *
+ * TTY Initialization/Cleanup Functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_tty_preinit()
+ *
+ * Initialize any global tty related data before we download any boards.
+ */
+static int dgap_tty_preinit(void)
+{
+       unsigned long flags;
+
+       DGAP_LOCK(dgap_global_lock, flags);
+
+       /*
+        * Allocate a buffer for doing the copy from user space to
+        * kernel space in dgap_input().  We only use one buffer and
+        * control access to it with a semaphore.  If we are paging, we
+        * are already in trouble so one buffer won't hurt much anyway.
+        */
+       dgap_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_ATOMIC);
+
+       if (!dgap_TmpWriteBuf) {
+               DGAP_UNLOCK(dgap_global_lock, flags);
+               return -ENOMEM;
+       }
+
+       DGAP_UNLOCK(dgap_global_lock, flags);
+       return 0;
+}
+
+/*
+ * dgap_tty_register()
+ *
+ * Init the tty subsystem for this board.
+ */
+static int dgap_tty_register(struct board_t *brd)
+{
+       int rc = 0;
+
+       brd->SerialDriver = alloc_tty_driver(MAXPORTS);
+
+       snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgap_%d_", brd->boardnum);
+       brd->SerialDriver->name = brd->SerialName;
+       brd->SerialDriver->name_base = 0;
+       brd->SerialDriver->major = 0;
+       brd->SerialDriver->minor_start = 0;
+       brd->SerialDriver->type = TTY_DRIVER_TYPE_SERIAL;
+       brd->SerialDriver->subtype = SERIAL_TYPE_NORMAL;
+       brd->SerialDriver->init_termios = DgapDefaultTermios;
+       brd->SerialDriver->driver_name = DRVSTR;
+       brd->SerialDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+       /* The kernel wants space to store pointers to tty_structs */
+       brd->SerialDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
+       if (!brd->SerialDriver->ttys)
+               return -ENOMEM;
+
+       /*
+        * Entry points for driver.  Called by the kernel from
+        * tty_io.c and n_tty.c.
+        */
+       tty_set_operations(brd->SerialDriver, &dgap_tty_ops);
+
+       /*
+        * If we're doing transparent print, we have to do all of the above
+        * again, separately so we don't get the LD confused about what major
+        * we are when we get into the dgap_tty_open() routine.
+        */
+       brd->PrintDriver = alloc_tty_driver(MAXPORTS);
+
+       snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgap_%d_", brd->boardnum);
+       brd->PrintDriver->name = brd->PrintName;
+       brd->PrintDriver->name_base = 0;
+       brd->PrintDriver->major = 0;
+       brd->PrintDriver->minor_start = 0;
+       brd->PrintDriver->type = TTY_DRIVER_TYPE_SERIAL;
+       brd->PrintDriver->subtype = SERIAL_TYPE_NORMAL;
+       brd->PrintDriver->init_termios = DgapDefaultTermios;
+       brd->PrintDriver->driver_name = DRVSTR;
+       brd->PrintDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+       /* The kernel wants space to store pointers to tty_structs */
+       brd->PrintDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
+       if (!brd->PrintDriver->ttys)
+               return -ENOMEM;
+
+       /*
+        * Entry points for driver.  Called by the kernel from
+        * tty_io.c and n_tty.c.
+        */
+       tty_set_operations(brd->PrintDriver, &dgap_tty_ops);
+
+       if (!brd->dgap_Major_Serial_Registered) {
+               /* Register tty devices */
+               rc = tty_register_driver(brd->SerialDriver);
+               if (rc < 0)
+                       return rc;
+               brd->dgap_Major_Serial_Registered = TRUE;
+               dgap_BoardsByMajor[brd->SerialDriver->major] = brd;
+               brd->dgap_Serial_Major = brd->SerialDriver->major;
+       }
+
+       if (!brd->dgap_Major_TransparentPrint_Registered) {
+               /* Register Transparent Print devices */
+               rc = tty_register_driver(brd->PrintDriver);
+               if (rc < 0)
+                       return rc;
+               brd->dgap_Major_TransparentPrint_Registered = TRUE;
+               dgap_BoardsByMajor[brd->PrintDriver->major] = brd;
+               brd->dgap_TransparentPrint_Major = brd->PrintDriver->major;
+       }
+
+       return rc;
+}
+
+/*
+ * dgap_tty_init()
+ *
+ * Init the tty subsystem.  Called once per board after board has been
+ * downloaded and init'ed.
+ */
+static int dgap_tty_init(struct board_t *brd)
+{
+       int i;
+       int tlw;
+       uint true_count = 0;
+       uchar *vaddr;
+       uchar modem = 0;
+       struct channel_t *ch;
+       struct bs_t *bs;
+       struct cm_t *cm;
+
+       if (!brd)
+               return -ENXIO;
+
+       /*
+        * Initialize board structure elements.
+        */
+
+       vaddr = brd->re_map_membase;
+       true_count = readw((vaddr + NCHAN));
+
+       brd->nasync = dgap_config_get_number_of_ports(brd);
+
+       if (!brd->nasync)
+               brd->nasync = brd->maxports;
+
+       if (brd->nasync > brd->maxports)
+               brd->nasync = brd->maxports;
+
+       if (true_count != brd->nasync) {
+               if ((brd->type == PPCM) && (true_count == 64))
+                       pr_warn("dgap: %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
+                               brd->name, brd->nasync, true_count);
+               else if ((brd->type == PPCM) && (true_count == 0))
+                       pr_warn("dgap: %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
+                               brd->name, brd->nasync, true_count);
+               else
+                       pr_warn("dgap: %s configured for %d ports, has %d ports.\n",
+                               brd->name, brd->nasync, true_count);
+
+               brd->nasync = true_count;
+
+               /* If no ports, don't bother going any further */
+               if (!brd->nasync) {
+                       brd->state = BOARD_FAILED;
+                       brd->dpastatus = BD_NOFEP;
+                       return -ENXIO;
+               }
+       }
+
+       /*
+        * Allocate channel memory that might not have been allocated
+        * when the driver was first loaded.
+        */
+       for (i = 0; i < brd->nasync; i++) {
+               if (!brd->channels[i]) {
+                       brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_ATOMIC);
+                       if (!brd->channels[i])
+                               return -ENOMEM;
+               }
+       }
+
+       ch = brd->channels[0];
+       vaddr = brd->re_map_membase;
+
+       bs = (struct bs_t *) ((ulong) vaddr + CHANBUF);
+       cm = (struct cm_t *) ((ulong) vaddr + CMDBUF);
+
+       brd->bd_bs = bs;
+
+       /* Set up channel variables */
+       for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
+
+               if (!brd->channels[i])
+                       continue;
+
+               DGAP_SPINLOCK_INIT(ch->ch_lock);
+
+               /* Store all our magic numbers */
+               ch->magic = DGAP_CHANNEL_MAGIC;
+               ch->ch_tun.magic = DGAP_UNIT_MAGIC;
+               ch->ch_tun.un_type = DGAP_SERIAL;
+               ch->ch_tun.un_ch = ch;
+               ch->ch_tun.un_dev = i;
+
+               ch->ch_pun.magic = DGAP_UNIT_MAGIC;
+               ch->ch_pun.un_type = DGAP_PRINT;
+               ch->ch_pun.un_ch = ch;
+               ch->ch_pun.un_dev = i;
+
+               ch->ch_vaddr = vaddr;
+               ch->ch_bs = bs;
+               ch->ch_cm = cm;
+               ch->ch_bd = brd;
+               ch->ch_portnum = i;
+               ch->ch_digi = dgap_digi_init;
+
+               /*
+                * Set up digi dsr and dcd bits based on altpin flag.
+                */
+               if (dgap_config_get_altpin(brd)) {
+                       ch->ch_dsr      = DM_CD;
+                       ch->ch_cd       = DM_DSR;
+                       ch->ch_digi.digi_flags |= DIGI_ALTPIN;
+               } else {
+                       ch->ch_cd       = DM_CD;
+                       ch->ch_dsr      = DM_DSR;
+               }
+
+               ch->ch_taddr = vaddr + ((ch->ch_bs->tx_seg) << 4);
+               ch->ch_raddr = vaddr + ((ch->ch_bs->rx_seg) << 4);
+               ch->ch_tx_win = 0;
+               ch->ch_rx_win = 0;
+               ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
+               ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
+               ch->ch_tstart = 0;
+               ch->ch_rstart = 0;
+
+               /* .25 second delay */
+               ch->ch_close_delay = 250;
+
+               /*
+                * Set queue water marks, interrupt mask,
+                * and general tty parameters.
+                */
+               ch->ch_tlw = tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : ch->ch_tsize / 2;
+
+               dgap_cmdw(ch, STLOW, tlw, 0);
+
+               dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
+
+               dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
+
+               ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
+
+               init_waitqueue_head(&ch->ch_flags_wait);
+               init_waitqueue_head(&ch->ch_tun.un_flags_wait);
+               init_waitqueue_head(&ch->ch_pun.un_flags_wait);
+               init_waitqueue_head(&ch->ch_sniff_wait);
+
+               /* Turn on all modem interrupts for now */
+               modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
+               writeb(modem, &(ch->ch_bs->m_int));
+
+               /*
+                * Set edelay to 0 if interrupts are turned on,
+                * otherwise set edelay to the usual 100.
+                */
+               if (brd->intr_used)
+                       writew(0, &(ch->ch_bs->edelay));
+               else
+                       writew(100, &(ch->ch_bs->edelay));
+
+               writeb(1, &(ch->ch_bs->idata));
+       }
+
+       return 0;
+}
+
+/*
+ * dgap_tty_post_uninit()
+ *
+ * UnInitialize any global tty related data.
+ */
+static void dgap_tty_post_uninit(void)
+{
+       kfree(dgap_TmpWriteBuf);
+       dgap_TmpWriteBuf = NULL;
+}
+
+/*
+ * dgap_tty_uninit()
+ *
+ * Uninitialize the TTY portion of this driver.  Free all memory and
+ * resources.
+ */
+static void dgap_tty_uninit(struct board_t *brd)
+{
+       int i = 0;
+
+       if (brd->dgap_Major_Serial_Registered) {
+               dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
+               brd->dgap_Serial_Major = 0;
+               for (i = 0; i < brd->nasync; i++) {
+                       tty_port_destroy(&brd->SerialPorts[i]);
+                       dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
+                       tty_unregister_device(brd->SerialDriver, i);
+               }
+               tty_unregister_driver(brd->SerialDriver);
+               kfree(brd->SerialDriver->ttys);
+               brd->SerialDriver->ttys = NULL;
+               put_tty_driver(brd->SerialDriver);
+               kfree(brd->SerialPorts);
+               brd->dgap_Major_Serial_Registered = FALSE;
+       }
+
+       if (brd->dgap_Major_TransparentPrint_Registered) {
+               dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
+               brd->dgap_TransparentPrint_Major = 0;
+               for (i = 0; i < brd->nasync; i++) {
+                       tty_port_destroy(&brd->PrinterPorts[i]);
+                       dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
+                       tty_unregister_device(brd->PrintDriver, i);
+               }
+               tty_unregister_driver(brd->PrintDriver);
+               kfree(brd->PrintDriver->ttys);
+               brd->PrintDriver->ttys = NULL;
+               put_tty_driver(brd->PrintDriver);
+               kfree(brd->PrinterPorts);
+               brd->dgap_Major_TransparentPrint_Registered = FALSE;
+       }
+}
+
+#define TMPBUFLEN (1024)
+/*
+ * dgap_sniff - Dump data out to the "sniff" buffer if the
+ * proc sniff file is opened...
+ */
+static void dgap_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len)
+{
+       struct timeval tv;
+       int n;
+       int r;
+       int nbuf;
+       int i;
+       int tmpbuflen;
+       char tmpbuf[TMPBUFLEN];
+       char *p = tmpbuf;
+       int too_much_data;
+
+       /* Leave if sniff not open */
+       if (!(ch->ch_sniff_flags & SNIFF_OPEN))
+               return;
+
+       do_gettimeofday(&tv);
+
+       /* Create our header for data dump */
+       p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
+       tmpbuflen = p - tmpbuf;
+
+       do {
+               too_much_data = 0;
+
+               for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
+                       p += sprintf(p, "%02x ", *buf);
+                       buf++;
+                       tmpbuflen = p - tmpbuf;
+               }
+
+               if (tmpbuflen < (TMPBUFLEN - 4)) {
+                       if (i > 0)
+                               p += sprintf(p - 1, "%s\n", ">");
+                       else
+                               p += sprintf(p, "%s\n", ">");
+               } else {
+                       too_much_data = 1;
+                       len -= i;
+               }
+
+               nbuf = strlen(tmpbuf);
+               p = tmpbuf;
+
+               /*
+                *  Loop while data remains.
+                */
+               while (nbuf > 0 && ch->ch_sniff_buf) {
+                       /*
+                        *  Determine the amount of available space left in the
+                        *  buffer.  If there's none, wait until some appears.
+                        */
+                       n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
+
+                       /*
+                        * If there is no space left to write to in our sniff buffer,
+                        * we have no choice but to drop the data.
+                        * We *cannot* sleep here waiting for space, because this
+                        * function was probably called by the interrupt/timer routines!
+                        */
+                       if (n == 0)
+                               return;
+
+                       /*
+                        * Copy as much data as will fit.
+                        */
+
+                       if (n > nbuf)
+                               n = nbuf;
+
+                       r = SNIFF_MAX - ch->ch_sniff_in;
+
+                       if (r <= n) {
+                               memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
+
+                               n -= r;
+                               ch->ch_sniff_in = 0;
+                               p += r;
+                               nbuf -= r;
+                       }
+
+                       memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
+
+                       ch->ch_sniff_in += n;
+                       p += n;
+                       nbuf -= n;
+
+                       /*
+                        *  Wakeup any thread waiting for data
+                        */
+                       if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
+                               ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
+                               wake_up_interruptible(&ch->ch_sniff_wait);
+                       }
+               }
+
+               /*
+                * If the user sent us too much data to push into our tmpbuf,
+                * we need to keep looping around on all the data.
+                */
+               if (too_much_data) {
+                       p = tmpbuf;
+                       tmpbuflen = 0;
+               }
+
+       } while (too_much_data);
+}
+
+/*=======================================================================
+ *
+ *      dgap_input - Process received data.
+ *
+ *              ch      - Pointer to channel structure.
+ *
+ *=======================================================================*/
+
+static void dgap_input(struct channel_t *ch)
+{
+       struct board_t *bd;
+       struct bs_t     *bs;
+       struct tty_struct *tp;
+       struct tty_ldisc *ld;
+       uint    rmask;
+       uint    head;
+       uint    tail;
+       int     data_len;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+       int flip_len;
+       int len = 0;
+       int n = 0;
+       uchar *buf;
+       uchar tmpchar;
+       int s = 0;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       tp = ch->ch_tun.un_tty;
+
+       bs  = ch->ch_bs;
+       if (!bs)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       /*
+        *      Figure the number of characters in the buffer.
+        *      Exit immediately if none.
+        */
+
+       rmask = ch->ch_rsize - 1;
+
+       head = readw(&(bs->rx_head));
+       head &= rmask;
+       tail = readw(&(bs->rx_tail));
+       tail &= rmask;
+
+       data_len = (head - tail) & rmask;
+
+       if (data_len == 0) {
+               writeb(1, &(bs->idata));
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return;
+       }
+
+       /*
+        * If the device is not open, or CREAD is off, flush
+        * input data and return immediately.
+        */
+       if ((bd->state != BOARD_READY) || !tp  ||
+           (tp->magic != TTY_MAGIC) ||
+           !(ch->ch_tun.un_flags & UN_ISOPEN) ||
+           !(tp->termios.c_cflag & CREAD) ||
+           (ch->ch_tun.un_flags & UN_CLOSING)) {
+
+               writew(head, &(bs->rx_tail));
+               writeb(1, &(bs->idata));
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return;
+       }
+
+       /*
+        * If we are throttled, simply don't read any data.
+        */
+       if (ch->ch_flags & CH_RXBLOCK) {
+               writeb(1, &(bs->idata));
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return;
+       }
+
+       /*
+        *      Ignore oruns.
+        */
+       tmpchar = readb(&(bs->orun));
+       if (tmpchar) {
+               ch->ch_err_overrun++;
+               writeb(0, &(bs->orun));
+       }
+
+       /* Decide how much data we can send into the tty layer */
+       flip_len = TTY_FLIPBUF_SIZE;
+
+       /* Chop down the length, if needed */
+       len = min(data_len, flip_len);
+       len = min(len, (N_TTY_BUF_SIZE - 1));
+
+       ld = tty_ldisc_ref(tp);
+
+#ifdef TTY_DONT_FLIP
+       /*
+        * If the DONT_FLIP flag is on, don't flush our buffer, and act
+        * like the ld doesn't have any space to put the data right now.
+        */
+       if (test_bit(TTY_DONT_FLIP, &tp->flags))
+               len = 0;
+#endif
+
+       /*
+        * If we were unable to get a reference to the ld,
+        * don't flush our buffer, and act like the ld doesn't
+        * have any space to put the data right now.
+        */
+       if (!ld) {
+               len = 0;
+       } else {
+               /*
+                * If ld doesn't have a pointer to a receive_buf function,
+                * flush the data, then act like the ld doesn't have any
+                * space to put the data right now.
+                */
+               if (!ld->ops->receive_buf) {
+                       writew(head, &(bs->rx_tail));
+                       len = 0;
+               }
+       }
+
+       if (len <= 0) {
+               writeb(1, &(bs->idata));
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               if (ld)
+                       tty_ldisc_deref(ld);
+               return;
+       }
+
+       buf = ch->ch_bd->flipbuf;
+       n = len;
+
+       /*
+        * n now contains the most amount of data we can copy,
+        * bounded either by our buffer size or the amount
+        * of data the card actually has pending...
+        */
+       while (n) {
+
+               s = ((head >= tail) ? head : ch->ch_rsize) - tail;
+               s = min(s, n);
+
+               if (s <= 0)
+                       break;
+
+               memcpy_fromio(buf, (char *) ch->ch_raddr + tail, s);
+               dgap_sniff_nowait_nolock(ch, "USER READ", buf, s);
+
+               tail += s;
+               buf += s;
+
+               n -= s;
+               /* Flip queue if needed */
+               tail &= rmask;
+       }
+
+       writew(tail, &(bs->rx_tail));
+       writeb(1, &(bs->idata));
+       ch->ch_rxcount += len;
+
+       /*
+        * If we are completely raw, we don't need to go through a lot
+        * of the tty layers that exist.
+        * In this case, we take the shortest and fastest route we
+        * can to relay the data to the user.
+        *
+        * On the other hand, if we are not raw, we need to go through
+        * the tty layer, which has its API more well defined.
+        */
+       if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+               dgap_parity_scan(ch, ch->ch_bd->flipbuf, ch->ch_bd->flipflagbuf, &len);
+
+               len = tty_buffer_request_room(tp->port, len);
+               tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
+                       ch->ch_bd->flipflagbuf, len);
+       } else {
+               len = tty_buffer_request_room(tp->port, len);
+               tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
+       }
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       /* Tell the tty layer its okay to "eat" the data now */
+       tty_flip_buffer_push(tp->port);
+
+       if (ld)
+               tty_ldisc_deref(ld);
+
+}
+
+/************************************************************************
+ * Determines when CARRIER changes state and takes appropriate
+ * action.
+ ************************************************************************/
+static void dgap_carrier(struct channel_t *ch)
+{
+       struct board_t *bd;
+
+       int virt_carrier = 0;
+       int phys_carrier = 0;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       /* Make sure altpin is always set correctly */
+       if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
+               ch->ch_dsr      = DM_CD;
+               ch->ch_cd       = DM_DSR;
+       } else {
+               ch->ch_dsr      = DM_DSR;
+               ch->ch_cd       = DM_CD;
+       }
+
+       if (ch->ch_mistat & D_CD(ch))
+               phys_carrier = 1;
+
+       if (ch->ch_digi.digi_flags & DIGI_FORCEDCD)
+               virt_carrier = 1;
+
+       if (ch->ch_c_cflag & CLOCAL)
+               virt_carrier = 1;
+
+       /*
+        * Test for a VIRTUAL carrier transition to HIGH.
+        */
+       if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
+
+               /*
+                * When carrier rises, wake any threads waiting
+                * for carrier in the open routine.
+                */
+
+               if (waitqueue_active(&(ch->ch_flags_wait)))
+                       wake_up_interruptible(&ch->ch_flags_wait);
+       }
+
+       /*
+        * Test for a PHYSICAL carrier transition to HIGH.
+        */
+       if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
+
+               /*
+                * When carrier rises, wake any threads waiting
+                * for carrier in the open routine.
+                */
+
+               if (waitqueue_active(&(ch->ch_flags_wait)))
+                       wake_up_interruptible(&ch->ch_flags_wait);
+       }
+
+       /*
+        *  Test for a PHYSICAL transition to low, so long as we aren't
+        *  currently ignoring physical transitions (which is what "virtual
+        *  carrier" indicates).
+        *
+        *  The transition of the virtual carrier to low really doesn't
+        *  matter... it really only means "ignore carrier state", not
+        *  "make pretend that carrier is there".
+        */
+       if ((virt_carrier == 0) &&
+           ((ch->ch_flags & CH_CD) != 0) &&
+           (phys_carrier == 0)) {
+
+               /*
+                *   When carrier drops:
+                *
+                *   Drop carrier on all open units.
+                *
+                *   Flush queues, waking up any task waiting in the
+                *   line discipline.
+                *
+                *   Send a hangup to the control terminal.
+                *
+                *   Enable all select calls.
+                */
+               if (waitqueue_active(&(ch->ch_flags_wait)))
+                       wake_up_interruptible(&ch->ch_flags_wait);
+
+               if (ch->ch_tun.un_open_count > 0)
+                       tty_hangup(ch->ch_tun.un_tty);
+
+               if (ch->ch_pun.un_open_count > 0)
+                       tty_hangup(ch->ch_pun.un_tty);
+       }
+
+       /*
+        *  Make sure that our cached values reflect the current reality.
+        */
+       if (virt_carrier == 1)
+               ch->ch_flags |= CH_FCAR;
+       else
+               ch->ch_flags &= ~CH_FCAR;
+
+       if (phys_carrier == 1)
+               ch->ch_flags |= CH_CD;
+       else
+               ch->ch_flags &= ~CH_CD;
+}
+
+/************************************************************************
+ *
+ * TTY Entry points and helper functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_tty_open()
+ *
+ */
+static int dgap_tty_open(struct tty_struct *tty, struct file *file)
+{
+       struct board_t  *brd;
+       struct channel_t *ch;
+       struct un_t     *un;
+       struct bs_t     *bs;
+       uint            major = 0;
+       uint            minor = 0;
+       int             rc = 0;
+       ulong           lock_flags;
+       ulong           lock_flags2;
+       u16             head;
+
+       rc = 0;
+
+       major = MAJOR(tty_devnum(tty));
+       minor = MINOR(tty_devnum(tty));
+
+       if (major > 255)
+               return -ENXIO;
+
+       /* Get board pointer from our array of majors we have allocated */
+       brd = dgap_BoardsByMajor[major];
+       if (!brd)
+               return -ENXIO;
+
+       /*
+        * If board is not yet up to a state of READY, go to
+        * sleep waiting for it to happen or they cancel the open.
+        */
+       rc = wait_event_interruptible(brd->state_wait,
+               (brd->state & BOARD_READY));
+
+       if (rc)
+               return rc;
+
+       DGAP_LOCK(brd->bd_lock, lock_flags);
+
+       /* The wait above should guarantee this cannot happen */
+       if (brd->state != BOARD_READY) {
+               DGAP_UNLOCK(brd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       /* If opened device is greater than our number of ports, bail. */
+       if (MINOR(tty_devnum(tty)) > brd->nasync) {
+               DGAP_UNLOCK(brd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       ch = brd->channels[minor];
+       if (!ch) {
+               DGAP_UNLOCK(brd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       /* Grab channel lock */
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       /* Figure out our type */
+       if (major == brd->dgap_Serial_Major) {
+               un = &brd->channels[minor]->ch_tun;
+               un->un_type = DGAP_SERIAL;
+       } else if (major == brd->dgap_TransparentPrint_Major) {
+               un = &brd->channels[minor]->ch_pun;
+               un->un_type = DGAP_PRINT;
+       } else {
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(brd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       /* Store our unit into driver_data, so we always have it available. */
+       tty->driver_data = un;
+
+       /*
+        * Error if channel info pointer is NULL.
+        */
+       bs = ch->ch_bs;
+       if (!bs) {
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(brd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       /*
+        * Initialize tty's
+        */
+       if (!(un->un_flags & UN_ISOPEN)) {
+               /* Store important variables. */
+               un->un_tty     = tty;
+
+               /* Maybe do something here to the TTY struct as well? */
+       }
+
+       /*
+        * Initialize if neither terminal or printer is open.
+        */
+       if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
+
+               ch->ch_mforce = 0;
+               ch->ch_mval = 0;
+
+               /*
+                * Flush input queue.
+                */
+               head = readw(&(bs->rx_head));
+               writew(head, &(bs->rx_tail));
+
+               ch->ch_flags = 0;
+               ch->pscan_state = 0;
+               ch->pscan_savechar = 0;
+
+               ch->ch_c_cflag   = tty->termios.c_cflag;
+               ch->ch_c_iflag   = tty->termios.c_iflag;
+               ch->ch_c_oflag   = tty->termios.c_oflag;
+               ch->ch_c_lflag   = tty->termios.c_lflag;
+               ch->ch_startc = tty->termios.c_cc[VSTART];
+               ch->ch_stopc  = tty->termios.c_cc[VSTOP];
+
+               /* TODO: flush our TTY struct here? */
+       }
+
+       dgap_carrier(ch);
+       /*
+        * Run param in case we changed anything
+        */
+       dgap_param(tty);
+
+       /*
+        * follow protocol for opening port
+        */
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(brd->bd_lock, lock_flags);
+
+       rc = dgap_block_til_ready(tty, file, ch);
+
+       if (!un->un_tty)
+               return -ENODEV;
+
+       /* No going back now, increment our unit and channel counters */
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+       ch->ch_open_count++;
+       un->un_open_count++;
+       un->un_flags |= (UN_ISOPEN);
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       return rc;
+}
+
+/*
+ * dgap_block_til_ready()
+ *
+ * Wait for DCD, if needed.
+ */
+static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
+{
+       int retval = 0;
+       struct un_t *un = NULL;
+       ulong   lock_flags;
+       uint    old_flags = 0;
+       int sleep_on_un_flags = 0;
+
+       if (!tty || tty->magic != TTY_MAGIC || !file || !ch ||
+               ch->magic != DGAP_CHANNEL_MAGIC)
+               return -ENXIO;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -ENXIO;
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+
+       ch->ch_wopen++;
+
+       /* Loop forever */
+       while (1) {
+
+               sleep_on_un_flags = 0;
+
+               /*
+                * If board has failed somehow during our sleep, bail with error.
+                */
+               if (ch->ch_bd->state == BOARD_FAILED) {
+                       retval = -ENXIO;
+                       break;
+               }
+
+               /* If tty was hung up, break out of loop and set error. */
+               if (tty_hung_up_p(file)) {
+                       retval = -EAGAIN;
+                       break;
+               }
+
+               /*
+                * If either unit is in the middle of the fragile part of close,
+                * we just cannot touch the channel safely.
+                * Go back to sleep, knowing that when the channel can be
+                * touched safely, the close routine will signal the
+                * ch_wait_flags to wake us back up.
+                */
+               if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
+
+                       /*
+                        * Our conditions to leave cleanly and happily:
+                        * 1) NONBLOCKING on the tty is set.
+                        * 2) CLOCAL is set.
+                        * 3) DCD (fake or real) is active.
+                        */
+
+                       if (file->f_flags & O_NONBLOCK)
+                               break;
+
+                       if (tty->flags & (1 << TTY_IO_ERROR))
+                               break;
+
+                       if (ch->ch_flags & CH_CD)
+                               break;
+
+                       if (ch->ch_flags & CH_FCAR)
+                               break;
+               } else {
+                       sleep_on_un_flags = 1;
+               }
+
+               /*
+                * If there is a signal pending, the user probably
+                * interrupted (ctrl-c) us.
+                * Leave loop with error set.
+                */
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       break;
+               }
+
+               /*
+                * Store the flags before we let go of channel lock
+                */
+               if (sleep_on_un_flags)
+                       old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
+               else
+                       old_flags = ch->ch_flags;
+
+               /*
+                * Let go of channel lock before calling schedule.
+                * Our poller will get any FEP events and wake us up when DCD
+                * eventually goes active.
+                */
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+               /*
+                * Wait for something in the flags to change from the current value.
+                */
+               if (sleep_on_un_flags) {
+                       retval = wait_event_interruptible(un->un_flags_wait,
+                               (old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
+               } else {
+                       retval = wait_event_interruptible(ch->ch_flags_wait,
+                               (old_flags != ch->ch_flags));
+               }
+
+               /*
+                * We got woken up for some reason.
+                * Before looping around, grab our channel lock.
+                */
+               DGAP_LOCK(ch->ch_lock, lock_flags);
+       }
+
+       ch->ch_wopen--;
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       if (retval)
+               return retval;
+
+       return 0;
+}
+
+/*
+ * dgap_tty_hangup()
+ *
+ * Hangup the port.  Like a close, but don't wait for output to drain.
+ */
+static void dgap_tty_hangup(struct tty_struct *tty)
+{
+       struct board_t  *bd;
+       struct channel_t *ch;
+       struct un_t     *un;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       /* flush the transmit queues */
+       dgap_tty_flush_buffer(tty);
+
+}
+
+/*
+ * dgap_tty_close()
+ *
+ */
+static void dgap_tty_close(struct tty_struct *tty, struct file *file)
+{
+       struct ktermios *ts;
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong lock_flags;
+       int rc = 0;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       ts = &tty->termios;
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+
+       /*
+        * Determine if this is the last close or not - and if we agree about
+        * which type of close it is with the Line Discipline
+        */
+       if ((tty->count == 1) && (un->un_open_count != 1))
+               /*
+                * Uh, oh.  tty->count is 1, which means that the tty
+                * structure will be freed.  un_open_count should always
+                * be one in these conditions.  If it's greater than
+                * one, we've got real problems, since it means the
+                * serial port won't be shutdown.
+                */
+               un->un_open_count = 1;
+
+       if (--un->un_open_count < 0)
+               un->un_open_count = 0;
+
+       ch->ch_open_count--;
+
+       if (ch->ch_open_count && un->un_open_count) {
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+               return;
+       }
+
+       /* OK, its the last close on the unit */
+
+       un->un_flags |= UN_CLOSING;
+
+       tty->closing = 1;
+
+       /*
+        * Only officially close channel if count is 0 and
+        * DIGI_PRINTER bit is not set.
+        */
+       if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
+
+               ch->ch_flags &= ~(CH_RXBLOCK);
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+               /* wait for output to drain */
+               /* This will also return if we take an interrupt */
+
+               rc = dgap_wait_for_drain(tty);
+
+               dgap_tty_flush_buffer(tty);
+               tty_ldisc_flush(tty);
+
+               DGAP_LOCK(ch->ch_lock, lock_flags);
+
+               tty->closing = 0;
+
+               /*
+                * If we have HUPCL set, lower DTR and RTS
+                */
+               if (ch->ch_c_cflag & HUPCL) {
+                       ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
+                       dgap_cmdb(ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0);
+
+                       /*
+                        * Go to sleep to ensure RTS/DTR
+                        * have been dropped for modems to see it.
+                        */
+                       if (ch->ch_close_delay) {
+                               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+                               dgap_ms_sleep(ch->ch_close_delay);
+                               DGAP_LOCK(ch->ch_lock, lock_flags);
+                       }
+               }
+
+               ch->pscan_state = 0;
+               ch->pscan_savechar = 0;
+               ch->ch_baud_info = 0;
+
+       }
+
+       /*
+        * turn off print device when closing print device.
+        */
+       if ((un->un_type == DGAP_PRINT)  && (ch->ch_flags & CH_PRON)) {
+               dgap_wmove(ch, ch->ch_digi.digi_offstr,
+                       (int) ch->ch_digi.digi_offlen);
+               ch->ch_flags &= ~CH_PRON;
+       }
+
+       un->un_tty = NULL;
+       un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
+       tty->driver_data = NULL;
+
+       wake_up_interruptible(&ch->ch_flags_wait);
+       wake_up_interruptible(&un->un_flags_wait);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+/*
+ * dgap_tty_chars_in_buffer()
+ *
+ * Return number of characters that have not been transmitted yet.
+ *
+ * This routine is used by the line discipline to determine if there
+ * is data waiting to be transmitted/drained/flushed or not.
+ */
+static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
+{
+       struct board_t *bd = NULL;
+       struct channel_t *ch = NULL;
+       struct un_t *un = NULL;
+       struct bs_t *bs = NULL;
+       uchar tbusy;
+       uint chars = 0;
+       u16 thead, ttail, tmask, chead, ctail;
+       ulong   lock_flags = 0;
+       ulong   lock_flags2 = 0;
+
+       if (tty == NULL)
+               return 0;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+
+       bs = ch->ch_bs;
+       if (!bs)
+               return 0;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       tmask = (ch->ch_tsize - 1);
+
+       /* Get Transmit queue pointers */
+       thead = readw(&(bs->tx_head)) & tmask;
+       ttail = readw(&(bs->tx_tail)) & tmask;
+
+       /* Get tbusy flag */
+       tbusy = readb(&(bs->tbusy));
+
+       /* Get Command queue pointers */
+       chead = readw(&(ch->ch_cm->cm_head));
+       ctail = readw(&(ch->ch_cm->cm_tail));
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       /*
+        * The only way we know for sure if there is no pending
+        * data left to be transferred, is if:
+        * 1) Transmit head and tail are equal (empty).
+        * 2) Command queue head and tail are equal (empty).
+        * 3) The "TBUSY" flag is 0. (Transmitter not busy).
+        */
+
+       if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
+               chars = 0;
+       } else {
+               if (thead >= ttail)
+                       chars = thead - ttail;
+               else
+                       chars = thead - ttail + ch->ch_tsize;
+               /*
+                * Fudge factor here.
+                * If chars is zero, we know that the command queue had
+                * something in it or tbusy was set.  Because we cannot
+                * be sure if there is still some data to be transmitted,
+                * lets lie, and tell ld we have 1 byte left.
+                */
+               if (chars == 0) {
+                       /*
+                        * If TBUSY is still set, and our tx buffers are empty,
+                        * force the firmware to send me another wakeup after
+                        * TBUSY has been cleared.
+                        */
+                       if (tbusy != 0) {
+                               DGAP_LOCK(ch->ch_lock, lock_flags);
+                               un->un_flags |= UN_EMPTY;
+                               writeb(1, &(bs->iempty));
+                               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+                       }
+                       chars = 1;
+               }
+       }
+
+       return chars;
+}
+
+static int dgap_wait_for_drain(struct tty_struct *tty)
+{
+       struct channel_t *ch;
+       struct un_t *un;
+       struct bs_t *bs;
+       int ret = -EIO;
+       uint count = 1;
+       ulong   lock_flags = 0;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return ret;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return ret;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return ret;
+
+       bs = ch->ch_bs;
+       if (!bs)
+               return ret;
+
+       ret = 0;
+
+       /* Loop until data is drained */
+       while (count != 0) {
+
+               count = dgap_tty_chars_in_buffer(tty);
+
+               if (count == 0)
+                       break;
+
+               /* Set flag waiting for drain */
+               DGAP_LOCK(ch->ch_lock, lock_flags);
+               un->un_flags |= UN_EMPTY;
+               writeb(1, &(bs->iempty));
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+               /* Go to sleep till we get woken up */
+               ret = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
+               /* If ret is non-zero, user ctrl-c'ed us */
+               if (ret)
+                       break;
+       }
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+       un->un_flags &= ~(UN_EMPTY);
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       return ret;
+}
+
+/*
+ * dgap_maxcps_room
+ *
+ * Reduces bytes_available to the max number of characters
+ * that can be sent currently given the maxcps value, and
+ * returns the new bytes_available.  This only affects printer
+ * output.
+ */
+static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
+{
+       struct channel_t *ch = NULL;
+       struct un_t *un = NULL;
+
+       if (tty == NULL)
+               return bytes_available;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return bytes_available;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return bytes_available;
+
+       /*
+        * If its not the Transparent print device, return
+        * the full data amount.
+        */
+       if (un->un_type != DGAP_PRINT)
+               return bytes_available;
+
+       if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) {
+               int cps_limit = 0;
+               unsigned long current_time = jiffies;
+               unsigned long buffer_time = current_time +
+                       (HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
+
+               if (ch->ch_cpstime < current_time) {
+                       /* buffer is empty */
+                       ch->ch_cpstime = current_time;            /* reset ch_cpstime */
+                       cps_limit = ch->ch_digi.digi_bufsize;
+               } else if (ch->ch_cpstime < buffer_time) {
+                       /* still room in the buffer */
+                       cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
+               } else {
+                       /* no room in the buffer */
+                       cps_limit = 0;
+               }
+
+               bytes_available = min(cps_limit, bytes_available);
+       }
+
+       return bytes_available;
+}
+
+static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
+{
+       struct channel_t *ch = NULL;
+       struct bs_t *bs = NULL;
+
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+       bs = ch->ch_bs;
+       if (!bs)
+               return;
+
+       if ((event & UN_LOW) != 0) {
+               if ((un->un_flags & UN_LOW) == 0) {
+                       un->un_flags |= UN_LOW;
+                       writeb(1, &(bs->ilow));
+               }
+       }
+       if ((event & UN_LOW) != 0) {
+               if ((un->un_flags & UN_EMPTY) == 0) {
+                       un->un_flags |= UN_EMPTY;
+                       writeb(1, &(bs->iempty));
+               }
+       }
+}
+
+/*
+ * dgap_tty_write_room()
+ *
+ * Return space available in Tx buffer
+ */
+static int dgap_tty_write_room(struct tty_struct *tty)
+{
+       struct channel_t *ch = NULL;
+       struct un_t *un = NULL;
+       struct bs_t *bs = NULL;
+       u16 head, tail, tmask;
+       int ret = 0;
+       ulong   lock_flags = 0;
+
+       if (tty == NULL || dgap_TmpWriteBuf == NULL)
+               return 0;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+
+       bs = ch->ch_bs;
+       if (!bs)
+               return 0;
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+
+       tmask = ch->ch_tsize - 1;
+       head = readw(&(bs->tx_head)) & tmask;
+       tail = readw(&(bs->tx_tail)) & tmask;
+
+       ret = tail - head - 1;
+       if (ret < 0)
+               ret += ch->ch_tsize;
+
+       /* Limit printer to maxcps */
+       ret = dgap_maxcps_room(tty, ret);
+
+       /*
+        * If we are printer device, leave space for
+        * possibly both the on and off strings.
+        */
+       if (un->un_type == DGAP_PRINT) {
+               if (!(ch->ch_flags & CH_PRON))
+                       ret -= ch->ch_digi.digi_onlen;
+               ret -= ch->ch_digi.digi_offlen;
+       } else {
+               if (ch->ch_flags & CH_PRON)
+                       ret -= ch->ch_digi.digi_offlen;
+       }
+
+       if (ret < 0)
+               ret = 0;
+
+       /*
+        * Schedule FEP to wake us up if needed.
+        *
+        * TODO:  This might be overkill...
+        * Do we really need to schedule callbacks from the FEP
+        * in every case?  Can we get smarter based on ret?
+        */
+       dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       return ret;
+}
+
+/*
+ * dgap_tty_put_char()
+ *
+ * Put a character into ch->ch_buf
+ *
+ *      - used by the line discipline for OPOST processing
+ */
+static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
+{
+       /*
+        * Simply call tty_write.
+        */
+       dgap_tty_write(tty, &c, 1);
+       return 1;
+}
+
+/*
+ * dgap_tty_write()
+ *
+ * Take data from the user or kernel and send it out to the FEP.
+ * In here exists all the Transparent Print magic as well.
+ */
+static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+       struct channel_t *ch = NULL;
+       struct un_t *un = NULL;
+       struct bs_t *bs = NULL;
+       char *vaddr = NULL;
+       u16 head, tail, tmask, remain;
+       int bufcount = 0, n = 0;
+       int orig_count = 0;
+       ulong lock_flags;
+       int from_user = 0;
+
+       if (tty == NULL || dgap_TmpWriteBuf == NULL)
+               return 0;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+
+       bs = ch->ch_bs;
+       if (!bs)
+               return 0;
+
+       if (!count)
+               return 0;
+
+       /*
+        * Store original amount of characters passed in.
+        * This helps to figure out if we should ask the FEP
+        * to send us an event when it has more space available.
+        */
+       orig_count = count;
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+
+       /* Get our space available for the channel from the board */
+       tmask = ch->ch_tsize - 1;
+       head = readw(&(bs->tx_head)) & tmask;
+       tail = readw(&(bs->tx_tail)) & tmask;
+
+       bufcount = tail - head - 1;
+       if (bufcount < 0)
+               bufcount += ch->ch_tsize;
+
+       /*
+        * Limit printer output to maxcps overall, with bursts allowed
+        * up to bufsize characters.
+        */
+       bufcount = dgap_maxcps_room(tty, bufcount);
+
+       /*
+        * Take minimum of what the user wants to send, and the
+        * space available in the FEP buffer.
+        */
+       count = min(count, bufcount);
+
+       /*
+        * Bail if no space left.
+        */
+       if (count <= 0) {
+               dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+               return 0;
+       }
+
+       /*
+        * Output the printer ON string, if we are in terminal mode, but
+        * need to be in printer mode.
+        */
+       if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
+               dgap_wmove(ch, ch->ch_digi.digi_onstr,
+                   (int) ch->ch_digi.digi_onlen);
+               head = readw(&(bs->tx_head)) & tmask;
+               ch->ch_flags |= CH_PRON;
+       }
+
+       /*
+        * On the other hand, output the printer OFF string, if we are
+        * currently in printer mode, but need to output to the terminal.
+        */
+       if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
+               dgap_wmove(ch, ch->ch_digi.digi_offstr,
+                       (int) ch->ch_digi.digi_offlen);
+               head = readw(&(bs->tx_head)) & tmask;
+               ch->ch_flags &= ~CH_PRON;
+       }
+
+       /*
+        * If there is nothing left to copy, or I can't handle any more data, leave.
+        */
+       if (count <= 0) {
+               dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+               return 0;
+       }
+
+       if (from_user) {
+
+               count = min(count, WRITEBUFLEN);
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+               /*
+                * If data is coming from user space, copy it into a temporary
+                * buffer so we don't get swapped out while doing the copy to
+                * the board.
+                */
+               /* we're allowed to block if it's from_user */
+               if (down_interruptible(&dgap_TmpWriteSem))
+                       return -EINTR;
+
+               if (copy_from_user(dgap_TmpWriteBuf, (const uchar __user *) buf, count)) {
+                       up(&dgap_TmpWriteSem);
+                       printk("Write: Copy from user failed!\n");
+                       return -EFAULT;
+               }
+
+               DGAP_LOCK(ch->ch_lock, lock_flags);
+
+               buf = dgap_TmpWriteBuf;
+       }
+
+       n = count;
+
+       /*
+        * If the write wraps over the top of the circular buffer,
+        * move the portion up to the wrap point, and reset the
+        * pointers to the bottom.
+        */
+       remain = ch->ch_tstart + ch->ch_tsize - head;
+
+       if (n >= remain) {
+               n -= remain;
+               vaddr = ch->ch_taddr + head;
+
+               memcpy_toio(vaddr, (uchar *) buf, remain);
+               dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
+
+               head = ch->ch_tstart;
+               buf += remain;
+       }
+
+       if (n > 0) {
+
+               /*
+                * Move rest of data.
+                */
+               vaddr = ch->ch_taddr + head;
+               remain = n;
+
+               memcpy_toio(vaddr, (uchar *) buf, remain);
+               dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
+
+               head += remain;
+
+       }
+
+       if (count) {
+               ch->ch_txcount += count;
+               head &= tmask;
+               writew(head, &(bs->tx_head));
+       }
+
+       dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+
+       /*
+        * If this is the print device, and the
+        * printer is still on, we need to turn it
+        * off before going idle.  If the buffer is
+        * non-empty, wait until it goes empty.
+        * Otherwise turn it off right now.
+        */
+       if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
+               tail = readw(&(bs->tx_tail)) & tmask;
+
+               if (tail != head) {
+                       un->un_flags |= UN_EMPTY;
+                       writeb(1, &(bs->iempty));
+               } else {
+                       dgap_wmove(ch, ch->ch_digi.digi_offstr,
+                               (int) ch->ch_digi.digi_offlen);
+                       head = readw(&(bs->tx_head)) & tmask;
+                       ch->ch_flags &= ~CH_PRON;
+               }
+       }
+
+       /* Update printer buffer empty time. */
+       if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
+           && (ch->ch_digi.digi_bufsize > 0)) {
+               ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
+       }
+
+       if (from_user) {
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+               up(&dgap_TmpWriteSem);
+       } else
+               DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       return count;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgap_tty_tiocmget(struct tty_struct *tty)
+{
+       struct channel_t *ch;
+       struct un_t *un;
+       int result = -EIO;
+       uchar mstat = 0;
+       ulong lock_flags;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return result;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return result;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return result;
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+
+       mstat = readb(&(ch->ch_bs->m_stat));
+       /* Append any outbound signals that might be pending... */
+       mstat |= ch->ch_mostat;
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       result = 0;
+
+       if (mstat & D_DTR(ch))
+               result |= TIOCM_DTR;
+       if (mstat & D_RTS(ch))
+               result |= TIOCM_RTS;
+       if (mstat & D_CTS(ch))
+               result |= TIOCM_CTS;
+       if (mstat & D_DSR(ch))
+               result |= TIOCM_DSR;
+       if (mstat & D_RI(ch))
+               result |= TIOCM_RI;
+       if (mstat & D_CD(ch))
+               result |= TIOCM_CD;
+
+       return result;
+}
+
+/*
+ * dgap_tty_tiocmset()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgap_tty_tiocmset(struct tty_struct *tty,
+               unsigned int set, unsigned int clear)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       int ret = -EIO;
+       ulong lock_flags;
+       ulong lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return ret;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return ret;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return ret;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return ret;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       if (set & TIOCM_RTS) {
+               ch->ch_mforce |= D_RTS(ch);
+               ch->ch_mval   |= D_RTS(ch);
+       }
+
+       if (set & TIOCM_DTR) {
+               ch->ch_mforce |= D_DTR(ch);
+               ch->ch_mval   |= D_DTR(ch);
+       }
+
+       if (clear & TIOCM_RTS) {
+               ch->ch_mforce |= D_RTS(ch);
+               ch->ch_mval   &= ~(D_RTS(ch));
+       }
+
+       if (clear & TIOCM_DTR) {
+               ch->ch_mforce |= D_DTR(ch);
+               ch->ch_mval   &= ~(D_DTR(ch));
+       }
+
+       dgap_param(tty);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return 0;
+}
+
+/*
+ * dgap_tty_send_break()
+ *
+ * Send a Break, called by ld.
+ */
+static int dgap_tty_send_break(struct tty_struct *tty, int msec)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       int ret = -EIO;
+       ulong lock_flags;
+       ulong lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return ret;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return ret;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return ret;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return ret;
+
+       switch (msec) {
+       case -1:
+               msec = 0xFFFF;
+               break;
+       case 0:
+               msec = 1;
+               break;
+       default:
+               msec /= 10;
+               break;
+       }
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+#if 0
+       dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+#endif
+       dgap_cmdw(ch, SBREAK, (u16) msec, 0);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return 0;
+}
+
+/*
+ * dgap_tty_wait_until_sent()
+ *
+ * wait until data has been transmitted, called by ld.
+ */
+static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+       dgap_wait_for_drain(tty);
+}
+
+/*
+ * dgap_send_xchar()
+ *
+ * send a high priority character, called by ld.
+ */
+static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong lock_flags;
+       ulong lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       /*
+        * This is technically what we should do.
+        * However, the NIST tests specifically want
+        * to see each XON or XOFF character that it
+        * sends, so lets just send each character
+        * by hand...
+        */
+#if 0
+       if (c == STOP_CHAR(tty))
+               dgap_cmdw(ch, RPAUSE, 0, 0);
+       else if (c == START_CHAR(tty))
+               dgap_cmdw(ch, RRESUME, 0, 0);
+       else
+               dgap_wmove(ch, &c, 1);
+#else
+       dgap_wmove(ch, &c, 1);
+#endif
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
+{
+       int result = 0;
+       uchar mstat = 0;
+       ulong lock_flags;
+       int rc = 0;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -ENXIO;
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+
+       mstat = readb(&(ch->ch_bs->m_stat));
+       /* Append any outbound signals that might be pending... */
+       mstat |= ch->ch_mostat;
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       result = 0;
+
+       if (mstat & D_DTR(ch))
+               result |= TIOCM_DTR;
+       if (mstat & D_RTS(ch))
+               result |= TIOCM_RTS;
+       if (mstat & D_CTS(ch))
+               result |= TIOCM_CTS;
+       if (mstat & D_DSR(ch))
+               result |= TIOCM_DSR;
+       if (mstat & D_RI(ch))
+               result |= TIOCM_RI;
+       if (mstat & D_CD(ch))
+               result |= TIOCM_CD;
+
+       rc = put_user(result, value);
+
+       return rc;
+}
+
+/*
+ * dgap_set_modem_info()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       int ret = -ENXIO;
+       unsigned int arg = 0;
+       ulong lock_flags;
+       ulong lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return ret;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return ret;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return ret;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return ret;
+
+       ret = get_user(arg, value);
+       if (ret)
+               return ret;
+
+       switch (command) {
+       case TIOCMBIS:
+               if (arg & TIOCM_RTS) {
+                       ch->ch_mforce |= D_RTS(ch);
+                       ch->ch_mval   |= D_RTS(ch);
+               }
+
+               if (arg & TIOCM_DTR) {
+                       ch->ch_mforce |= D_DTR(ch);
+                       ch->ch_mval   |= D_DTR(ch);
+               }
+
+               break;
+
+       case TIOCMBIC:
+               if (arg & TIOCM_RTS) {
+                       ch->ch_mforce |= D_RTS(ch);
+                       ch->ch_mval   &= ~(D_RTS(ch));
+               }
+
+               if (arg & TIOCM_DTR) {
+                       ch->ch_mforce |= D_DTR(ch);
+                       ch->ch_mval   &= ~(D_DTR(ch));
+               }
+
+               break;
+
+       case TIOCMSET:
+               ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
+
+               if (arg & TIOCM_RTS)
+                       ch->ch_mval |= D_RTS(ch);
+               else
+                       ch->ch_mval &= ~(D_RTS(ch));
+
+               if (arg & TIOCM_DTR)
+                       ch->ch_mval |= (D_DTR(ch));
+               else
+                       ch->ch_mval &= ~(D_DTR(ch));
+
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       dgap_param(tty);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return 0;
+}
+
+/*
+ * dgap_tty_digigeta()
+ *
+ * Ioctl to get the information for ditty.
+ *
+ *
+ *
+ */
+static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
+{
+       struct channel_t *ch;
+       struct un_t *un;
+       struct digi_t tmp;
+       ulong lock_flags;
+
+       if (!retinfo)
+               return -EFAULT;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -EFAULT;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -EFAULT;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+       memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * dgap_tty_digiseta()
+ *
+ * Ioctl to set the information for ditty.
+ *
+ *
+ *
+ */
+static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       struct digi_t new_digi;
+       ulong   lock_flags = 0;
+       unsigned long lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -EFAULT;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -EFAULT;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -EFAULT;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return -EFAULT;
+
+       if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t)))
+               return -EFAULT;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
+
+       if (ch->ch_digi.digi_maxcps < 1)
+               ch->ch_digi.digi_maxcps = 1;
+
+       if (ch->ch_digi.digi_maxcps > 10000)
+               ch->ch_digi.digi_maxcps = 10000;
+
+       if (ch->ch_digi.digi_bufsize < 10)
+               ch->ch_digi.digi_bufsize = 10;
+
+       if (ch->ch_digi.digi_maxchar < 1)
+               ch->ch_digi.digi_maxchar = 1;
+
+       if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
+               ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
+
+       if (ch->ch_digi.digi_onlen > DIGI_PLEN)
+               ch->ch_digi.digi_onlen = DIGI_PLEN;
+
+       if (ch->ch_digi.digi_offlen > DIGI_PLEN)
+               ch->ch_digi.digi_offlen = DIGI_PLEN;
+
+       dgap_param(tty);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return 0;
+}
+
+/*
+ * dgap_tty_digigetedelay()
+ *
+ * Ioctl to get the current edelay setting.
+ *
+ *
+ *
+ */
+static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
+{
+       struct channel_t *ch;
+       struct un_t *un;
+       int tmp;
+       ulong lock_flags;
+
+       if (!retinfo)
+               return -EFAULT;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -EFAULT;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -EFAULT;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+       tmp = readw(&(ch->ch_bs->edelay));
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * dgap_tty_digisetedelay()
+ *
+ * Ioctl to set the EDELAY setting
+ *
+ */
+static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       int new_digi;
+       ulong lock_flags;
+       ulong lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -EFAULT;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -EFAULT;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -EFAULT;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return -EFAULT;
+
+       if (copy_from_user(&new_digi, new_info, sizeof(int)))
+               return -EFAULT;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       writew((u16) new_digi, &(ch->ch_bs->edelay));
+
+       dgap_param(tty);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return 0;
+}
+
+/*
+ * dgap_tty_digigetcustombaud()
+ *
+ * Ioctl to get the current custom baud rate setting.
+ */
+static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo)
+{
+       struct channel_t *ch;
+       struct un_t *un;
+       int tmp;
+       ulong lock_flags;
+
+       if (!retinfo)
+               return -EFAULT;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -EFAULT;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -EFAULT;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       DGAP_LOCK(ch->ch_lock, lock_flags);
+       tmp = dgap_get_custom_baud(ch);
+       DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * dgap_tty_digisetcustombaud()
+ *
+ * Ioctl to set the custom baud rate setting
+ */
+static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       uint new_rate;
+       ulong lock_flags;
+       ulong lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -EFAULT;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -EFAULT;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -EFAULT;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return -EFAULT;
+
+
+       if (copy_from_user(&new_rate, new_info, sizeof(unsigned int)))
+               return -EFAULT;
+
+       if (bd->bd_flags & BD_FEP5PLUS) {
+
+               DGAP_LOCK(bd->bd_lock, lock_flags);
+               DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+               ch->ch_custom_speed = new_rate;
+
+               dgap_param(tty);
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+       }
+
+       return 0;
+}
+
+/*
+ * dgap_set_termios()
+ */
+static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       unsigned long lock_flags;
+       unsigned long lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       ch->ch_c_cflag   = tty->termios.c_cflag;
+       ch->ch_c_iflag   = tty->termios.c_iflag;
+       ch->ch_c_oflag   = tty->termios.c_oflag;
+       ch->ch_c_lflag   = tty->termios.c_lflag;
+       ch->ch_startc    = tty->termios.c_cc[VSTART];
+       ch->ch_stopc     = tty->termios.c_cc[VSTOP];
+
+       dgap_carrier(ch);
+       dgap_param(tty);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+static void dgap_tty_throttle(struct tty_struct *tty)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       ch->ch_flags |= (CH_RXBLOCK);
+#if 1
+       dgap_cmdw(ch, RPAUSE, 0, 0);
+#endif
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+static void dgap_tty_unthrottle(struct tty_struct *tty)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       ch->ch_flags &= ~(CH_RXBLOCK);
+
+#if 1
+       dgap_cmdw(ch, RRESUME, 0, 0);
+#endif
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+static void dgap_tty_start(struct tty_struct *tty)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       dgap_cmdw(ch, RESUMETX, 0, 0);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+static void dgap_tty_stop(struct tty_struct *tty)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       dgap_cmdw(ch, PAUSETX, 0, 0);
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+/*
+ * dgap_tty_flush_chars()
+ *
+ * Flush the cook buffer
+ *
+ * Note to self, and any other poor souls who venture here:
+ *
+ * flush in this case DOES NOT mean dispose of the data.
+ * instead, it means "stop buffering and send it if you
+ * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
+ *
+ * It is also always called in interrupt context - JAR 8-Sept-99
+ */
+static void dgap_tty_flush_chars(struct tty_struct *tty)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       /* TODO: Do something here */
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+/*
+ * dgap_tty_flush_buffer()
+ *
+ * Flush Tx buffer (make in == out)
+ */
+static void dgap_tty_flush_buffer(struct tty_struct *tty)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       ulong   lock_flags;
+       ulong   lock_flags2;
+       u16     head = 0;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       ch->ch_flags &= ~CH_STOP;
+       head = readw(&(ch->ch_bs->tx_head));
+       dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+       dgap_cmdw(ch, RESUMETX, 0, 0);
+       if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+               ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+               wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+       }
+       if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+               ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+               wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+       }
+
+       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+       if (waitqueue_active(&tty->write_wait))
+               wake_up_interruptible(&tty->write_wait);
+       tty_wakeup(tty);
+}
+
+/*****************************************************************************
+ *
+ * The IOCTL function and all of its helpers
+ *
+ *****************************************************************************/
+
+/*
+ * dgap_tty_ioctl()
+ *
+ * The usual assortment of ioctl's
+ */
+static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+               unsigned long arg)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       int rc;
+       u16     head = 0;
+       ulong   lock_flags = 0;
+       ulong   lock_flags2 = 0;
+       void __user *uarg = (void __user *) arg;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -ENODEV;
+
+       un = tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -ENODEV;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -ENODEV;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return -ENODEV;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+       if (un->un_open_count <= 0) {
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return -EIO;
+       }
+
+       switch (cmd) {
+
+       /* Here are all the standard ioctl's that we MUST implement */
+
+       case TCSBRK:
+               /*
+                * TCSBRK is SVID version: non-zero arg --> no break
+                * this behaviour is exploited by tcdrain().
+                *
+                * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+                * between 0.25 and 0.5 seconds so we'll ask for something
+                * in the middle: 0.375 seconds.
+                */
+               rc = tty_check_change(tty);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               if (rc)
+                       return rc;
+
+               rc = dgap_wait_for_drain(tty);
+
+               if (rc)
+                       return -EINTR;
+
+               DGAP_LOCK(bd->bd_lock, lock_flags);
+               DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+               if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP))
+                       dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               return 0;
+
+       case TCSBRKP:
+               /* support for POSIX tcsendbreak()
+
+                * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+                * between 0.25 and 0.5 seconds so we'll ask for something
+                * in the middle: 0.375 seconds.
+                */
+               rc = tty_check_change(tty);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               if (rc)
+                       return rc;
+
+               rc = dgap_wait_for_drain(tty);
+               if (rc)
+                       return -EINTR;
+
+               DGAP_LOCK(bd->bd_lock, lock_flags);
+               DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+               dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               return 0;
+
+       case TIOCSBRK:
+               /*
+                * FEP5 doesn't support turning on a break unconditionally.
+                * The FEP5 device will stop sending a break automatically
+                * after the specified time value that was sent when turning on
+                * the break.
+                */
+               rc = tty_check_change(tty);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               if (rc)
+                       return rc;
+
+               rc = dgap_wait_for_drain(tty);
+               if (rc)
+                       return -EINTR;
+
+               DGAP_LOCK(bd->bd_lock, lock_flags);
+               DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+               dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               return 0;
+
+       case TIOCCBRK:
+               /*
+                * FEP5 doesn't support turning off a break unconditionally.
+                * The FEP5 device will stop sending a break automatically
+                * after the specified time value that was sent when turning on
+                * the break.
+                */
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return 0;
+
+       case TIOCGSOFTCAR:
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
+               return rc;
+
+       case TIOCSSOFTCAR:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               rc = get_user(arg, (unsigned long __user *) arg);
+               if (rc)
+                       return rc;
+
+               DGAP_LOCK(bd->bd_lock, lock_flags);
+               DGAP_LOCK(ch->ch_lock, lock_flags2);
+               tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+               dgap_param(tty);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               return 0;
+
+       case TIOCMGET:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_get_modem_info(ch, uarg);
+
+       case TIOCMBIS:
+       case TIOCMBIC:
+       case TIOCMSET:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_set_modem_info(tty, cmd, uarg);
+
+               /*
+                * Here are any additional ioctl's that we want to implement
+                */
+
+       case TCFLSH:
+               /*
+                * The linux tty driver doesn't have a flush
+                * input routine for the driver, assuming all backed
+                * up data is in the line disc. buffers.  However,
+                * we all know that's not the case.  Here, we
+                * act on the ioctl, but then lie and say we didn't
+                * so the line discipline will process the flush
+                * also.
+                */
+               rc = tty_check_change(tty);
+               if (rc) {
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       return rc;
+               }
+
+               if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
+                       if (!(un->un_type == DGAP_PRINT)) {
+                               head = readw(&(ch->ch_bs->rx_head));
+                               writew(head, &(ch->ch_bs->rx_tail));
+                               writeb(0, &(ch->ch_bs->orun));
+                       }
+               }
+
+               if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
+                       ch->ch_flags &= ~CH_STOP;
+                       head = readw(&(ch->ch_bs->tx_head));
+                       dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+                       dgap_cmdw(ch, RESUMETX, 0, 0);
+                       if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+                               ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+                               wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+                       }
+                       if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+                               ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+                               wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+                       }
+                       if (waitqueue_active(&tty->write_wait))
+                               wake_up_interruptible(&tty->write_wait);
+
+                       /* Can't hold any locks when calling tty_wakeup! */
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       tty_wakeup(tty);
+                       DGAP_LOCK(bd->bd_lock, lock_flags);
+                       DGAP_LOCK(ch->ch_lock, lock_flags2);
+               }
+
+               /* pretend we didn't recognize this IOCTL */
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               return -ENOIOCTLCMD;
+
+       case TCSETSF:
+       case TCSETSW:
+               /*
+                * The linux tty driver doesn't have a flush
+                * input routine for the driver, assuming all backed
+                * up data is in the line disc. buffers.  However,
+                * we all know that's not the case.  Here, we
+                * act on the ioctl, but then lie and say we didn't
+                * so the line discipline will process the flush
+                * also.
+                */
+               if (cmd == TCSETSF) {
+                       /* flush rx */
+                       ch->ch_flags &= ~CH_STOP;
+                       head = readw(&(ch->ch_bs->rx_head));
+                       writew(head, &(ch->ch_bs->rx_tail));
+               }
+
+               /* now wait for all the output to drain */
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               rc = dgap_wait_for_drain(tty);
+               if (rc)
+                       return -EINTR;
+
+               /* pretend we didn't recognize this */
+               return -ENOIOCTLCMD;
+
+       case TCSETAW:
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               rc = dgap_wait_for_drain(tty);
+               if (rc)
+                       return -EINTR;
+
+               /* pretend we didn't recognize this */
+               return -ENOIOCTLCMD;
+
+       case TCXONC:
+               /*
+                * The Linux Line Discipline (LD) would do this for us if we
+                * let it, but we have the special firmware options to do this
+                * the "right way" regardless of hardware or software flow
+                * control so we'll do it outselves instead of letting the LD
+                * do it.
+                */
+               rc = tty_check_change(tty);
+               if (rc) {
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       return rc;
+               }
+
+               switch (arg) {
+
+               case TCOON:
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       dgap_tty_start(tty);
+                       return 0;
+               case TCOOFF:
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       dgap_tty_stop(tty);
+                       return 0;
+               case TCION:
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       /* Make the ld do it */
+                       return -ENOIOCTLCMD;
+               case TCIOFF:
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       /* Make the ld do it */
+                       return -ENOIOCTLCMD;
+               default:
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       return -EINVAL;
+               }
+
+       case DIGI_GETA:
+               /* get information for ditty */
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_tty_digigeta(tty, uarg);
+
+       case DIGI_SETAW:
+       case DIGI_SETAF:
+
+               /* set information for ditty */
+               if (cmd == (DIGI_SETAW)) {
+
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       rc = dgap_wait_for_drain(tty);
+                       if (rc)
+                               return -EINTR;
+                       DGAP_LOCK(bd->bd_lock, lock_flags);
+                       DGAP_LOCK(ch->ch_lock, lock_flags2);
+               } else
+                       tty_ldisc_flush(tty);
+               /* fall thru */
+
+       case DIGI_SETA:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_tty_digiseta(tty, uarg);
+
+       case DIGI_GEDELAY:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_tty_digigetedelay(tty, uarg);
+
+       case DIGI_SEDELAY:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_tty_digisetedelay(tty, uarg);
+
+       case DIGI_GETCUSTOMBAUD:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_tty_digigetcustombaud(tty, uarg);
+
+       case DIGI_SETCUSTOMBAUD:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return dgap_tty_digisetcustombaud(tty, uarg);
+
+       case DIGI_RESET_PORT:
+               dgap_firmware_reset_port(ch);
+               dgap_param(tty);
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return 0;
+
+       default:
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+               return -ENOIOCTLCMD;
+       }
+}
+
+static int dgap_after_config_loaded(int board)
+{
+       /*
+        * Initialize KME waitqueues...
+        */
+       init_waitqueue_head(&(dgap_Board[board]->kme_wait));
+
+       /*
+        * allocate flip buffer for board.
+        */
+       dgap_Board[board]->flipbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
+       if (!dgap_Board[board]->flipbuf)
+               return -ENOMEM;
+
+       dgap_Board[board]->flipflagbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
+       if (!dgap_Board[board]->flipflagbuf) {
+               kfree(dgap_Board[board]->flipbuf);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/*
+ * Create pr and tty device entries
+ */
+static int dgap_tty_register_ports(struct board_t *brd)
+{
+       struct channel_t *ch;
+       int i;
+
+       brd->SerialPorts = kcalloc(brd->nasync, sizeof(*brd->SerialPorts),
+                                       GFP_KERNEL);
+       if (brd->SerialPorts == NULL)
+               return -ENOMEM;
+       for (i = 0; i < brd->nasync; i++)
+               tty_port_init(&brd->SerialPorts[i]);
+
+       brd->PrinterPorts = kcalloc(brd->nasync, sizeof(*brd->PrinterPorts),
+                                       GFP_KERNEL);
+       if (brd->PrinterPorts == NULL) {
+               kfree(brd->SerialPorts);
+               return -ENOMEM;
+       }
+       for (i = 0; i < brd->nasync; i++)
+               tty_port_init(&brd->PrinterPorts[i]);
+
+       ch = brd->channels[0];
+       for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+               struct device *classp;
+
+               classp = tty_port_register_device(&brd->SerialPorts[i],
+                                       brd->SerialDriver,
+                                       brd->firstminor + i, NULL);
+
+               dgap_create_tty_sysfs(&ch->ch_tun, classp);
+               ch->ch_tun.un_sysfs = classp;
+
+               classp = tty_port_register_device(&brd->PrinterPorts[i],
+                                       brd->PrintDriver,
+                                       brd->firstminor + i, NULL);
+
+               dgap_create_tty_sysfs(&ch->ch_pun, classp);
+               ch->ch_pun.un_sysfs = classp;
+       }
+       dgap_create_ports_sysfiles(brd);
+
+       return 0;
+}
+
+/*
+ * Copies the BIOS code from the user to the board,
+ * and starts the BIOS running.
+ */
+static void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len)
+{
+       uchar *addr;
+       uint offset;
+       int i;
+
+       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+               return;
+
+       addr = brd->re_map_membase;
+
+       /*
+        * clear POST area
+        */
+       for (i = 0; i < 16; i++)
+               writeb(0, addr + POSTAREA + i);
+
+       /*
+        * Download bios
+        */
+       offset = 0x1000;
+       memcpy_toio(addr + offset, ubios, len);
+
+       writel(0x0bf00401, addr);
+       writel(0, (addr + 4));
+
+       /* Clear the reset, and change states. */
+       writeb(FEPCLR, brd->re_map_port);
+}
+
+/*
+ * Checks to see if the BIOS completed running on the card.
+ */
+static void dgap_do_wait_for_bios(struct board_t *brd)
+{
+       uchar *addr;
+       u16 word;
+       u16 err1;
+       u16 err2;
+
+       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+               return;
+
+       addr = brd->re_map_membase;
+       word = readw(addr + POSTAREA);
+
+       /*
+        * It can take 5-6 seconds for a board to
+        * pass the bios self test and post results.
+        * Give it 10 seconds.
+        */
+       brd->wait_for_bios = 0;
+       while (brd->wait_for_bios < 1000) {
+               /* Check to see if BIOS thinks board is good. (GD). */
+               if (word == *(u16 *) "GD") {
+                       brd->state = FINISHED_BIOS_LOAD;
+                       return;
+               }
+               msleep_interruptible(10);
+               brd->wait_for_bios++;
+               word = readw(addr + POSTAREA);
+       }
+
+       /* Gave up on board after too long of time taken */
+       err1 = readw(addr + SEQUENCE);
+       err2 = readw(addr + ERROR);
+       pr_warn("dgap: %s failed diagnostics.  Error #(%x,%x).\n",
+               brd->name, err1, err2);
+       brd->state = BOARD_FAILED;
+       brd->dpastatus = BD_NOBIOS;
+}
+
+/*
+ * Copies the FEP code from the user to the board,
+ * and starts the FEP running.
+ */
+static void dgap_do_fep_load(struct board_t *brd, uchar *ufep, int len)
+{
+       uchar *addr;
+       uint offset;
+
+       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+               return;
+
+       addr = brd->re_map_membase;
+
+       /*
+        * Download FEP
+        */
+       offset = 0x1000;
+       memcpy_toio(addr + offset, ufep, len);
+
+       /*
+        * If board is a concentrator product, we need to give
+        * it its config string describing how the concentrators look.
+        */
+       if ((brd->type == PCX) || (brd->type == PEPC)) {
+               uchar string[100];
+               uchar *config, *xconfig;
+               int i = 0;
+
+               xconfig = dgap_create_config_string(brd, string);
+
+               /* Write string to board memory */
+               config = addr + CONFIG;
+               for (; i < CONFIGSIZE; i++, config++, xconfig++) {
+                       writeb(*xconfig, config);
+                       if ((*xconfig & 0xff) == 0xff)
+                               break;
+               }
+       }
+
+       writel(0xbfc01004, (addr + 0xc34));
+       writel(0x3, (addr + 0xc30));
+
+}
+
+/*
+ * Waits for the FEP to report thats its ready for us to use.
+ */
+static void dgap_do_wait_for_fep(struct board_t *brd)
+{
+       uchar *addr;
+       u16 word;
+       u16 err1;
+       u16 err2;
+
+       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+               return;
+
+       addr = brd->re_map_membase;
+       word = readw(addr + FEPSTAT);
+
+       /*
+        * It can take 2-3 seconds for the FEP to
+        * be up and running. Give it 5 secs.
+        */
+       brd->wait_for_fep = 0;
+       while (brd->wait_for_fep < 500) {
+               /* Check to see if FEP is up and running now. */
+               if (word == *(u16 *) "OS") {
+                       brd->state = FINISHED_FEP_LOAD;
+                       /*
+                        * Check to see if the board can support FEP5+ commands.
+                       */
+                       word = readw(addr + FEP5_PLUS);
+                       if (word == *(u16 *) "5A")
+                               brd->bd_flags |= BD_FEP5PLUS;
+
+                       return;
+               }
+               msleep_interruptible(10);
+               brd->wait_for_fep++;
+               word = readw(addr + FEPSTAT);
+       }
+
+       /* Gave up on board after too long of time taken */
+       err1 = readw(addr + SEQUENCE);
+       err2 = readw(addr + ERROR);
+       pr_warn("dgap: FEPOS for %s not functioning.  Error #(%x,%x).\n",
+               brd->name, err1, err2);
+       brd->state = BOARD_FAILED;
+       brd->dpastatus = BD_NOFEP;
+}
+
+/*
+ * Physically forces the FEP5 card to reset itself.
+ */
+static void dgap_do_reset_board(struct board_t *brd)
+{
+       uchar check;
+       u32 check1;
+       u32 check2;
+       int i = 0;
+
+       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) ||
+           !brd->re_map_membase || !brd->re_map_port)
+               return;
+
+       /* FEPRST does not vary among supported boards */
+       writeb(FEPRST, brd->re_map_port);
+
+       for (i = 0; i <= 1000; i++) {
+               check = readb(brd->re_map_port) & 0xe;
+               if (check == FEPRST)
+                       break;
+               udelay(10);
+
+       }
+       if (i > 1000) {
+               pr_warn("dgap: Board not resetting...  Failing board.\n");
+               brd->state = BOARD_FAILED;
+               brd->dpastatus = BD_NOFEP;
+               return;
+       }
+
+       /*
+        * Make sure there really is memory out there.
+        */
+       writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
+       writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
+       check1 = readl(brd->re_map_membase + LOWMEM);
+       check2 = readl(brd->re_map_membase + HIGHMEM);
+
+       if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
+               pr_warn("dgap: No memory at %p for board.\n",
+                       brd->re_map_membase);
+               brd->state = BOARD_FAILED;
+               brd->dpastatus = BD_NOFEP;
+               return;
+       }
+
+       if (brd->state != BOARD_FAILED)
+               brd->state = FINISHED_RESET;
+}
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+/*
+ * Sends a concentrator image into the FEP5 board.
+ */
+static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
+{
+       char *vaddr;
+       u16 offset = 0;
+       struct downld_t *to_dp;
+
+       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+               return;
+
+       vaddr = brd->re_map_membase;
+
+       offset = readw((u16 *) (vaddr + DOWNREQ));
+       to_dp = (struct downld_t *) (vaddr + (int) offset);
+       memcpy_toio(to_dp, uaddr, len);
+
+       /* Tell card we have data for it */
+       writew(0, vaddr + (DOWNREQ));
+
+       brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
+}
+#endif
+
+#define EXPANSION_ROM_SIZE     (64 * 1024)
+#define FEP5_ROM_MAGIC         (0xFEFFFFFF)
+
+static void dgap_get_vpd(struct board_t *brd)
+{
+       u32 magic;
+       u32 base_offset;
+       u16 rom_offset;
+       u16 vpd_offset;
+       u16 image_length;
+       u16 i;
+       uchar byte1;
+       uchar byte2;
+
+       /*
+        * Poke the magic number at the PCI Rom Address location.
+        * If VPD is supported, the value read from that address
+        * will be non-zero.
+        */
+       magic = FEP5_ROM_MAGIC;
+       pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+       pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
+
+       /* VPD not supported, bail */
+       if (!magic)
+               return;
+
+       /*
+        * To get to the OTPROM memory, we have to send the boards base
+        * address or'ed with 1 into the PCI Rom Address location.
+        */
+       magic = brd->membase | 0x01;
+       pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+       pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
+
+       byte1 = readb(brd->re_map_membase);
+       byte2 = readb(brd->re_map_membase + 1);
+
+       /*
+        * If the board correctly swapped to the OTPROM memory,
+        * the first 2 bytes (header) should be 0x55, 0xAA
+        */
+       if (byte1 == 0x55 && byte2 == 0xAA) {
+
+               base_offset = 0;
+
+               /*
+                * We have to run through all the OTPROM memory looking
+                * for the VPD offset.
+                */
+               while (base_offset <= EXPANSION_ROM_SIZE) {
+
+                       /*
+                        * Lots of magic numbers here.
+                        *
+                        * The VPD offset is located inside the ROM Data Structure.
+                        * We also have to remember the length of each
+                        * ROM Data Structure, so we can "hop" to the next
+                        * entry if the VPD isn't in the current
+                        * ROM Data Structure.
+                        */
+                       rom_offset = readw(brd->re_map_membase + base_offset + 0x18);
+                       image_length = readw(brd->re_map_membase + rom_offset + 0x10) * 512;
+                       vpd_offset = readw(brd->re_map_membase + rom_offset + 0x08);
+
+                       /* Found the VPD entry */
+                       if (vpd_offset)
+                               break;
+
+                       /* We didn't find a VPD entry, go to next ROM entry. */
+                       base_offset += image_length;
+
+                       byte1 = readb(brd->re_map_membase + base_offset);
+                       byte2 = readb(brd->re_map_membase + base_offset + 1);
+
+                       /*
+                        * If the new ROM offset doesn't have 0x55, 0xAA
+                        * as its header, we have run out of ROM.
+                        */
+                       if (byte1 != 0x55 || byte2 != 0xAA)
+                               break;
+               }
+
+               /*
+                * If we have a VPD offset, then mark the board
+                * as having a valid VPD, and copy VPDSIZE (512) bytes of
+                * that VPD to the buffer we have in our board structure.
+                */
+               if (vpd_offset) {
+                       brd->bd_flags |= BD_HAS_VPD;
+                       for (i = 0; i < VPDSIZE; i++)
+                               brd->vpd[i] = readb(brd->re_map_membase + vpd_offset + i);
+               }
+       }
+
+       /*
+        * We MUST poke the magic number at the PCI Rom Address location again.
+        * This makes the card report the regular board memory back to us,
+        * rather than the OTPROM memory.
+        */
+       magic = FEP5_ROM_MAGIC;
+       pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+}
+
+/*
+ * Our board poller function.
+ */
+static void dgap_poll_tasklet(unsigned long data)
+{
+       struct board_t *bd = (struct board_t *) data;
+       ulong  lock_flags;
+       ulong  lock_flags2;
+       char *vaddr;
+       u16 head, tail;
+
+       if (!bd || (bd->magic != DGAP_BOARD_MAGIC))
+               return;
+
+       if (bd->inhibit_poller)
+               return;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+
+       vaddr = bd->re_map_membase;
+
+       /*
+        * If board is ready, parse deeper to see if there is anything to do.
+        */
+       if (bd->state == BOARD_READY) {
+
+               struct ev_t *eaddr = NULL;
+
+               if (!bd->re_map_membase) {
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       return;
+               }
+               if (!bd->re_map_port) {
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       return;
+               }
+
+               if (!bd->nasync)
+                       goto out;
+
+               eaddr = (struct ev_t *) (vaddr + EVBUF);
+
+               /* Get our head and tail */
+               head = readw(&(eaddr->ev_head));
+               tail = readw(&(eaddr->ev_tail));
+
+               /*
+                * If there is an event pending. Go service it.
+                */
+               if (head != tail) {
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                       dgap_event(bd);
+                       DGAP_LOCK(bd->bd_lock, lock_flags);
+               }
+
+out:
+               /*
+                * If board is doing interrupts, ACK the interrupt.
+                */
+               if (bd && bd->intr_running)
+                       readb(bd->re_map_port + 2);
+
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return;
+       }
+
+       /* Our state machine to get the board up and running */
+
+       /* Reset board */
+       if (bd->state == NEED_RESET) {
+
+               /* Get VPD info */
+               dgap_get_vpd(bd);
+
+               dgap_do_reset_board(bd);
+       }
+
+       /* Move to next state */
+       if (bd->state == FINISHED_RESET)
+               bd->state = NEED_CONFIG;
+
+       if (bd->state == NEED_CONFIG) {
+               /*
+                * Match this board to a config the user created for us.
+                */
+               bd->bd_config = dgap_find_config(bd->type, bd->pci_bus, bd->pci_slot);
+
+               /*
+                * Because the 4 port Xr products share the same PCI ID
+                * as the 8 port Xr products, if we receive a NULL config
+                * back, and this is a PAPORT8 board, retry with a
+                * PAPORT4 attempt as well.
+                */
+               if (bd->type == PAPORT8 && !bd->bd_config)
+                       bd->bd_config = dgap_find_config(PAPORT4, bd->pci_bus, bd->pci_slot);
+
+               /*
+                * Register the ttys (if any) into the kernel.
+                */
+               if (bd->bd_config)
+                       bd->state = FINISHED_CONFIG;
+               else
+                       bd->state = CONFIG_NOT_FOUND;
+       }
+
+       /* Move to next state */
+       if (bd->state == FINISHED_CONFIG)
+               bd->state = NEED_DEVICE_CREATION;
+
+       /* Move to next state */
+       if (bd->state == NEED_DEVICE_CREATION) {
+               /*
+                * Signal downloader, its got some work to do.
+                */
+               DGAP_LOCK(dgap_dl_lock, lock_flags2);
+               if (dgap_dl_action != 1) {
+                       dgap_dl_action = 1;
+                       wake_up_interruptible(&dgap_dl_wait);
+               }
+               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+       }
+
+       /* Move to next state */
+       if (bd->state == FINISHED_DEVICE_CREATION)
+               bd->state = NEED_BIOS_LOAD;
+
+       /* Move to next state */
+       if (bd->state == NEED_BIOS_LOAD) {
+               /*
+                * Signal downloader, its got some work to do.
+                */
+               DGAP_LOCK(dgap_dl_lock, lock_flags2);
+               if (dgap_dl_action != 1) {
+                       dgap_dl_action = 1;
+                       wake_up_interruptible(&dgap_dl_wait);
+               }
+               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+       }
+
+       /* Wait for BIOS to test board... */
+       if (bd->state == WAIT_BIOS_LOAD)
+               dgap_do_wait_for_bios(bd);
+
+       /* Move to next state */
+       if (bd->state == FINISHED_BIOS_LOAD) {
+               bd->state = NEED_FEP_LOAD;
+
+               /*
+                * Signal downloader, its got some work to do.
+                */
+               DGAP_LOCK(dgap_dl_lock, lock_flags2);
+               if (dgap_dl_action != 1) {
+                       dgap_dl_action = 1;
+                       wake_up_interruptible(&dgap_dl_wait);
+               }
+               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+       }
+
+       /* Wait for FEP to load on board... */
+       if (bd->state == WAIT_FEP_LOAD)
+               dgap_do_wait_for_fep(bd);
+
+       /* Move to next state */
+       if (bd->state == FINISHED_FEP_LOAD) {
+
+               /*
+                * Do tty device initialization.
+                */
+               int rc = dgap_tty_init(bd);
+
+               if (rc < 0) {
+                       dgap_tty_uninit(bd);
+                       bd->state = BOARD_FAILED;
+                       bd->dpastatus = BD_NOFEP;
+               } else {
+                       bd->state = NEED_PROC_CREATION;
+
+                       /*
+                        * Signal downloader, its got some work to do.
+                        */
+                       DGAP_LOCK(dgap_dl_lock, lock_flags2);
+                       if (dgap_dl_action != 1) {
+                               dgap_dl_action = 1;
+                               wake_up_interruptible(&dgap_dl_wait);
+                       }
+                       DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+               }
+       }
+
+       /* Move to next state */
+       if (bd->state == FINISHED_PROC_CREATION) {
+
+               bd->state = BOARD_READY;
+               bd->dpastatus = BD_RUNNING;
+
+               /*
+                * If user requested the board to run in interrupt mode,
+                * go and set it up on the board.
+                */
+               if (bd->intr_used) {
+                       writew(1, (bd->re_map_membase + ENABLE_INTR));
+                       /*
+                        * Tell the board to poll the UARTS as fast as possible.
+                        */
+                       writew(FEPPOLL_MIN, (bd->re_map_membase + FEPPOLL));
+                       bd->intr_running = 1;
+               }
+
+               /* Wake up anyone waiting for board state to change to ready */
+               wake_up_interruptible(&bd->state_wait);
+       }
+
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdb - Sends a 2 byte command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              byte1   - Integer containing first byte to be sent.
+ *              byte2   - Integer containing second byte to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds)
+{
+       char            *vaddr = NULL;
+       struct cm_t     *cm_addr = NULL;
+       uint            count;
+       uint            n;
+       u16             head;
+       u16             tail;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       /*
+        * Check if board is still alive.
+        */
+       if (ch->ch_bd->state == BOARD_FAILED)
+               return;
+
+       /*
+        * Make sure the pointers are in range before
+        * writing to the FEP memory.
+        */
+       vaddr = ch->ch_bd->re_map_membase;
+
+       if (!vaddr)
+               return;
+
+       cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+       head = readw(&(cm_addr->cm_head));
+
+       /*
+        * Forget it if pointers out of range.
+        */
+       if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+               ch->ch_bd->state = BOARD_FAILED;
+               return;
+       }
+
+       /*
+        * Put the data in the circular command buffer.
+        */
+       writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
+       writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
+       writeb(byte1, (char *) (vaddr + head + CMDSTART + 2));
+       writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
+
+       head = (head + 4) & (CMDMAX - CMDSTART - 4);
+
+       writew(head, &(cm_addr->cm_head));
+
+       /*
+        * Wait if necessary before updating the head
+        * pointer to limit the number of outstanding
+        * commands to the FEP.   If the time spent waiting
+        * is outlandish, declare the FEP dead.
+        */
+       for (count = dgap_count ;;) {
+
+               head = readw(&(cm_addr->cm_head));
+               tail = readw(&(cm_addr->cm_tail));
+
+               n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+               if (n <= ncmds * sizeof(struct cm_t))
+                       break;
+
+               if (--count == 0) {
+                       ch->ch_bd->state = BOARD_FAILED;
+                       return;
+               }
+               udelay(10);
+       }
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdw - Sends a 1 word command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              word    - Integer containing word to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
+{
+       char            *vaddr = NULL;
+       struct cm_t     *cm_addr = NULL;
+       uint            count;
+       uint            n;
+       u16             head;
+       u16             tail;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       /*
+        * Check if board is still alive.
+        */
+       if (ch->ch_bd->state == BOARD_FAILED)
+               return;
+
+       /*
+        * Make sure the pointers are in range before
+        * writing to the FEP memory.
+        */
+       vaddr = ch->ch_bd->re_map_membase;
+       if (!vaddr)
+               return;
+
+       cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+       head = readw(&(cm_addr->cm_head));
+
+       /*
+        * Forget it if pointers out of range.
+        */
+       if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+               ch->ch_bd->state = BOARD_FAILED;
+               return;
+       }
+
+       /*
+        * Put the data in the circular command buffer.
+        */
+       writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
+       writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
+       writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
+
+       head = (head + 4) & (CMDMAX - CMDSTART - 4);
+
+       writew(head, &(cm_addr->cm_head));
+
+       /*
+        * Wait if necessary before updating the head
+        * pointer to limit the number of outstanding
+        * commands to the FEP.   If the time spent waiting
+        * is outlandish, declare the FEP dead.
+        */
+       for (count = dgap_count ;;) {
+
+               head = readw(&(cm_addr->cm_head));
+               tail = readw(&(cm_addr->cm_tail));
+
+               n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+               if (n <= ncmds * sizeof(struct cm_t))
+                       break;
+
+               if (--count == 0) {
+                       ch->ch_bd->state = BOARD_FAILED;
+                       return;
+               }
+               udelay(10);
+       }
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdw_ext - Sends a extended word command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              word    - Integer containing word to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
+{
+       char            *vaddr = NULL;
+       struct cm_t     *cm_addr = NULL;
+       uint            count;
+       uint            n;
+       u16             head;
+       u16             tail;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       /*
+        * Check if board is still alive.
+        */
+       if (ch->ch_bd->state == BOARD_FAILED)
+               return;
+
+       /*
+        * Make sure the pointers are in range before
+        * writing to the FEP memory.
+        */
+       vaddr = ch->ch_bd->re_map_membase;
+       if (!vaddr)
+               return;
+
+       cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+       head = readw(&(cm_addr->cm_head));
+
+       /*
+        * Forget it if pointers out of range.
+        */
+       if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+               ch->ch_bd->state = BOARD_FAILED;
+               return;
+       }
+
+       /*
+        * Put the data in the circular command buffer.
+        */
+
+       /* Write an FF to tell the FEP that we want an extended command */
+       writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
+
+       writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
+       writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
+
+       /*
+        * If the second part of the command won't fit,
+        * put it at the beginning of the circular buffer.
+        */
+       if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03)))
+               writew((u16) word, (char *) (vaddr + CMDSTART));
+       else
+               writew((u16) word, (char *) (vaddr + head + CMDSTART + 4));
+
+       head = (head + 8) & (CMDMAX - CMDSTART - 4);
+
+       writew(head, &(cm_addr->cm_head));
+
+       /*
+        * Wait if necessary before updating the head
+        * pointer to limit the number of outstanding
+        * commands to the FEP.   If the time spent waiting
+        * is outlandish, declare the FEP dead.
+        */
+       for (count = dgap_count ;;) {
+
+               head = readw(&(cm_addr->cm_head));
+               tail = readw(&(cm_addr->cm_tail));
+
+               n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+               if (n <= ncmds * sizeof(struct cm_t))
+                       break;
+
+               if (--count == 0) {
+                       ch->ch_bd->state = BOARD_FAILED;
+                       return;
+               }
+               udelay(10);
+       }
+}
+
+/*=======================================================================
+ *
+ *      dgap_wmove - Write data to FEP buffer.
+ *
+ *              ch      - Pointer to channel structure.
+ *              buf     - Poiter to characters to be moved.
+ *              cnt     - Number of characters to move.
+ *
+ *=======================================================================*/
+static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
+{
+       int    n;
+       char   *taddr;
+       struct bs_t    *bs;
+       u16    head;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       /*
+        * Check parameters.
+        */
+       bs   = ch->ch_bs;
+       head = readw(&(bs->tx_head));
+
+       /*
+        * If pointers are out of range, just return.
+        */
+       if ((cnt > ch->ch_tsize) ||
+           (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize)
+               return;
+
+       /*
+        * If the write wraps over the top of the circular buffer,
+        * move the portion up to the wrap point, and reset the
+        * pointers to the bottom.
+        */
+       n = ch->ch_tstart + ch->ch_tsize - head;
+
+       if (cnt >= n) {
+               cnt -= n;
+               taddr = ch->ch_taddr + head;
+               memcpy_toio(taddr, buf, n);
+               head = ch->ch_tstart;
+               buf += n;
+       }
+
+       /*
+        * Move rest of data.
+        */
+       taddr = ch->ch_taddr + head;
+       n = cnt;
+       memcpy_toio(taddr, buf, n);
+       head += cnt;
+
+       writew(head, &(bs->tx_head));
+}
+
+/*
+ * Retrives the current custom baud rate from FEP memory,
+ * and returns it back to the user.
+ * Returns 0 on error.
+ */
+static uint dgap_get_custom_baud(struct channel_t *ch)
+{
+       uchar *vaddr;
+       ulong offset = 0;
+       uint value = 0;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+
+       if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+
+       if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
+               return 0;
+
+       vaddr = ch->ch_bd->re_map_membase;
+
+       if (!vaddr)
+               return 0;
+
+       /*
+        * Go get from fep mem, what the fep
+        * believes the custom baud rate is.
+        */
+       offset = ((((*(unsigned short *)(vaddr + ECS_SEG)) << 4) +
+               (ch->ch_portnum * 0x28) + LINE_SPEED));
+
+       value = readw(vaddr + offset);
+       return value;
+}
+
+/*
+ * Calls the firmware to reset this channel.
+ */
+static void dgap_firmware_reset_port(struct channel_t *ch)
+{
+       dgap_cmdb(ch, CHRESET, 0, 0, 0);
+
+       /*
+        * Now that the channel is reset, we need to make sure
+        * all the current settings get reapplied to the port
+        * in the firmware.
+        *
+        * So we will set the driver's cache of firmware
+        * settings all to 0, and then call param.
+        */
+       ch->ch_fepiflag = 0;
+       ch->ch_fepcflag = 0;
+       ch->ch_fepoflag = 0;
+       ch->ch_fepstartc = 0;
+       ch->ch_fepstopc = 0;
+       ch->ch_fepastartc = 0;
+       ch->ch_fepastopc = 0;
+       ch->ch_mostat = 0;
+       ch->ch_hflow = 0;
+}
+
+/*=======================================================================
+ *
+ *      dgap_param - Set Digi parameters.
+ *
+ *              struct tty_struct *     - TTY for port.
+ *
+ *=======================================================================*/
+static int dgap_param(struct tty_struct *tty)
+{
+       struct ktermios *ts;
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct bs_t   *bs;
+       struct un_t   *un;
+       u16     head;
+       u16     cflag;
+       u16     iflag;
+       uchar   mval;
+       uchar   hflow;
+
+       if (!tty || tty->magic != TTY_MAGIC)
+               return -ENXIO;
+
+       un = (struct un_t *) tty->driver_data;
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return -ENXIO;
+
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return -ENXIO;
+
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return -ENXIO;
+
+       bs = ch->ch_bs;
+       if (!bs)
+               return -ENXIO;
+
+       ts = &tty->termios;
+
+       /*
+        * If baud rate is zero, flush queues, and set mval to drop DTR.
+        */
+       if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+
+               /* flush rx */
+               head = readw(&(ch->ch_bs->rx_head));
+               writew(head, &(ch->ch_bs->rx_tail));
+
+               /* flush tx */
+               head = readw(&(ch->ch_bs->tx_head));
+               writew(head, &(ch->ch_bs->tx_tail));
+
+               ch->ch_flags |= (CH_BAUD0);
+
+               /* Drop RTS and DTR */
+               ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
+               mval = D_DTR(ch) | D_RTS(ch);
+               ch->ch_baud_info = 0;
+
+       } else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
+               /*
+                * Tell the fep to do the command
+                */
+
+               dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
+
+               /*
+                * Now go get from fep mem, what the fep
+                * believes the custom baud rate is.
+                */
+               ch->ch_baud_info = ch->ch_custom_speed = dgap_get_custom_baud(ch);
+
+               /* Handle transition from B0 */
+               if (ch->ch_flags & CH_BAUD0) {
+                       ch->ch_flags &= ~(CH_BAUD0);
+                       ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+               }
+               mval = D_DTR(ch) | D_RTS(ch);
+
+       } else {
+               /*
+                * Set baud rate, character size, and parity.
+                */
+
+
+               int iindex = 0;
+               int jindex = 0;
+               int baud = 0;
+
+               ulong bauds[4][16] = {
+                       { /* slowbaud */
+                               0,      50,     75,     110,
+                               134,    150,    200,    300,
+                               600,    1200,   1800,   2400,
+                               4800,   9600,   19200,  38400 },
+                       { /* slowbaud & CBAUDEX */
+                               0,      57600,  115200, 230400,
+                               460800, 150,    200,    921600,
+                               600,    1200,   1800,   2400,
+                               4800,   9600,   19200,  38400 },
+                       { /* fastbaud */
+                               0,      57600,  76800,  115200,
+                               14400,  57600,  230400, 76800,
+                               115200, 230400, 28800,  460800,
+                               921600, 9600,   19200,  38400 },
+                       { /* fastbaud & CBAUDEX */
+                               0,      57600,  115200, 230400,
+                               460800, 150,    200,    921600,
+                               600,    1200,   1800,   2400,
+                               4800,   9600,   19200,  38400 }
+               };
+
+               /* Only use the TXPrint baud rate if the terminal unit is NOT open */
+               if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGAP_PRINT))
+                       baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
+               else
+                       baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
+
+               if (ch->ch_c_cflag & CBAUDEX)
+                       iindex = 1;
+
+               if (ch->ch_digi.digi_flags & DIGI_FAST)
+                       iindex += 2;
+
+               jindex = baud;
+
+               if ((iindex >= 0) && (iindex < 4) &&
+                   (jindex >= 0) && (jindex < 16))
+                       baud = bauds[iindex][jindex];
+               else
+                       baud = 0;
+
+               if (baud == 0)
+                       baud = 9600;
+
+               ch->ch_baud_info = baud;
+
+               /*
+                * CBAUD has bit position 0x1000 set these days to indicate Linux
+                * baud rate remap.
+                * We use a different bit assignment for high speed.  Clear this
+                * bit out while grabbing the parts of "cflag" we want.
+                */
+               cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
+
+               /*
+                * HUPCL bit is used by FEP to indicate fast baud
+                * table is to be used.
+                */
+               if ((ch->ch_digi.digi_flags & DIGI_FAST) || (ch->ch_c_cflag & CBAUDEX))
+                       cflag |= HUPCL;
+
+               if ((ch->ch_c_cflag & CBAUDEX) && !(ch->ch_digi.digi_flags & DIGI_FAST)) {
+               /*
+                * The below code is trying to guarantee that only baud rates
+                * 115200, 230400, 460800, 921600 are remapped.  We use exclusive or
+                * because the various baud rates share common bit positions
+                * and therefore can't be tested for easily.
+                */
+                       tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
+                       int baudpart = 0;
+
+                       /* Map high speed requests to index into FEP's baud table */
+                       switch (tcflag) {
+                       case B57600:
+                               baudpart = 1;
+                               break;
+#ifdef B76800
+                       case B76800:
+                               baudpart = 2;
+                               break;
+#endif
+                       case B115200:
+                               baudpart = 3;
+                               break;
+                       case B230400:
+                               baudpart = 9;
+                               break;
+                       case B460800:
+                               baudpart = 11;
+                               break;
+#ifdef B921600
+                       case B921600:
+                               baudpart = 12;
+                               break;
+#endif
+                       default:
+                               baudpart = 0;
+                       }
+
+                       if (baudpart)
+                               cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
+               }
+
+               cflag &= 0xffff;
+
+               if (cflag != ch->ch_fepcflag) {
+                       ch->ch_fepcflag = (u16) (cflag & 0xffff);
+
+                       /* Okay to have channel and board locks held calling this */
+                       dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
+               }
+
+               /* Handle transition from B0 */
+               if (ch->ch_flags & CH_BAUD0) {
+                       ch->ch_flags &= ~(CH_BAUD0);
+                       ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+               }
+               mval = D_DTR(ch) | D_RTS(ch);
+       }
+
+       /*
+        * Get input flags.
+        */
+       iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON | IXANY | IXOFF);
+
+       if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) {
+               iflag &= ~(IXON | IXOFF);
+               ch->ch_c_iflag &= ~(IXON | IXOFF);
+       }
+
+       /*
+        * Only the IBM Xr card can switch between
+        * 232 and 422 modes on the fly
+        */
+       if (bd->device == PCI_DEVICE_XR_IBM_DID) {
+               if (ch->ch_digi.digi_flags & DIGI_422)
+                       dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
+               else
+                       dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
+       }
+
+       if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
+               iflag |= IALTPIN;
+
+       if (iflag != ch->ch_fepiflag) {
+               ch->ch_fepiflag = iflag;
+
+               /* Okay to have channel and board locks held calling this */
+               dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
+       }
+
+       /*
+        * Select hardware handshaking.
+        */
+       hflow = 0;
+
+       if (ch->ch_c_cflag & CRTSCTS)
+               hflow |= (D_RTS(ch) | D_CTS(ch));
+       if (ch->ch_digi.digi_flags & RTSPACE)
+               hflow |= D_RTS(ch);
+       if (ch->ch_digi.digi_flags & DTRPACE)
+               hflow |= D_DTR(ch);
+       if (ch->ch_digi.digi_flags & CTSPACE)
+               hflow |= D_CTS(ch);
+       if (ch->ch_digi.digi_flags & DSRPACE)
+               hflow |= D_DSR(ch);
+       if (ch->ch_digi.digi_flags & DCDPACE)
+               hflow |= D_CD(ch);
+
+       if (hflow != ch->ch_hflow) {
+               ch->ch_hflow = hflow;
+
+               /* Okay to have channel and board locks held calling this */
+               dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
+       }
+
+
+       /*
+        * Set RTS and/or DTR Toggle if needed, but only if product is FEP5+ based.
+        */
+       if (bd->bd_flags & BD_FEP5PLUS) {
+               u16 hflow2 = 0;
+               if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
+                       hflow2 |= (D_RTS(ch));
+               if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)
+                       hflow2 |= (D_DTR(ch));
+
+               dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
+       }
+
+       /*
+        * Set modem control lines.
+        */
+
+       mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
+
+       if (ch->ch_mostat ^ mval) {
+               ch->ch_mostat = mval;
+
+               /* Okay to have channel and board locks held calling this */
+               dgap_cmdb(ch, SMODEM, (uchar) mval, D_RTS(ch)|D_DTR(ch), 0);
+       }
+
+       /*
+        * Read modem signals, and then call carrier function.
+        */
+       ch->ch_mistat = readb(&(bs->m_stat));
+       dgap_carrier(ch);
+
+       /*
+        * Set the start and stop characters.
+        */
+       if (ch->ch_startc != ch->ch_fepstartc || ch->ch_stopc != ch->ch_fepstopc) {
+               ch->ch_fepstartc = ch->ch_startc;
+               ch->ch_fepstopc =  ch->ch_stopc;
+
+               /* Okay to have channel and board locks held calling this */
+               dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
+       }
+
+       /*
+        * Set the Auxiliary start and stop characters.
+        */
+       if (ch->ch_astartc != ch->ch_fepastartc || ch->ch_astopc != ch->ch_fepastopc) {
+               ch->ch_fepastartc = ch->ch_astartc;
+               ch->ch_fepastopc = ch->ch_astopc;
+
+               /* Okay to have channel and board locks held calling this */
+               dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
+       }
+
+       return 0;
+}
+
+/*
+ * dgap_parity_scan()
+ *
+ * Convert the FEP5 way of reporting parity errors and breaks into
+ * the Linux line discipline way.
+ */
+static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len)
+{
+       int l = *len;
+       int count = 0;
+       unsigned char *in, *cout, *fout;
+       unsigned char c;
+
+       in = cbuf;
+       cout = cbuf;
+       fout = fbuf;
+
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return;
+
+       while (l--) {
+               c = *in++;
+               switch (ch->pscan_state) {
+               default:
+                       /* reset to sanity and fall through */
+                       ch->pscan_state = 0;
+
+               case 0:
+                       /* No FF seen yet */
+                       if (c == (unsigned char) '\377')
+                               /* delete this character from stream */
+                               ch->pscan_state = 1;
+                       else {
+                               *cout++ = c;
+                               *fout++ = TTY_NORMAL;
+                               count += 1;
+                       }
+                       break;
+
+               case 1:
+                       /* first FF seen */
+                       if (c == (unsigned char) '\377') {
+                               /* doubled ff, transform to single ff */
+                               *cout++ = c;
+                               *fout++ = TTY_NORMAL;
+                               count += 1;
+                               ch->pscan_state = 0;
+                       } else {
+                               /* save value examination in next state */
+                               ch->pscan_savechar = c;
+                               ch->pscan_state = 2;
+                       }
+                       break;
+
+               case 2:
+                       /* third character of ff sequence */
+
+                       *cout++ = c;
+
+                       if (ch->pscan_savechar == 0x0) {
+
+                               if (c == 0x0) {
+                                       ch->ch_err_break++;
+                                       *fout++ = TTY_BREAK;
+                               } else {
+                                       ch->ch_err_parity++;
+                                       *fout++ = TTY_PARITY;
+                               }
+                       }
+
+                       count += 1;
+                       ch->pscan_state = 0;
+               }
+       }
+       *len = count;
+}
+
+/*=======================================================================
+ *
+ *      dgap_event - FEP to host event processing routine.
+ *
+ *              bd     - Board of current event.
+ *
+ *=======================================================================*/
+static int dgap_event(struct board_t *bd)
+{
+       struct channel_t *ch;
+       ulong           lock_flags;
+       ulong           lock_flags2;
+       struct bs_t     *bs;
+       uchar           *event;
+       uchar           *vaddr = NULL;
+       struct ev_t     *eaddr = NULL;
+       uint            head;
+       uint            tail;
+       int             port;
+       int             reason;
+       int             modem;
+       int             b1;
+
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return -ENXIO;
+
+       DGAP_LOCK(bd->bd_lock, lock_flags);
+
+       vaddr = bd->re_map_membase;
+
+       if (!vaddr) {
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       eaddr = (struct ev_t *) (vaddr + EVBUF);
+
+       /* Get our head and tail */
+       head = readw(&(eaddr->ev_head));
+       tail = readw(&(eaddr->ev_tail));
+
+       /*
+        * Forget it if pointers out of range.
+        */
+
+       if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
+           (head | tail) & 03) {
+               /* Let go of board lock */
+               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+               return -ENXIO;
+       }
+
+       /*
+        * Loop to process all the events in the buffer.
+        */
+       while (tail != head) {
+
+               /*
+                * Get interrupt information.
+                */
+
+               event = bd->re_map_membase + tail + EVSTART;
+
+               port   = event[0];
+               reason = event[1];
+               modem  = event[2];
+               b1     = event[3];
+
+               /*
+                * Make sure the interrupt is valid.
+                */
+               if (port >= bd->nasync)
+                       goto next;
+
+               if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA)))
+                       goto next;
+
+               ch = bd->channels[port];
+
+               if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+                       goto next;
+
+               /*
+                * If we have made it here, the event was valid.
+                * Lock down the channel.
+                */
+               DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+               bs = ch->ch_bs;
+
+               if (!bs) {
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       goto next;
+               }
+
+               /*
+                * Process received data.
+                */
+               if (reason & IFDATA) {
+
+                       /*
+                        * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
+                        * input could send some data to ld, which in turn
+                        * could do a callback to one of our other functions.
+                        */
+                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+                       dgap_input(ch);
+
+                       DGAP_LOCK(bd->bd_lock, lock_flags);
+                       DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+                       if (ch->ch_flags & CH_RACTIVE)
+                               ch->ch_flags |= CH_RENABLE;
+                       else
+                               writeb(1, &(bs->idata));
+
+                       if (ch->ch_flags & CH_RWAIT) {
+                               ch->ch_flags &= ~CH_RWAIT;
+
+                               wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+                       }
+               }
+
+               /*
+                * Process Modem change signals.
+                */
+               if (reason & IFMODEM) {
+                       ch->ch_mistat = modem;
+                       dgap_carrier(ch);
+               }
+
+               /*
+                * Process break.
+                */
+               if (reason & IFBREAK) {
+
+                       if (ch->ch_tun.un_tty) {
+                               /* A break has been indicated */
+                               ch->ch_err_break++;
+                               tty_buffer_request_room(ch->ch_tun.un_tty->port, 1);
+                               tty_insert_flip_char(ch->ch_tun.un_tty->port, 0, TTY_BREAK);
+                               tty_flip_buffer_push(ch->ch_tun.un_tty->port);
+                       }
+               }
+
+               /*
+                * Process Transmit low.
+                */
+               if (reason & IFTLW) {
+
+                       if (ch->ch_tun.un_flags & UN_LOW) {
+                               ch->ch_tun.un_flags &= ~UN_LOW;
+
+                               if (ch->ch_tun.un_flags & UN_ISOPEN) {
+                                       if ((ch->ch_tun.un_tty->flags &
+                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
+                                               ch->ch_tun.un_tty->ldisc->ops->write_wakeup) {
+                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                                               (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+                                               DGAP_LOCK(bd->bd_lock, lock_flags);
+                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
+                                       }
+                                       wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+                                       wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+                               }
+                       }
+
+                       if (ch->ch_pun.un_flags & UN_LOW) {
+                               ch->ch_pun.un_flags &= ~UN_LOW;
+                               if (ch->ch_pun.un_flags & UN_ISOPEN) {
+                                       if ((ch->ch_pun.un_tty->flags &
+                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
+                                               ch->ch_pun.un_tty->ldisc->ops->write_wakeup) {
+                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                                               (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+                                               DGAP_LOCK(bd->bd_lock, lock_flags);
+                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
+                                       }
+                                       wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+                                       wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+                               }
+                       }
+
+                       if (ch->ch_flags & CH_WLOW) {
+                               ch->ch_flags &= ~CH_WLOW;
+                               wake_up_interruptible(&ch->ch_flags_wait);
+                       }
+               }
+
+               /*
+                * Process Transmit empty.
+                */
+               if (reason & IFTEM) {
+                       if (ch->ch_tun.un_flags & UN_EMPTY) {
+                               ch->ch_tun.un_flags &= ~UN_EMPTY;
+                               if (ch->ch_tun.un_flags & UN_ISOPEN) {
+                                       if ((ch->ch_tun.un_tty->flags &
+                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
+                                               ch->ch_tun.un_tty->ldisc->ops->write_wakeup) {
+                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+                                               (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+                                               DGAP_LOCK(bd->bd_lock, lock_flags);
+                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
+                                       }
+                                       wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+                                       wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+                               }
+                       }
+
+                       if (ch->ch_pun.un_flags & UN_EMPTY) {
+                               ch->ch_pun.un_flags &= ~UN_EMPTY;
+                               if (ch->ch_pun.un_flags & UN_ISOPEN) {
+                                       if ((ch->ch_pun.un_tty->flags &
+                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
+                                               ch->ch_pun.un_tty->ldisc->ops->write_wakeup) {
+                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
+                                               (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+                                               DGAP_LOCK(bd->bd_lock, lock_flags);
+                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
+                                       }
+                                       wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+                                       wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+                               }
+                       }
+
+
+                       if (ch->ch_flags & CH_WEMPTY) {
+                               ch->ch_flags &= ~CH_WEMPTY;
+                               wake_up_interruptible(&ch->ch_flags_wait);
+                       }
+               }
+
+               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+
+next:
+               tail = (tail + 4) & (EVMAX - EVSTART - 4);
+       }
+
+       writew(tail, &(eaddr->ev_tail));
+       DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+       return 0;
+}
+
+static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
+}
+static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
+
+
+static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
+}
+static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
+
+
+static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
+}
+static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
+
+
+static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
+}
+static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
+
+
+static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
+}
+static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
+
+static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
+}
+
+static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+       sscanf(buf, "0x%x\n", &dgap_rawreadok);
+       return count;
+}
+static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
+
+
+static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
+}
+
+static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+       sscanf(buf, "%d\n", &dgap_poll_tick);
+       return count;
+}
+static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
+
+static void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
+{
+       int rc = 0;
+       struct device_driver *driverfs = &dgap_driver->driver;
+
+       rc |= driver_create_file(driverfs, &driver_attr_version);
+       rc |= driver_create_file(driverfs, &driver_attr_boards);
+       rc |= driver_create_file(driverfs, &driver_attr_maxboards);
+       rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
+       rc |= driver_create_file(driverfs, &driver_attr_pollrate);
+       rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
+       rc |= driver_create_file(driverfs, &driver_attr_state);
+       if (rc)
+               printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
+}
+
+static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
+{
+       struct device_driver *driverfs = &dgap_driver->driver;
+       driver_remove_file(driverfs, &driver_attr_version);
+       driver_remove_file(driverfs, &driver_attr_boards);
+       driver_remove_file(driverfs, &driver_attr_maxboards);
+       driver_remove_file(driverfs, &driver_attr_rawreadok);
+       driver_remove_file(driverfs, &driver_attr_pollrate);
+       driver_remove_file(driverfs, &driver_attr_pollcounter);
+       driver_remove_file(driverfs, &driver_attr_state);
+}
+
+#define DGAP_VERIFY_BOARD(p, bd)                       \
+       if (!p)                                         \
+               return 0;                               \
+                                                       \
+       bd = dev_get_drvdata(p);                        \
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)       \
+               return 0;                               \
+       if (bd->state != BOARD_READY)                   \
+               return 0;                               \
+
+static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++) {
+               count += snprintf(buf + count, PAGE_SIZE - count,
+                       "%d %s\n", bd->channels[i]->ch_portnum,
+                       bd->channels[i]->ch_open_count ? "Open" : "Closed");
+       }
+       return count;
+}
+static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
+
+static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++) {
+               count +=  snprintf(buf + count, PAGE_SIZE - count,
+                       "%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
+       }
+       return count;
+}
+static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
+
+static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++) {
+               if (bd->channels[i]->ch_open_count)
+                       count += snprintf(buf + count, PAGE_SIZE - count,
+                               "%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
+                               (bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+                               (bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+                               (bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+                               (bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+                               (bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+                               (bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+               else
+                       count += snprintf(buf + count, PAGE_SIZE - count,
+                               "%d\n", bd->channels[i]->ch_portnum);
+       }
+       return count;
+}
+static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
+
+static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
+       return count;
+}
+static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
+
+static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
+       return count;
+}
+static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
+
+static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
+       return count;
+}
+static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
+
+static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
+       return count;
+}
+static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
+
+static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
+       return count;
+}
+static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
+
+static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
+       return count;
+}
+static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
+
+static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       int count = 0;
+       int i = 0;
+
+       DGAP_VERIFY_BOARD(p, bd);
+
+       for (i = 0; i < bd->nasync; i++)
+               count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
+       return count;
+}
+static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
+
+/* this function creates the sys files that will export each signal status
+ * to sysfs each value will be put in a separate filename
+ */
+static void dgap_create_ports_sysfiles(struct board_t *bd)
+{
+       int rc = 0;
+
+       dev_set_drvdata(&bd->pdev->dev, bd);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+       if (rc)
+               printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
+}
+
+/* removes all the sys files created for that port */
+static void dgap_remove_ports_sysfiles(struct board_t *bd)
+{
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+}
+
+static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
+}
+static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
+
+static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
+}
+static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
+
+static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       if (ch->ch_open_count) {
+               return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
+                       (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+                       (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+                       (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+                       (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+                       (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+                       (ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+       }
+       return 0;
+}
+static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
+
+static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
+}
+static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
+
+static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
+}
+static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
+
+static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
+}
+static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
+
+static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
+}
+static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
+
+static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
+}
+static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
+
+static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
+}
+static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
+
+static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
+}
+static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
+
+static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct board_t *bd;
+       struct channel_t *ch;
+       struct un_t *un;
+       int     cn;
+       int     bn;
+       struct cnode *cptr = NULL;
+       int found = FALSE;
+       int ncount = 0;
+       int starto = 0;
+       int i = 0;
+
+       if (!d)
+               return 0;
+       un = dev_get_drvdata(d);
+       if (!un || un->magic != DGAP_UNIT_MAGIC)
+               return 0;
+       ch = un->un_ch;
+       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+               return 0;
+       bd = ch->ch_bd;
+       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+               return 0;
+       if (bd->state != BOARD_READY)
+               return 0;
+
+       bn = bd->boardnum;
+       cn = ch->ch_portnum;
+
+       for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
+
+               if ((cptr->type == BNODE) &&
+                   ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
+                    (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
+                    (cptr->u.board.type == PAPORT8))) {
+
+                               found = TRUE;
+                               if (cptr->u.board.v_start)
+                                       starto = cptr->u.board.start;
+                               else
+                                       starto = 1;
+               }
+
+               if (cptr->type == TNODE && found == TRUE) {
+                       char *ptr1;
+                       if (strstr(cptr->u.ttyname, "tty")) {
+                               ptr1 = cptr->u.ttyname;
+                               ptr1 += 3;
+                       } else
+                               ptr1 = cptr->u.ttyname;
+
+                       for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
+                               if (cn == i)
+                                       return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+                                               (un->un_type == DGAP_PRINT) ? "pr" : "tty",
+                                               ptr1, i + starto);
+                       }
+               }
+
+               if (cptr->type == CNODE) {
+
+                       for (i = 0; i < cptr->u.conc.nport; i++) {
+                               if (cn == (i + ncount))
+
+                                       return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+                                               (un->un_type == DGAP_PRINT) ? "pr" : "tty",
+                                               cptr->u.conc.id,
+                                               i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
+                       }
+
+                       ncount += cptr->u.conc.nport;
+               }
+
+               if (cptr->type == MNODE) {
+
+                       for (i = 0; i < cptr->u.module.nport; i++) {
+                               if (cn == (i + ncount))
+                                       return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+                                               (un->un_type == DGAP_PRINT) ? "pr" : "tty",
+                                               cptr->u.module.id,
+                                               i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
+                       }
+
+                       ncount += cptr->u.module.nport;
+
+               }
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
+               (un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
+
+}
+static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
+
+static struct attribute *dgap_sysfs_tty_entries[] = {
+       &dev_attr_state.attr,
+       &dev_attr_baud.attr,
+       &dev_attr_msignals.attr,
+       &dev_attr_iflag.attr,
+       &dev_attr_cflag.attr,
+       &dev_attr_oflag.attr,
+       &dev_attr_lflag.attr,
+       &dev_attr_digi_flag.attr,
+       &dev_attr_rxcount.attr,
+       &dev_attr_txcount.attr,
+       &dev_attr_custom_name.attr,
+       NULL
+};
+
+static struct attribute_group dgap_tty_attribute_group = {
+       .name = NULL,
+       .attrs = dgap_sysfs_tty_entries,
+};
+
+static void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
+{
+       int ret;
+
+       ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
+       if (ret) {
+               printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
+               sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
+               return;
+       }
+
+       dev_set_drvdata(c, un);
+
+}
+
+static void dgap_remove_tty_sysfs(struct device *c)
+{
+       sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
+}
+
+/*
+ * Parse a configuration file read into memory as a string.
+ */
+static int     dgap_parsefile(char **in, int Remove)
+{
+       struct cnode *p, *brd, *line, *conc;
+       int     rc;
+       char    *s = NULL, *s2 = NULL;
+       int     linecnt = 0;
+
+       p = &dgap_head;
+       brd = line = conc = NULL;
+
+       /* perhaps we are adding to an existing list? */
+       while (p->next != NULL)
+               p = p->next;
+
+       /* file must start with a BEGIN */
+       while ((rc = dgap_gettok(in, p)) != BEGIN) {
+               if (rc == 0) {
+                       dgap_err("unexpected EOF");
+                       return -1;
+               }
+       }
+
+       for (; ;) {
+               rc = dgap_gettok(in, p);
+               if (rc == 0) {
+                       dgap_err("unexpected EOF");
+                       return -1;
+               }
+
+               switch (rc) {
+               case 0:
+                       dgap_err("unexpected end of file");
+                       return -1;
+
+               case BEGIN:     /* should only be 1 begin */
+                       dgap_err("unexpected config_begin\n");
+                       return -1;
+
+               case END:
+                       return 0;
+
+               case BOARD:     /* board info */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(BNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+
+                       p->u.board.status = dgap_savestring("No");
+                       line = conc = NULL;
+                       brd = p;
+                       linecnt = -1;
+                       break;
+
+               case APORT2_920P:       /* AccelePort_4 */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected Digi_2r_920 string");
+                               return -1;
+                       }
+                       p->u.board.type = APORT2_920P;
+                       p->u.board.v_type = 1;
+                       break;
+
+               case APORT4_920P:       /* AccelePort_4 */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected Digi_4r_920 string");
+                               return -1;
+                       }
+                       p->u.board.type = APORT4_920P;
+                       p->u.board.v_type = 1;
+                       break;
+
+               case APORT8_920P:       /* AccelePort_8 */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected Digi_8r_920 string");
+                               return -1;
+                       }
+                       p->u.board.type = APORT8_920P;
+                       p->u.board.v_type = 1;
+                       break;
+
+               case PAPORT4:   /* AccelePort_4 PCI */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected Digi_4r(PCI) string");
+                               return -1;
+                       }
+                       p->u.board.type = PAPORT4;
+                       p->u.board.v_type = 1;
+                       break;
+
+               case PAPORT8:   /* AccelePort_8 PCI */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected Digi_8r string");
+                               return -1;
+                       }
+                       p->u.board.type = PAPORT8;
+                       p->u.board.v_type = 1;
+                       break;
+
+               case PCX:       /* PCI C/X */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected Digi_C/X_(PCI) string");
+                               return -1;
+                       }
+                       p->u.board.type = PCX;
+                       p->u.board.v_type = 1;
+                       p->u.board.conc1 = 0;
+                       p->u.board.conc2 = 0;
+                       p->u.board.module1 = 0;
+                       p->u.board.module2 = 0;
+                       break;
+
+               case PEPC:      /* PCI EPC/X */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
+                               return -1;
+                       }
+                       p->u.board.type = PEPC;
+                       p->u.board.v_type = 1;
+                       p->u.board.conc1 = 0;
+                       p->u.board.conc2 = 0;
+                       p->u.board.module1 = 0;
+                       p->u.board.module2 = 0;
+                       break;
+
+               case PPCM:      /* PCI/Xem */
+                       if (p->type != BNODE) {
+                               dgap_err("unexpected PCI/Xem string");
+                               return -1;
+                       }
+                       p->u.board.type = PPCM;
+                       p->u.board.v_type = 1;
+                       p->u.board.conc1 = 0;
+                       p->u.board.conc2 = 0;
+                       break;
+
+               case IO:        /* i/o port */
+                       if (p->type != BNODE) {
+                               dgap_err("IO port only vaild for boards");
+                               return -1;
+                       }
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.board.portstr = dgap_savestring(s);
+                       p->u.board.port = (short)simple_strtol(s, &s2, 0);
+                       if ((short)strlen(s) > (short)(s2 - s)) {
+                               dgap_err("bad number for IO port");
+                               return -1;
+                       }
+                       p->u.board.v_port = 1;
+                       break;
+
+               case MEM:       /* memory address */
+                       if (p->type != BNODE) {
+                               dgap_err("memory address only vaild for boards");
+                               return -1;
+                       }
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.board.addrstr = dgap_savestring(s);
+                       p->u.board.addr = simple_strtoul(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for memory address");
+                               return -1;
+                       }
+                       p->u.board.v_addr = 1;
+                       break;
+
+               case PCIINFO:   /* pci information */
+                       if (p->type != BNODE) {
+                               dgap_err("memory address only vaild for boards");
+                               return -1;
+                       }
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.board.pcibusstr = dgap_savestring(s);
+                       p->u.board.pcibus = simple_strtoul(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for pci bus");
+                               return -1;
+                       }
+                       p->u.board.v_pcibus = 1;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.board.pcislotstr = dgap_savestring(s);
+                       p->u.board.pcislot = simple_strtoul(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for pci slot");
+                               return -1;
+                       }
+                       p->u.board.v_pcislot = 1;
+                       break;
+
+               case METHOD:
+                       if (p->type != BNODE) {
+                               dgap_err("install method only vaild for boards");
+                               return -1;
+                       }
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.board.method = dgap_savestring(s);
+                       p->u.board.v_method = 1;
+                       break;
+
+               case STATUS:
+                       if (p->type != BNODE) {
+                               dgap_err("config status only vaild for boards");
+                               return -1;
+                       }
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.board.status = dgap_savestring(s);
+                       break;
+
+               case NPORTS:    /* number of ports */
+                       if (p->type == BNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.board.nport = (char)simple_strtol(s, &s2, 0);
+                               if ((int)strlen(s) > (int)(s2 - s)) {
+                                       dgap_err("bad number for number of ports");
+                                       return -1;
+                               }
+                               p->u.board.v_nport = 1;
+                       } else if (p->type == CNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
+                               if ((int)strlen(s) > (int)(s2 - s)) {
+                                       dgap_err("bad number for number of ports");
+                                       return -1;
+                               }
+                               p->u.conc.v_nport = 1;
+                       } else if (p->type == MNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.module.nport = (char)simple_strtol(s, &s2, 0);
+                               if ((int)strlen(s) > (int)(s2 - s)) {
+                                       dgap_err("bad number for number of ports");
+                                       return -1;
+                               }
+                               p->u.module.v_nport = 1;
+                       } else {
+                               dgap_err("nports only valid for concentrators or modules");
+                               return -1;
+                       }
+                       break;
+
+               case ID:        /* letter ID used in tty name */
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+
+                       p->u.board.status = dgap_savestring(s);
+
+                       if (p->type == CNODE) {
+                               p->u.conc.id = dgap_savestring(s);
+                               p->u.conc.v_id = 1;
+                       } else if (p->type == MNODE) {
+                               p->u.module.id = dgap_savestring(s);
+                               p->u.module.v_id = 1;
+                       } else {
+                               dgap_err("id only valid for concentrators or modules");
+                               return -1;
+                       }
+                       break;
+
+               case STARTO:    /* start offset of ID */
+                       if (p->type == BNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.board.start = simple_strtol(s, &s2, 0);
+                               if ((int)strlen(s) > (int)(s2 - s)) {
+                                       dgap_err("bad number for start of tty count");
+                                       return -1;
+                               }
+                               p->u.board.v_start = 1;
+                       } else if (p->type == CNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.conc.start = simple_strtol(s, &s2, 0);
+                               if ((int)strlen(s) > (int)(s2 - s)) {
+                                       dgap_err("bad number for start of tty count");
+                                       return -1;
+                               }
+                               p->u.conc.v_start = 1;
+                       } else if (p->type == MNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.module.start = simple_strtol(s, &s2, 0);
+                               if ((int)strlen(s) > (int)(s2 - s)) {
+                                       dgap_err("bad number for start of tty count");
+                                       return -1;
+                               }
+                               p->u.module.v_start = 1;
+                       } else {
+                               dgap_err("start only valid for concentrators or modules");
+                               return -1;
+                       }
+                       break;
+
+               case TTYN:      /* tty name prefix */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(TNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (!s) {
+                               dgap_err("unexpeced end of file");
+                               return -1;
+                       }
+                       p->u.ttyname = dgap_savestring(s);
+                       if (!p->u.ttyname) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       break;
+
+               case CU:        /* cu name prefix */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(CUNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (!s) {
+                               dgap_err("unexpeced end of file");
+                               return -1;
+                       }
+                       p->u.cuname = dgap_savestring(s);
+                       if (!p->u.cuname) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       break;
+
+               case LINE:      /* line information */
+                       if (dgap_checknode(p))
+                               return -1;
+                       if (brd == NULL) {
+                               dgap_err("must specify board before line info");
+                               return -1;
+                       }
+                       switch (brd->u.board.type) {
+                       case PPCM:
+                               dgap_err("line not vaild for PC/em");
+                               return -1;
+                       }
+                       p->next = dgap_newnode(LNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       conc = NULL;
+                       line = p;
+                       linecnt++;
+                       break;
+
+               case CONC:      /* concentrator information */
+                       if (dgap_checknode(p))
+                               return -1;
+                       if (line == NULL) {
+                               dgap_err("must specify line info before concentrator");
+                               return -1;
+                       }
+                       p->next = dgap_newnode(CNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       conc = p;
+                       if (linecnt)
+                               brd->u.board.conc2++;
+                       else
+                               brd->u.board.conc1++;
+
+                       break;
+
+               case CX:        /* c/x type concentrator */
+                       if (p->type != CNODE) {
+                               dgap_err("cx only valid for concentrators");
+                               return -1;
+                       }
+                       p->u.conc.type = CX;
+                       p->u.conc.v_type = 1;
+                       break;
+
+               case EPC:       /* epc type concentrator */
+                       if (p->type != CNODE) {
+                               dgap_err("cx only valid for concentrators");
+                               return -1;
+                       }
+                       p->u.conc.type = EPC;
+                       p->u.conc.v_type = 1;
+                       break;
+
+               case MOD:       /* EBI module */
+                       if (dgap_checknode(p))
+                               return -1;
+                       if (brd == NULL) {
+                               dgap_err("must specify board info before EBI modules");
+                               return -1;
+                       }
+                       switch (brd->u.board.type) {
+                       case PPCM:
+                               linecnt = 0;
+                               break;
+                       default:
+                               if (conc == NULL) {
+                                       dgap_err("must specify concentrator info before EBI module");
+                                       return -1;
+                               }
+                       }
+                       p->next = dgap_newnode(MNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       if (linecnt)
+                               brd->u.board.module2++;
+                       else
+                               brd->u.board.module1++;
+
+                       break;
+
+               case PORTS:     /* ports type EBI module */
+                       if (p->type != MNODE) {
+                               dgap_err("ports only valid for EBI modules");
+                               return -1;
+                       }
+                       p->u.module.type = PORTS;
+                       p->u.module.v_type = 1;
+                       break;
+
+               case MODEM:     /* ports type EBI module */
+                       if (p->type != MNODE) {
+                               dgap_err("modem only valid for modem modules");
+                               return -1;
+                       }
+                       p->u.module.type = MODEM;
+                       p->u.module.v_type = 1;
+                       break;
+
+               case CABLE:
+                       if (p->type == LNODE) {
+                               s = dgap_getword(in);
+                               if (!s) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.line.cable = dgap_savestring(s);
+                               p->u.line.v_cable = 1;
+                       }
+                       break;
+
+               case SPEED:     /* sync line speed indication */
+                       if (p->type == LNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.line.speed = (char)simple_strtol(s, &s2, 0);
+                               if ((short)strlen(s) > (short)(s2 - s)) {
+                                       dgap_err("bad number for line speed");
+                                       return -1;
+                               }
+                               p->u.line.v_speed = 1;
+                       } else if (p->type == CNODE) {
+                               s = dgap_getword(in);
+                               if (s == NULL) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
+                               if ((short)strlen(s) > (short)(s2 - s)) {
+                                       dgap_err("bad number for line speed");
+                                       return -1;
+                               }
+                               p->u.conc.v_speed = 1;
+                       } else {
+                               dgap_err("speed valid only for lines or concentrators.");
+                               return -1;
+                       }
+                       break;
+
+               case CONNECT:
+                       if (p->type == CNODE) {
+                               s = dgap_getword(in);
+                               if (!s) {
+                                       dgap_err("unexpected end of file");
+                                       return -1;
+                               }
+                               p->u.conc.connect = dgap_savestring(s);
+                               p->u.conc.v_connect = 1;
+                       }
+                       break;
+               case PRINT:     /* transparent print name prefix */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(PNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (!s) {
+                               dgap_err("unexpeced end of file");
+                               return -1;
+                       }
+                       p->u.printname = dgap_savestring(s);
+                       if (!p->u.printname) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       break;
+
+               case CMAJOR:    /* major number */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(JNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.majornumber = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for major number");
+                               return -1;
+                       }
+                       break;
+
+               case ALTPIN:    /* altpin setting */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(ANODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.altpin = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for altpin");
+                               return -1;
+                       }
+                       break;
+
+               case USEINTR:           /* enable interrupt setting */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(INTRNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.useintr = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for useintr");
+                               return -1;
+                       }
+                       break;
+
+               case TTSIZ:     /* size of tty structure */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(TSNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.ttysize = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for ttysize");
+                               return -1;
+                       }
+                       break;
+
+               case CHSIZ:     /* channel structure size */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(CSNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.chsize = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for chsize");
+                               return -1;
+                       }
+                       break;
+
+               case BSSIZ:     /* board structure size */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(BSNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.bssize = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for bssize");
+                               return -1;
+                       }
+                       break;
+
+               case UNTSIZ:    /* sched structure size */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(USNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.unsize = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for schedsize");
+                               return -1;
+                       }
+                       break;
+
+               case F2SIZ:     /* f2200 structure size */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(FSNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.f2size = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for f2200size");
+                               return -1;
+                       }
+                       break;
+
+               case VPSIZ:     /* vpix structure size */
+                       if (dgap_checknode(p))
+                               return -1;
+                       p->next = dgap_newnode(VSNODE);
+                       if (!p->next) {
+                               dgap_err("out of memory");
+                               return -1;
+                       }
+                       p = p->next;
+                       s = dgap_getword(in);
+                       if (s == NULL) {
+                               dgap_err("unexpected end of file");
+                               return -1;
+                       }
+                       p->u.vpixsize = simple_strtol(s, &s2, 0);
+                       if ((int)strlen(s) > (int)(s2 - s)) {
+                               dgap_err("bad number for vpixsize");
+                               return -1;
+                       }
+                       break;
+               }
+       }
+}
+
+/*
+ * dgap_sindex: much like index(), but it looks for a match of any character in
+ * the group, and returns that position.  If the first character is a ^, then
+ * this will match the first occurrence not in that group.
+ */
+static char *dgap_sindex (char *string, char *group)
+{
+       char    *ptr;
+
+       if (!string || !group)
+               return (char *) NULL;
+
+       if (*group == '^') {
+               group++;
+               for (; *string; string++) {
+                       for (ptr = group; *ptr; ptr++) {
+                               if (*ptr == *string)
+                                       break;
+                       }
+                       if (*ptr == '\0')
+                               return string;
+               }
+       } else {
+               for (; *string; string++) {
+                       for (ptr = group; *ptr; ptr++) {
+                               if (*ptr == *string)
+                                       return string;
+                       }
+               }
+       }
+
+       return (char *) NULL;
+}
+
+/*
+ * Get a token from the input file; return 0 if end of file is reached
+ */
+static int dgap_gettok(char **in, struct cnode *p)
+{
+       char    *w;
+       struct toklist *t;
+
+       if (strstr(dgap_cword, "boar")) {
+               w = dgap_getword(in);
+               snprintf(dgap_cword, MAXCWORD, "%s", w);
+               for (t = dgap_tlist; t->token != 0; t++) {
+                       if (!strcmp(w, t->string))
+                               return t->token;
+               }
+               dgap_err("board !!type not specified");
+               return 1;
+       } else {
+               while ( (w = dgap_getword(in)) != NULL ) {
+                       snprintf(dgap_cword, MAXCWORD, "%s", w);
+                       for (t = dgap_tlist; t->token != 0; t++) {
+                               if (!strcmp(w, t->string))
+                                       return t->token;
+                       }
+               }
+               return 0;
+       }
+}
+
+/*
+ * get a word from the input stream, also keep track of current line number.
+ * words are separated by whitespace.
+ */
+static char *dgap_getword(char **in)
+{
+       char *ret_ptr = *in;
+
+       char *ptr = dgap_sindex(*in, " \t\n");
+
+       /* If no word found, return null */
+       if (!ptr)
+               return NULL;
+
+       /* Mark new location for our buffer */
+       *ptr = '\0';
+       *in = ptr + 1;
+
+       /* Eat any extra spaces/tabs/newlines that might be present */
+       while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
+               **in = '\0';
+               *in = *in + 1;
+       }
+
+       return ret_ptr;
+}
+
+/*
+ * print an error message, giving the line number in the file where
+ * the error occurred.
+ */
+static void dgap_err(char *s)
+{
+       printk("DGAP: parse: %s\n", s);
+}
+
+/*
+ * allocate a new configuration node of type t
+ */
+static struct cnode *dgap_newnode(int t)
+{
+       struct cnode *n;
+
+       n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
+       if (n != NULL) {
+               memset((char *)n, 0, sizeof(struct cnode));
+               n->type = t;
+       }
+       return n;
+}
+
+/*
+ * dgap_checknode: see if all the necessary info has been supplied for a node
+ * before creating the next node.
+ */
+static int dgap_checknode(struct cnode *p)
+{
+       switch (p->type) {
+       case BNODE:
+               if (p->u.board.v_type == 0) {
+                       dgap_err("board type !not specified");
+                       return 1;
+               }
+
+               return 0;
+
+       case LNODE:
+               if (p->u.line.v_speed == 0) {
+                       dgap_err("line speed not specified");
+                       return 1;
+               }
+               return 0;
+
+       case CNODE:
+               if (p->u.conc.v_type == 0) {
+                       dgap_err("concentrator type not specified");
+                       return 1;
+               }
+               if (p->u.conc.v_speed == 0) {
+                       dgap_err("concentrator line speed not specified");
+                       return 1;
+               }
+               if (p->u.conc.v_nport == 0) {
+                       dgap_err("number of ports on concentrator not specified");
+                       return 1;
+               }
+               if (p->u.conc.v_id == 0) {
+                       dgap_err("concentrator id letter not specified");
+                       return 1;
+               }
+               return 0;
+
+       case MNODE:
+               if (p->u.module.v_type == 0) {
+                       dgap_err("EBI module type not specified");
+                       return 1;
+               }
+               if (p->u.module.v_nport == 0) {
+                       dgap_err("number of ports on EBI module not specified");
+                       return 1;
+               }
+               if (p->u.module.v_id == 0) {
+                       dgap_err("EBI module id letter not specified");
+                       return 1;
+               }
+               return 0;
+       }
+       return 0;
+}
+
+/*
+ * save a string somewhere
+ */
+static char    *dgap_savestring(char *s)
+{
+       char    *p;
+
+       p = kmalloc(strlen(s) + 1, GFP_ATOMIC);
+       if (p)
+               strcpy(p, s);
+       return p;
+}
+
+/*
+ * Given a board pointer, returns whether we should use interrupts or not.
+ */
+static uint dgap_config_get_useintr(struct board_t *bd)
+{
+       struct cnode *p = NULL;
+
+       if (!bd)
+               return 0;
+
+       for (p = bd->bd_config; p; p = p->next) {
+               switch (p->type) {
+               case INTRNODE:
+                       /*
+                        * check for pcxr types.
+                        */
+                       return p->u.useintr;
+               default:
+                       break;
+               }
+       }
+
+       /* If not found, then don't turn on interrupts. */
+       return 0;
+}
+
+/*
+ * Given a board pointer, returns whether we turn on altpin or not.
+ */
+static uint dgap_config_get_altpin(struct board_t *bd)
+{
+       struct cnode *p = NULL;
+
+       if (!bd)
+               return 0;
+
+       for (p = bd->bd_config; p; p = p->next) {
+               switch (p->type) {
+               case ANODE:
+                       /*
+                        * check for pcxr types.
+                        */
+                       return p->u.altpin;
+               default:
+                       break;
+               }
+       }
+
+       /* If not found, then don't turn on interrupts. */
+       return 0;
+}
+
+/*
+ * Given a specific type of board, if found, detached link and
+ * returns the first occurrence in the list.
+ */
+static struct cnode *dgap_find_config(int type, int bus, int slot)
+{
+       struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
+
+       p = &dgap_head;
+
+       while (p->next != NULL) {
+               prev = p;
+               p = p->next;
+
+               if (p->type == BNODE) {
+
+                       if (p->u.board.type == type) {
+
+                               if (p->u.board.v_pcibus &&
+                                   p->u.board.pcibus != bus)
+                                       continue;
+                               if (p->u.board.v_pcislot &&
+                                   p->u.board.pcislot != slot)
+                                       continue;
+
+                               found = p;
+                               /*
+                                * Keep walking thru the list till we find the next board.
+                                */
+                               while (p->next != NULL) {
+                                       prev2 = p;
+                                       p = p->next;
+                                       if (p->type == BNODE) {
+
+                                               /*
+                                                * Mark the end of our 1 board chain of configs.
+                                                */
+                                               prev2->next = NULL;
+
+                                               /*
+                                                * Link the "next" board to the previous board,
+                                                * effectively "unlinking" our board from the main config.
+                                                */
+                                               prev->next = p;
+
+                                               return found;
+                                       }
+                               }
+                               /*
+                                * It must be the last board in the list.
+                                */
+                               prev->next = NULL;
+                               return found;
+                       }
+               }
+       }
+       return NULL;
+}
+
+/*
+ * Given a board pointer, walks the config link, counting up
+ * all ports user specified should be on the board.
+ * (This does NOT mean they are all actually present right now tho)
+ */
+static uint dgap_config_get_number_of_ports(struct board_t *bd)
+{
+       int count = 0;
+       struct cnode *p = NULL;
+
+       if (!bd)
+               return 0;
+
+       for (p = bd->bd_config; p; p = p->next) {
+
+               switch (p->type) {
+               case BNODE:
+                       /*
+                        * check for pcxr types.
+                        */
+                       if (p->u.board.type > EPCFE)
+                               count += p->u.board.nport;
+                       break;
+               case CNODE:
+                       count += p->u.conc.nport;
+                       break;
+               case MNODE:
+                       count += p->u.module.nport;
+                       break;
+               }
+       }
+       return count;
+}
+
+static char *dgap_create_config_string(struct board_t *bd, char *string)
+{
+       char *ptr = string;
+       struct cnode *p = NULL;
+       struct cnode *q = NULL;
+       int speed;
+
+       if (!bd) {
+               *ptr = 0xff;
+               return string;
+       }
+
+       for (p = bd->bd_config; p; p = p->next) {
+
+               switch (p->type) {
+               case LNODE:
+                       *ptr = '\0';
+                       ptr++;
+                       *ptr = p->u.line.speed;
+                       ptr++;
+                       break;
+               case CNODE:
+                       /*
+                        * Because the EPC/con concentrators can have EM modules
+                        * hanging off of them, we have to walk ahead in the list
+                        * and keep adding the number of ports on each EM to the config.
+                        * UGH!
+                        */
+                       speed = p->u.conc.speed;
+                       q = p->next;
+                       if ((q != NULL) && (q->type == MNODE)) {
+                               *ptr = (p->u.conc.nport + 0x80);
+                               ptr++;
+                               p = q;
+                               while ((q->next != NULL) && (q->next->type) == MNODE) {
+                                       *ptr = (q->u.module.nport + 0x80);
+                                       ptr++;
+                                       p = q;
+                                       q = q->next;
+                               }
+                               *ptr = q->u.module.nport;
+                               ptr++;
+                       } else {
+                               *ptr = p->u.conc.nport;
+                               ptr++;
+                       }
+
+                       *ptr = speed;
+                       ptr++;
+                       break;
+               }
+       }
+
+       *ptr = 0xff;
+       return string;
+}
diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h
new file mode 100644 (file)
index 0000000..e33e591
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
+ *
+ *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *************************************************************************
+ *
+ * Driver includes
+ *
+ *************************************************************************/
+
+#ifndef __DGAP_DRIVER_H
+#define __DGAP_DRIVER_H
+
+#include <linux/types.h>        /* To pick up the varions Linux types */
+#include <linux/tty.h>          /* To pick up the various tty structs/defines */
+#include <linux/interrupt.h>    /* For irqreturn_t type */
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/* Required for our shared headers! */
+typedef unsigned char          uchar;
+
+#if !defined(TTY_FLIPBUF_SIZE)
+# define TTY_FLIPBUF_SIZE 512
+#endif
+
+/* Sparse stuff */
+# ifndef __user
+#  define __user
+#  define __kernel
+#  define __safe
+#  define __force
+#  define __chk_user_ptr(x) (void)0
+# endif
+
+
+#  define PARM_STR(VAR, INIT, PERM, DESC) \
+               static char *VAR = INIT; \
+               char *dgap_##VAR; \
+               module_param(VAR, charp, PERM); \
+               MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_INT(VAR, INIT, PERM, DESC) \
+               static int VAR = INIT; \
+               int dgap_##VAR; \
+               module_param(VAR, int, PERM); \
+               MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
+               static ulong VAR = INIT; \
+               ulong dgap_##VAR; \
+               module_param(VAR, long, PERM); \
+               MODULE_PARM_DESC(VAR, DESC);
+
+/*************************************************************************
+ *
+ * Driver defines
+ *
+ *************************************************************************/
+
+/*
+ * Driver identification, error and debugging statments
+ *
+ * In theory, you can change all occurrences of "digi" in the next
+ * three lines, and the driver printk's will all automagically change.
+ *
+ * APR((fmt, args, ...));      Always prints message
+ * DPR((fmt, args, ...));      Only prints if DGAP_TRACER is defined at
+ *                               compile time and dgap_debug!=0
+ */
+#define        DG_NAME         "dgap-1.3-16"
+#define        DG_PART         "40002347_C"
+
+#define        PROCSTR         "dgap"                  /* /proc entries         */
+#define        DEVSTR          "/dev/dg/dgap"          /* /dev entries          */
+#define        DRVSTR          "dgap"                  /* Driver name string
+                                                * displayed by APR      */
+#define        APR(args)       do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
+                          } while (0)
+#define        RAPR(args)      do { PRINTF_TO_KMEM(args); printk args; } while (0)
+
+#define TRC_TO_CONSOLE 1
+
+/*
+ * defines from dgap_pci.h
+ */ 
+#define PCIMAX 32                      /* maximum number of PCI boards */
+
+#define DIGI_VID               0x114F
+
+#define PCI_DEVICE_EPC_DID     0x0002
+#define PCI_DEVICE_XEM_DID     0x0004
+#define PCI_DEVICE_XR_DID      0x0005
+#define PCI_DEVICE_CX_DID      0x0006
+#define PCI_DEVICE_XRJ_DID     0x0009  /* PLX-based Xr adapter */
+#define PCI_DEVICE_XR_IBM_DID  0x0011  /* IBM 8-port Async Adapter */
+#define PCI_DEVICE_XR_BULL_DID 0x0013  /* BULL 8-port Async Adapter */
+#define PCI_DEVICE_XR_SAIP_DID 0x001c  /* SAIP card - Xr adapter */
+#define PCI_DEVICE_XR_422_DID  0x0012  /* Xr-422 */
+#define PCI_DEVICE_920_2_DID   0x0034  /* XR-Plus 920 K, 2 port */
+#define PCI_DEVICE_920_4_DID   0x0026  /* XR-Plus 920 K, 4 port */
+#define PCI_DEVICE_920_8_DID   0x0027  /* XR-Plus 920 K, 8 port */
+#define PCI_DEVICE_EPCJ_DID    0x000a  /* PLX 9060 chip for PCI  */
+#define PCI_DEVICE_CX_IBM_DID  0x001b  /* IBM 128-port Async Adapter */
+#define PCI_DEVICE_920_8_HP_DID        0x0058  /* HP XR-Plus 920 K, 8 port */
+#define PCI_DEVICE_XEM_HP_DID  0x0059  /* HP Xem PCI */
+
+#define PCI_DEVICE_XEM_NAME    "AccelePort XEM"
+#define PCI_DEVICE_CX_NAME     "AccelePort CX"
+#define PCI_DEVICE_XR_NAME     "AccelePort Xr"
+#define PCI_DEVICE_XRJ_NAME    "AccelePort Xr (PLX)"
+#define PCI_DEVICE_XR_SAIP_NAME        "AccelePort Xr (SAIP)"
+#define PCI_DEVICE_920_2_NAME  "AccelePort Xr920 2 port"
+#define PCI_DEVICE_920_4_NAME  "AccelePort Xr920 4 port"
+#define PCI_DEVICE_920_8_NAME  "AccelePort Xr920 8 port"
+#define PCI_DEVICE_XR_422_NAME "AccelePort Xr 422"
+#define PCI_DEVICE_EPCJ_NAME   "AccelePort EPC (PLX)"
+#define PCI_DEVICE_XR_BULL_NAME        "AccelePort Xr (BULL)"
+#define PCI_DEVICE_XR_IBM_NAME "AccelePort Xr (IBM)"
+#define PCI_DEVICE_CX_IBM_NAME "AccelePort CX (IBM)"
+#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
+#define PCI_DEVICE_XEM_HP_NAME "AccelePort XEM (HP)"
+
+/*
+ * On the PCI boards, there is no IO space allocated
+ * The I/O registers will be in the first 3 bytes of the
+ * upper 2MB of the 4MB memory space.  The board memory
+ * will be mapped into the low 2MB of the 4MB memory space
+ */
+
+/* Potential location of PCI Bios from E0000 to FFFFF*/
+#define PCI_BIOS_SIZE          0x00020000
+
+/* Size of Memory and I/O for PCI (4MB) */
+#define PCI_RAM_SIZE           0x00400000
+
+/* Size of Memory (2MB) */
+#define PCI_MEM_SIZE           0x00200000
+
+/* Max PCI Window Size (2MB) */
+#define PCI_WIN_SIZE           0x00200000
+
+#define PCI_WIN_SHIFT          21 /* 21 bits max */
+
+/* Offset of I/0 in Memory (2MB) */
+#define PCI_IO_OFFSET          0x00200000
+
+/* Size of IO (2MB) */
+#define PCI_IO_SIZE            0x00200000
+
+/* Number of boards we support at once. */
+#define        MAXBOARDS       32
+#define        MAXPORTS        224
+#define MAXTTYNAMELEN  200
+
+/* Our 3 magic numbers for our board, channel and unit structs */
+#define DGAP_BOARD_MAGIC       0x5c6df104
+#define DGAP_CHANNEL_MAGIC     0x6c6df104
+#define DGAP_UNIT_MAGIC                0x7c6df104
+
+/* Serial port types */
+#define DGAP_SERIAL            0
+#define DGAP_PRINT             1
+
+#define        SERIAL_TYPE_NORMAL      1
+
+/* 4 extra for alignment play space */
+#define WRITEBUFLEN            ((4096) + 4)
+#define MYFLIPLEN              N_TTY_BUF_SIZE
+
+#define SBREAK_TIME 0x25
+#define U2BSIZE 0x400
+
+#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
+
+/*
+ * Our major for the mgmt devices.
+ *
+ * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
+ * 22 has now become obsolete now that the "cu" devices have
+ * been removed from 2.6.
+ * Also, this *IS* the epca driver, just PCI only now.
+ */
+#ifndef DIGI_DGAP_MAJOR
+# define DIGI_DGAP_MAJOR         22
+#endif
+
+/*
+ * The parameters we use to define the periods of the moving averages.
+ */
+#define                MA_PERIOD       (HZ / 10)
+#define                SMA_DUR         (1 * HZ)
+#define                EMA_DUR         (1 * HZ)
+#define                SMA_NPERIODS    (SMA_DUR / MA_PERIOD)
+#define                EMA_NPERIODS    (EMA_DUR / MA_PERIOD)
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.  This is the same structure that is defined
+ * as the default in tty_io.c with the same settings overriden as in serial.c
+ *
+ * In short, this should match the internal serial ports' defaults.
+ */
+#define        DEFAULT_IFLAGS  (ICRNL | IXON)
+#define        DEFAULT_OFLAGS  (OPOST | ONLCR)
+#define        DEFAULT_CFLAGS  (B9600 | CS8 | CREAD | HUPCL | CLOCAL)
+#define        DEFAULT_LFLAGS  (ISIG | ICANON | ECHO | ECHOE | ECHOK | \
+                       ECHOCTL | ECHOKE | IEXTEN)
+
+#ifndef _POSIX_VDISABLE
+#define   _POSIX_VDISABLE '\0'
+#endif
+
+#define SNIFF_MAX      65536           /* Sniff buffer size (2^n) */
+#define SNIFF_MASK     (SNIFF_MAX - 1) /* Sniff wrap mask */
+
+#define VPDSIZE (512)
+
+/*
+ * Lock function/defines.
+ * Makes spotting lock/unlock locations easier.
+ */
+# define DGAP_SPINLOCK_INIT(x)         spin_lock_init(&(x))
+# define DGAP_LOCK(x,y)                        spin_lock_irqsave(&(x), y)
+# define DGAP_UNLOCK(x,y)              spin_unlock_irqrestore(&(x), y)
+# define DGAP_TRYLOCK(x,y)             spin_trylock(&(x))
+
+/************************************************************************
+ *      FEP memory offsets
+ ************************************************************************/
+#define START           0x0004L         /* Execution start address      */
+
+#define CMDBUF          0x0d10L         /* Command (cm_t) structure offset */
+#define CMDSTART        0x0400L         /* Start of command buffer      */
+#define CMDMAX          0x0800L         /* End of command buffer        */
+
+#define EVBUF           0x0d18L         /* Event (ev_t) structure       */
+#define EVSTART         0x0800L         /* Start of event buffer        */
+#define EVMAX           0x0c00L         /* End of event buffer          */
+#define FEP5_PLUS       0x0E40          /* ASCII '5' and ASCII 'A' is here  */
+#define ECS_SEG         0x0E44          /* Segment of the extended channel structure */
+#define LINE_SPEED      0x10            /* Offset into ECS_SEG for line speed   */
+                                        /* if the fep has extended capabilities */
+
+/* BIOS MAGIC SPOTS */
+#define ERROR           0x0C14L                /* BIOS error code              */
+#define SEQUENCE       0x0C12L         /* BIOS sequence indicator      */
+#define POSTAREA       0x0C00L         /* POST complete message area   */
+
+/* FEP MAGIC SPOTS */
+#define FEPSTAT         POSTAREA        /* OS here when FEP comes up    */
+#define NCHAN           0x0C02L         /* number of ports FEP sees     */
+#define PANIC           0x0C10L         /* PANIC area for FEP           */
+#define KMEMEM          0x0C30L         /* Memory for KME use           */
+#define CONFIG          0x0CD0L         /* Concentrator configuration info */
+#define CONFIGSIZE      0x0030          /* configuration info size      */
+#define DOWNREQ         0x0D00          /* Download request buffer pointer */
+
+#define CHANBUF         0x1000L         /* Async channel (bs_t) structs */
+#define FEPOSSIZE       0x1FFF          /* 8K FEPOS                     */
+
+#define XEMPORTS    0xC02      /*
+                                * Offset in board memory where FEP5 stores
+                                * how many ports it has detected.
+                                * NOTE: FEP5 reports 64 ports when the user
+                                * has the cable in EBI OUT instead of EBI IN.
+                                */
+
+#define FEPCLR      0x00
+#define FEPMEM      0x02
+#define FEPRST      0x04
+#define FEPINT      0x08
+#define FEPMASK     0x0e
+#define FEPWIN      0x80
+
+#define LOWMEM      0x0100
+#define HIGHMEM     0x7f00
+
+#define FEPTIMEOUT 200000
+
+#define ENABLE_INTR            0x0e04          /* Enable interrupts flag */
+#define FEPPOLL_MIN            1               /* minimum of 1 millisecond */
+#define FEPPOLL_MAX            20              /* maximum of 20 milliseconds */
+#define FEPPOLL                        0x0c26          /* Fep event poll interval */
+
+#define        IALTPIN                 0x0080          /* Input flag to swap DSR <-> DCD */
+
+/************************************************************************
+ * FEP supported functions
+ ************************************************************************/
+#define SRLOW          0xe0            /* Set receive low water        */
+#define SRHIGH         0xe1            /* Set receive high water       */
+#define FLUSHTX                0xe2            /* Flush transmit buffer        */
+#define PAUSETX                0xe3            /* Pause data transmission      */
+#define RESUMETX       0xe4            /* Resume data transmission     */
+#define SMINT          0xe5            /* Set Modem Interrupt          */
+#define SAFLOWC                0xe6            /* Set Aux. flow control chars  */
+#define SBREAK         0xe8            /* Send break                   */
+#define SMODEM         0xe9            /* Set 8530 modem control lines */
+#define SIFLAG         0xea            /* Set UNIX iflags              */
+#define SFLOWC         0xeb            /* Set flow control characters  */
+#define STLOW          0xec            /* Set transmit low water mark  */
+#define RPAUSE         0xee            /* Pause receive                */
+#define RRESUME                0xef            /* Resume receive               */
+#define CHRESET                0xf0            /* Reset Channel                */
+#define BUFSETALL      0xf2            /* Set Tx & Rx buffer size avail*/
+#define SOFLAG         0xf3            /* Set UNIX oflags              */
+#define SHFLOW         0xf4            /* Set hardware handshake       */
+#define SCFLAG         0xf5            /* Set UNIX cflags              */
+#define SVNEXT         0xf6            /* Set VNEXT character          */
+#define SPINTFC                0xfc            /* Reserved                     */
+#define SCOMMODE       0xfd            /* Set RS232/422 mode           */
+
+
+/************************************************************************
+ *     Modes for SCOMMODE
+ ************************************************************************/
+#define MODE_232       0x00
+#define MODE_422       0x01
+
+
+/************************************************************************
+ *      Event flags.
+ ************************************************************************/
+#define IFBREAK         0x01            /* Break received               */
+#define IFTLW           0x02            /* Transmit low water           */
+#define IFTEM           0x04            /* Transmitter empty            */
+#define IFDATA          0x08            /* Receive data present         */
+#define IFMODEM         0x20            /* Modem status change          */
+
+/************************************************************************
+ *      Modem flags
+ ************************************************************************/
+#       define  DM_RTS          0x02    /* Request to send              */
+#       define  DM_CD           0x80    /* Carrier detect               */
+#       define  DM_DSR          0x20    /* Data set ready               */
+#       define  DM_CTS          0x10    /* Clear to send                */
+#       define  DM_RI           0x40    /* Ring indicator               */
+#       define  DM_DTR          0x01    /* Data terminal ready          */
+
+/*
+ * defines from dgap_conf.h
+ */
+#define NULLNODE 0             /* header node, not used */
+#define BNODE 1                        /* Board node */
+#define LNODE 2                        /* Line node */
+#define CNODE 3                        /* Concentrator node */
+#define MNODE 4                        /* EBI Module node */
+#define TNODE 5                        /* tty name prefix node */
+#define        CUNODE 6                /* cu name prefix (non-SCO) */
+#define PNODE 7                        /* trans. print prefix node */
+#define JNODE 8                        /* maJor number node */
+#define ANODE 9                        /* altpin */
+#define        TSNODE 10               /* tty structure size */
+#define CSNODE 11              /* channel structure size */
+#define BSNODE 12              /* board structure size */
+#define USNODE 13              /* unit schedule structure size */
+#define FSNODE 14              /* f2200 structure size */
+#define VSNODE 15              /* size of VPIX structures */
+#define INTRNODE 16            /* enable interrupt */
+
+/* Enumeration of tokens */
+#define        BEGIN   1
+#define        END     2
+#define        BOARD   10
+
+#define EPCFS  11 /* start of EPC family definitions */
+#define        ICX             11
+#define        MCX             13
+#define PCX    14
+#define        IEPC    15
+#define        EEPC    16
+#define        MEPC    17
+#define        IPCM    18
+#define        EPCM    19
+#define        MPCM    20
+#define PEPC   21
+#define PPCM   22
+#ifdef CP
+#define ICP     23
+#define ECP     24
+#define MCP     25
+#endif
+#define EPCFE  25 /* end of EPC family definitions */
+#define        PC2E    26
+#define        PC4E    27
+#define        PC4E8K  28
+#define        PC8E    29
+#define        PC8E8K  30
+#define        PC16E   31
+#define MC2E8K  34
+#define MC4E8K  35
+#define MC8E8K  36
+
+#define AVANFS 42      /* start of Avanstar family definitions */
+#define A8P    42
+#define A16P   43
+#define AVANFE 43      /* end of Avanstar family definitions */
+
+#define DA2000FS       44      /* start of AccelePort 2000 family definitions */
+#define DA22           44 /* AccelePort 2002 */
+#define DA24           45 /* AccelePort 2004 */
+#define DA28           46 /* AccelePort 2008 */
+#define DA216          47 /* AccelePort 2016 */
+#define DAR4           48 /* AccelePort RAS 4 port */
+#define DAR8           49 /* AccelePort RAS 8 port */
+#define DDR24          50 /* DataFire RAS 24 port */
+#define DDR30          51 /* DataFire RAS 30 port */
+#define DDR48          52 /* DataFire RAS 48 port */
+#define DDR60          53 /* DataFire RAS 60 port */
+#define DA2000FE       53 /* end of AccelePort 2000/RAS family definitions */
+
+#define PCXRFS 106     /* start of PCXR family definitions */
+#define        APORT4  106
+#define        APORT8  107
+#define PAPORT4 108
+#define PAPORT8 109
+#define APORT4_920I    110
+#define APORT8_920I    111
+#define APORT4_920P    112
+#define APORT8_920P    113
+#define APORT2_920P 114
+#define PCXRFE 117     /* end of PCXR family definitions */
+
+#define        LINE    82
+#ifdef T1
+#define T1M    83
+#define E1M    84
+#endif
+#define        CONC    64
+#define        CX      65
+#define        EPC     66
+#define        MOD     67
+#define        PORTS   68
+#define METHOD 69
+#define CUSTOM 70
+#define BASIC  71
+#define STATUS 72
+#define MODEM  73
+/* The following tokens can appear in multiple places */
+#define        SPEED   74
+#define        NPORTS  75
+#define        ID      76
+#define CABLE  77
+#define CONNECT        78
+#define        IO      79
+#define        MEM     80
+#define DPSZ   81
+
+#define        TTYN    90
+#define        CU      91
+#define        PRINT   92
+#define        XPRINT  93
+#define CMAJOR   94
+#define ALTPIN  95
+#define STARTO 96
+#define USEINTR  97
+#define PCIINFO  98
+
+#define        TTSIZ   100
+#define        CHSIZ   101
+#define BSSIZ  102
+#define        UNTSIZ  103
+#define        F2SIZ   104
+#define        VPSIZ   105
+
+#define        TOTAL_BOARD     2
+#define        CURRENT_BRD     4
+#define        BOARD_TYPE      6
+#define        IO_ADDRESS      8
+#define        MEM_ADDRESS     10
+
+#define        FIELDS_PER_PAGE 18
+
+#define TB_FIELD       1
+#define CB_FIELD       3
+#define BT_FIELD       5
+#define IO_FIELD       7
+#define ID_FIELD       8
+#define ME_FIELD       9
+#define TTY_FIELD      11
+#define CU_FIELD       13
+#define PR_FIELD       15
+#define MPR_FIELD      17
+
+#define        MAX_FIELD       512
+
+#define        INIT            0
+#define        NITEMS          128
+#define MAX_ITEM       512
+
+#define        DSCRINST        1
+#define        DSCRNUM         3
+#define        ALTPINQ         5
+#define        SSAVE           7
+
+#define        DSCR            "32"
+#define        ONETONINE       "123456789"
+#define        ALL             "1234567890"
+
+/*
+ * All the possible states the driver can be while being loaded.
+ */
+enum {
+       DRIVER_INITIALIZED = 0,
+       DRIVER_NEED_CONFIG_LOAD,
+       DRIVER_REQUESTED_CONFIG,
+       DRIVER_READY
+};
+
+/*
+ * All the possible states the board can be while booting up.
+ */
+enum {
+       BOARD_FAILED = 0,
+       CONFIG_NOT_FOUND,
+       BOARD_FOUND,
+       NEED_RESET,
+       FINISHED_RESET,
+       NEED_CONFIG,
+       FINISHED_CONFIG,
+       NEED_DEVICE_CREATION,
+       REQUESTED_DEVICE_CREATION,
+       FINISHED_DEVICE_CREATION,
+       NEED_BIOS_LOAD,
+       REQUESTED_BIOS,
+       WAIT_BIOS_LOAD,
+       FINISHED_BIOS_LOAD,
+       NEED_FEP_LOAD,
+       REQUESTED_FEP,
+       WAIT_FEP_LOAD,
+       FINISHED_FEP_LOAD,
+       NEED_PROC_CREATION,
+       FINISHED_PROC_CREATION,
+       BOARD_READY
+};
+
+/*
+ * All the possible states that a requested concentrator image can be in.
+ */
+enum {
+       NO_PENDING_CONCENTRATOR_REQUESTS = 0,
+       NEED_CONCENTRATOR,
+       REQUESTED_CONCENTRATOR
+};
+
+
+
+/*
+ * Modem line constants are defined as macros because DSR and
+ * DCD are swapable using the ditty altpin option.
+ */
+#define D_CD(ch)        ch->ch_cd       /* Carrier detect       */
+#define D_DSR(ch)       ch->ch_dsr      /* Data set ready       */
+#define D_RTS(ch)       DM_RTS          /* Request to send      */
+#define D_CTS(ch)       DM_CTS          /* Clear to send        */
+#define D_RI(ch)        DM_RI           /* Ring indicator       */
+#define D_DTR(ch)       DM_DTR          /* Data terminal ready  */
+
+
+/*************************************************************************
+ *
+ * Structures and closely related defines.
+ *
+ *************************************************************************/
+
+
+/*
+ * A structure to hold a statistics counter.  We also
+ * compute moving averages for this counter.
+ */
+struct macounter
+{
+       u32             cnt;    /* Total count */
+       ulong           accum;  /* Acuumulator per period */
+       ulong           sma;    /* Simple moving average */
+       ulong           ema;    /* Exponential moving average */
+};
+
+
+/************************************************************************
+ * Device flag definitions for bd_flags.
+ ************************************************************************/
+#define        BD_FEP5PLUS     0x0001          /* Supports FEP5 Plus commands */
+#define BD_HAS_VPD     0x0002          /* Board has VPD info available */
+
+/*
+ *     Per-board information
+ */
+struct board_t
+{
+       int             magic;          /* Board Magic number.  */
+       int             boardnum;       /* Board number: 0-3 */
+       int             firstminor;     /* First minor, e.g. 0, 30, 60 */
+
+       int             type;           /* Type of board */
+       char            *name;          /* Product Name */
+       struct pci_dev  *pdev;          /* Pointer to the pci_dev struct */
+       u16             vendor;         /* PCI vendor ID */
+       u16             device;         /* PCI device ID */
+       u16             subvendor;      /* PCI subsystem vendor ID */
+       u16             subdevice;      /* PCI subsystem device ID */
+       uchar           rev;            /* PCI revision ID */
+       uint            pci_bus;        /* PCI bus value */
+       uint            pci_slot;       /* PCI slot value */
+       u16             maxports;       /* MAX ports this board can handle */
+       uchar           vpd[VPDSIZE];   /* VPD of board, if found */
+       u32             bd_flags;       /* Board flags */
+
+       spinlock_t      bd_lock;        /* Used to protect board */
+
+       u32             state;          /* State of card. */
+       wait_queue_head_t state_wait;   /* Place to sleep on for state change */
+
+       struct          tasklet_struct helper_tasklet; /* Poll helper tasklet */
+
+       u32             wait_for_bios;
+       u32             wait_for_fep;
+
+       struct cnode *  bd_config;      /* Config of board */
+
+       u16             nasync;         /* Number of ports on card */
+
+       u32             use_interrupts; /* Should we be interrupt driven? */
+       ulong           irq;            /* Interrupt request number */
+       ulong           intr_count;     /* Count of interrupts */
+       u32             intr_used;      /* Non-zero if using interrupts */
+       u32             intr_running;   /* Non-zero if FEP knows its doing interrupts */
+
+       ulong           port;           /* Start of base io port of the card */
+       ulong           port_end;       /* End of base io port of the card */
+       ulong           membase;        /* Start of base memory of the card */
+       ulong           membase_end;    /* End of base memory of the card */
+
+       uchar           *re_map_port;   /* Remapped io port of the card */
+       uchar           *re_map_membase;/* Remapped memory of the card */
+
+       uchar           runwait;        /* # Processes waiting for FEP  */
+       uchar           inhibit_poller; /* Tells  the poller to leave us alone */
+
+       struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
+
+       struct tty_driver       *SerialDriver;
+       struct tty_port *SerialPorts;
+       char            SerialName[200];
+       struct tty_driver       *PrintDriver;
+       struct tty_port *PrinterPorts;
+       char            PrintName[200];
+
+       u32             dgap_Major_Serial_Registered;
+       u32             dgap_Major_TransparentPrint_Registered;
+
+       u32             dgap_Serial_Major;
+       u32             dgap_TransparentPrint_Major;
+
+       struct bs_t     *bd_bs;                 /* Base structure pointer       */
+
+       char    *flipbuf;               /* Our flip buffer, alloced if board is found */
+       char    *flipflagbuf;           /* Our flip flag buffer, alloced if board is found */
+
+       u16             dpatype;        /* The board "type", as defined by DPA */
+       u16             dpastatus;      /* The board "status", as defined by DPA */
+       wait_queue_head_t kme_wait;     /* Needed for DPA support */
+
+       u32             conc_dl_status; /* Status of any pending conc download */
+       /*
+        *      Mgmt data.
+        */
+        char           *msgbuf_head;
+        char           *msgbuf;
+};
+
+
+
+/************************************************************************
+ * Unit flag definitions for un_flags.
+ ************************************************************************/
+#define UN_ISOPEN      0x0001          /* Device is open               */
+#define UN_CLOSING     0x0002          /* Line is being closed         */
+#define UN_IMM         0x0004          /* Service immediately          */
+#define UN_BUSY                0x0008          /* Some work this channel       */
+#define UN_BREAKI      0x0010          /* Input break received         */
+#define UN_PWAIT       0x0020          /* Printer waiting for terminal */
+#define UN_TIME                0x0040          /* Waiting on time              */
+#define UN_EMPTY       0x0080          /* Waiting output queue empty   */
+#define UN_LOW         0x0100          /* Waiting output low water mark*/
+#define UN_EXCL_OPEN   0x0200          /* Open for exclusive use       */
+#define UN_WOPEN       0x0400          /* Device waiting for open      */
+#define UN_WIOCTL      0x0800          /* Device waiting for open      */
+#define UN_HANGUP      0x8000          /* Carrier lost                 */
+
+struct device;
+
+/************************************************************************
+ * Structure for terminal or printer unit.
+ ************************************************************************/
+struct un_t {
+       int     magic;          /* Unit Magic Number.                   */
+       struct  channel_t *un_ch;
+       u32     un_time;
+       u32     un_type;
+       u32     un_open_count;  /* Counter of opens to port             */
+       struct tty_struct *un_tty;/* Pointer to unit tty structure      */
+       u32     un_flags;       /* Unit flags                           */
+       wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
+       u32     un_dev;         /* Minor device number                  */
+       tcflag_t un_oflag;      /* oflags being done on board           */
+       tcflag_t un_lflag;      /* lflags being done on board           */
+       struct device *un_sysfs;
+};
+
+
+/************************************************************************
+ * Device flag definitions for ch_flags.
+ ************************************************************************/
+#define CH_PRON         0x0001          /* Printer on string                */
+#define CH_OUT          0x0002          /* Dial-out device open             */
+#define CH_STOP         0x0004          /* Output is stopped                */
+#define CH_STOPI        0x0008          /* Input is stopped                 */
+#define CH_CD           0x0010          /* Carrier is present               */
+#define CH_FCAR         0x0020          /* Carrier forced on                */
+
+#define CH_RXBLOCK      0x0080          /* Enable rx blocked flag           */
+#define CH_WLOW         0x0100          /* Term waiting low event           */
+#define CH_WEMPTY       0x0200          /* Term waiting empty event         */
+#define CH_RENABLE      0x0400          /* Buffer just emptied          */
+#define CH_RACTIVE      0x0800          /* Process active in xxread()   */
+#define CH_RWAIT        0x1000          /* Process waiting in xxread()  */
+#define CH_BAUD0       0x2000          /* Used for checking B0 transitions */
+#define CH_HANGUP       0x8000         /* Hangup received                  */
+
+/*
+ * Definitions for ch_sniff_flags
+ */
+#define SNIFF_OPEN     0x1
+#define SNIFF_WAIT_DATA        0x2
+#define SNIFF_WAIT_SPACE 0x4
+
+
+/************************************************************************
+ ***   Definitions for Digi ditty(1) command.
+ ************************************************************************/
+
+
+/*
+ * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
+ */
+
+/************************************************************************
+ * This module provides application access to special Digi
+ * serial line enhancements which are not standard UNIX(tm) features.
+ ************************************************************************/
+
+#if !defined(TIOCMODG)
+
+#define        TIOCMODG        ('d'<<8) | 250          /* get modem ctrl state */
+#define        TIOCMODS        ('d'<<8) | 251          /* set modem ctrl state */
+
+#ifndef TIOCM_LE
+#define                TIOCM_LE        0x01            /* line enable          */
+#define                TIOCM_DTR       0x02            /* data terminal ready  */
+#define                TIOCM_RTS       0x04            /* request to send      */
+#define                TIOCM_ST        0x08            /* secondary transmit   */
+#define                TIOCM_SR        0x10            /* secondary receive    */
+#define                TIOCM_CTS       0x20            /* clear to send        */
+#define                TIOCM_CAR       0x40            /* carrier detect       */
+#define                TIOCM_RNG       0x80            /* ring indicator       */
+#define                TIOCM_DSR       0x100           /* data set ready       */
+#define                TIOCM_RI        TIOCM_RNG       /* ring (alternate)     */
+#define                TIOCM_CD        TIOCM_CAR       /* carrier detect (alt) */
+#endif
+
+#endif
+
+#if !defined(TIOCMSET)
+#define        TIOCMSET        ('d'<<8) | 252          /* set modem ctrl state */
+#define        TIOCMGET        ('d'<<8) | 253          /* set modem ctrl state */
+#endif
+
+#if !defined(TIOCMBIC)
+#define        TIOCMBIC        ('d'<<8) | 254          /* set modem ctrl state */
+#define        TIOCMBIS        ('d'<<8) | 255          /* set modem ctrl state */
+#endif
+
+
+#if !defined(TIOCSDTR)
+#define        TIOCSDTR        ('e'<<8) | 0            /* set DTR              */
+#define        TIOCCDTR        ('e'<<8) | 1            /* clear DTR            */
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA      ('e'<<8) | 94           /* Read params          */
+
+#define DIGI_SETA      ('e'<<8) | 95           /* Set params           */
+#define DIGI_SETAW     ('e'<<8) | 96           /* Drain & set params   */
+#define DIGI_SETAF     ('e'<<8) | 97           /* Drain, flush & set params */
+
+#define DIGI_KME       ('e'<<8) | 98           /* Read/Write Host      */
+                                               /* Adapter Memory       */
+
+#define        DIGI_GETFLOW    ('e'<<8) | 99           /* Get startc/stopc flow */
+                                               /* control characters    */
+#define        DIGI_SETFLOW    ('e'<<8) | 100          /* Set startc/stopc flow */
+                                               /* control characters    */
+#define        DIGI_GETAFLOW   ('e'<<8) | 101          /* Get Aux. startc/stopc */
+                                               /* flow control chars    */
+#define        DIGI_SETAFLOW   ('e'<<8) | 102          /* Set Aux. startc/stopc */
+                                               /* flow control chars    */
+
+#define DIGI_GEDELAY   ('d'<<8) | 246          /* Get edelay */
+#define DIGI_SEDELAY   ('d'<<8) | 247          /* Set edelay */
+
+struct digiflow_t {
+       unsigned char   startc;                         /* flow cntl start char */
+       unsigned char   stopc;                          /* flow cntl stop char  */
+};
+
+
+#ifdef FLOW_2200
+#define        F2200_GETA      ('e'<<8) | 104          /* Get 2x36 flow cntl flags */
+#define        F2200_SETAW     ('e'<<8) | 105          /* Set 2x36 flow cntl flags */
+#define                F2200_MASK      0x03            /* 2200 flow cntl bit mask  */
+#define                FCNTL_2200      0x01            /* 2x36 terminal flow cntl  */
+#define                PCNTL_2200      0x02            /* 2x36 printer flow cntl   */
+#define        F2200_XON       0xf8
+#define        P2200_XON       0xf9
+#define        F2200_XOFF      0xfa
+#define        P2200_XOFF      0xfb
+
+#define        FXOFF_MASK      0x03                    /* 2200 flow status mask    */
+#define        RCVD_FXOFF      0x01                    /* 2x36 Terminal XOFF rcvd  */
+#define        RCVD_PXOFF      0x02                    /* 2x36 Printer XOFF rcvd   */
+#endif
+
+/************************************************************************
+ * Values for digi_flags
+ ************************************************************************/
+#define DIGI_IXON      0x0001          /* Handle IXON in the FEP       */
+#define DIGI_FAST      0x0002          /* Fast baud rates              */
+#define RTSPACE                0x0004          /* RTS input flow control       */
+#define CTSPACE                0x0008          /* CTS output flow control      */
+#define DSRPACE                0x0010          /* DSR output flow control      */
+#define DCDPACE                0x0020          /* DCD output flow control      */
+#define DTRPACE                0x0040          /* DTR input flow control       */
+#define DIGI_COOK      0x0080          /* Cooked processing done in FEP */
+#define DIGI_FORCEDCD  0x0100          /* Force carrier                */
+#define        DIGI_ALTPIN     0x0200          /* Alternate RJ-45 pin config   */
+#define        DIGI_AIXON      0x0400          /* Aux flow control in fep      */
+#define        DIGI_PRINTER    0x0800          /* Hold port open for flow cntrl*/
+#define DIGI_PP_INPUT  0x1000          /* Change parallel port to input*/
+#define DIGI_DTR_TOGGLE 0x2000         /* Support DTR Toggle           */
+#define        DIGI_422        0x4000          /* for 422/232 selectable panel */
+#define DIGI_RTS_TOGGLE        0x8000          /* Support RTS Toggle           */
+
+/************************************************************************
+ * These options are not supported on the comxi.
+ ************************************************************************/
+#define        DIGI_COMXI      (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
+
+#define DIGI_PLEN      28              /* String length                */
+#define        DIGI_TSIZ       10              /* Terminal string len          */
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_t {
+       unsigned short  digi_flags;             /* Flags (see above)    */
+       unsigned short  digi_maxcps;            /* Max printer CPS      */
+       unsigned short  digi_maxchar;           /* Max chars in print queue */
+       unsigned short  digi_bufsize;           /* Buffer size          */
+       unsigned char   digi_onlen;             /* Length of ON string  */
+       unsigned char   digi_offlen;            /* Length of OFF string */
+       char            digi_onstr[DIGI_PLEN];  /* Printer on string    */
+       char            digi_offstr[DIGI_PLEN]; /* Printer off string   */
+       char            digi_term[DIGI_TSIZ];   /* terminal string      */
+};
+
+/************************************************************************
+ * KME definitions and structures.
+ ************************************************************************/
+#define        RW_IDLE         0       /* Operation complete                   */
+#define        RW_READ         1       /* Read Concentrator Memory             */
+#define        RW_WRITE        2       /* Write Concentrator Memory            */
+
+struct rw_t {
+       unsigned char   rw_req;         /* Request type                 */
+       unsigned char   rw_board;       /* Host Adapter board number    */
+       unsigned char   rw_conc;        /* Concentrator number          */
+       unsigned char   rw_reserved;    /* Reserved for expansion       */
+       unsigned long   rw_addr;        /* Address in concentrator      */
+       unsigned short  rw_size;        /* Read/write request length    */
+       unsigned char   rw_data[128];   /* Data to read/write           */
+};
+
+/***********************************************************************
+ * Shrink Buffer and Board Information definitions and structures.
+
+ ************************************************************************/
+                       /* Board type return codes */
+#define        PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
+#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
+#define        PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
+#define        MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
+#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
+
+                        /* Non-Zero Result codes. */
+#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
+#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
+#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
+#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
+#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
+
+struct shrink_buf_struct {
+       unsigned long   shrink_buf_vaddr;       /* Virtual address of board */
+       unsigned long   shrink_buf_phys;        /* Physical address of board */
+       unsigned long   shrink_buf_bseg;        /* Amount of board memory */
+       unsigned long   shrink_buf_hseg;        /* '186 Beginning of Dual-Port */
+
+       unsigned long   shrink_buf_lseg;        /* '186 Beginning of freed memory                                               */
+       unsigned long   shrink_buf_mseg;        /* Linear address from start of
+                                                  dual-port were freed memory
+                                                  begins, host viewpoint. */
+
+       unsigned long   shrink_buf_bdparam;     /* Parameter for xxmemon and
+                                                  xxmemoff */
+
+       unsigned long   shrink_buf_reserva;     /* Reserved */
+       unsigned long   shrink_buf_reservb;     /* Reserved */
+       unsigned long   shrink_buf_reservc;     /* Reserved */
+       unsigned long   shrink_buf_reservd;     /* Reserved */
+
+       unsigned char   shrink_buf_result;      /* Reason for call failing
+                                                  Zero is Good return */
+       unsigned char   shrink_buf_init;        /* Non-Zero if it caused an
+                                                  xxinit call. */
+
+       unsigned char   shrink_buf_anports;     /* Number of async ports  */
+       unsigned char   shrink_buf_snports;     /* Number of sync  ports */
+       unsigned char   shrink_buf_type;        /* Board type 1 = PC/Xi,
+                                                             2 = PC/Xm,
+                                                             3 = PC/Xe
+                                                             4 = MC/Xi
+                                                             5 = COMX/i */
+       unsigned char   shrink_buf_card;        /* Card number */
+
+};
+
+/************************************************************************
+ * Structure to get driver status information
+ ************************************************************************/
+struct digi_dinfo {
+       unsigned long   dinfo_nboards;          /* # boards configured  */
+       char            dinfo_reserved[12];     /* for future expansion */
+       char            dinfo_version[16];      /* driver version       */
+};
+
+#define        DIGI_GETDD      ('d'<<8) | 248          /* get driver info      */
+
+/************************************************************************
+ * Structure used with ioctl commands for per-board information
+ *
+ * physsize and memsize differ when board has "windowed" memory
+ ************************************************************************/
+struct digi_info {
+       unsigned long   info_bdnum;             /* Board number (0 based)  */
+       unsigned long   info_ioport;            /* io port address         */
+       unsigned long   info_physaddr;          /* memory address          */
+       unsigned long   info_physsize;          /* Size of host mem window */
+       unsigned long   info_memsize;           /* Amount of dual-port mem */
+                                               /* on board                */
+       unsigned short  info_bdtype;            /* Board type              */
+       unsigned short  info_nports;            /* number of ports         */
+       char            info_bdstate;           /* board state             */
+       char            info_reserved[7];       /* for future expansion    */
+};
+
+#define        DIGI_GETBD      ('d'<<8) | 249          /* get board info          */
+
+struct digi_stat {
+       unsigned int    info_chan;              /* Channel number (0 based)  */
+       unsigned int    info_brd;               /* Board number (0 based)  */
+       unsigned long   info_cflag;             /* cflag for channel       */
+       unsigned long   info_iflag;             /* iflag for channel       */
+       unsigned long   info_oflag;             /* oflag for channel       */
+       unsigned long   info_mstat;             /* mstat for channel       */
+       unsigned long   info_tx_data;           /* tx_data for channel       */
+       unsigned long   info_rx_data;           /* rx_data for channel       */
+       unsigned long   info_hflow;             /* hflow for channel       */
+       unsigned long   info_reserved[8];       /* for future expansion    */
+};
+
+#define        DIGI_GETSTAT    ('d'<<8) | 244          /* get board info          */
+/************************************************************************
+ *
+ * Structure used with ioctl commands for per-channel information
+ *
+ ************************************************************************/
+struct digi_ch {
+       unsigned long   info_bdnum;             /* Board number (0 based)  */
+       unsigned long   info_channel;           /* Channel index number    */
+       unsigned long   info_ch_cflag;          /* Channel cflag           */
+       unsigned long   info_ch_iflag;          /* Channel iflag           */
+       unsigned long   info_ch_oflag;          /* Channel oflag           */
+       unsigned long   info_chsize;            /* Channel structure size  */
+       unsigned long   info_sleep_stat;        /* sleep status            */
+       dev_t           info_dev;               /* device number           */
+       unsigned char   info_initstate;         /* Channel init state      */
+       unsigned char   info_running;           /* Channel running state   */
+       long            reserved[8];            /* reserved for future use */
+};
+
+/*
+* This structure is used with the DIGI_FEPCMD ioctl to
+* tell the driver which port to send the command for.
+*/
+struct digi_cmd {
+       int     cmd;
+       int     word;
+       int     ncmds;
+       int     chan; /* channel index (zero based) */
+       int     bdid; /* board index (zero based) */
+};
+
+/*
+*  info_sleep_stat defines
+*/
+#define INFO_RUNWAIT   0x0001
+#define INFO_WOPEN     0x0002
+#define INFO_TTIOW     0x0004
+#define INFO_CH_RWAIT  0x0008
+#define INFO_CH_WEMPTY 0x0010
+#define INFO_CH_WLOW   0x0020
+#define INFO_XXBUF_BUSY 0x0040
+
+#define        DIGI_GETCH      ('d'<<8) | 245          /* get board info          */
+
+/* Board type definitions */
+
+#define        SUBTYPE         0007
+#define        T_PCXI          0000
+#define T_PCXM         0001
+#define T_PCXE         0002
+#define T_PCXR         0003
+#define T_SP           0004
+#define T_SP_PLUS      0005
+#      define T_HERC   0000
+#      define T_HOU    0001
+#      define T_LON    0002
+#      define T_CHA    0003
+#define FAMILY         0070
+#define T_COMXI                0000
+#define T_PCXX         0010
+#define T_CX           0020
+#define T_EPC          0030
+#define        T_PCLITE        0040
+#define        T_SPXX          0050
+#define        T_AVXX          0060
+#define T_DXB          0070
+#define T_A2K_4_8      0070
+#define BUSTYPE                0700
+#define T_ISABUS       0000
+#define T_MCBUS                0100
+#define        T_EISABUS       0200
+#define        T_PCIBUS        0400
+
+/* Board State Definitions */
+
+#define        BD_RUNNING      0x0
+#define        BD_REASON       0x7f
+#define        BD_NOTFOUND     0x1
+#define        BD_NOIOPORT     0x2
+#define        BD_NOMEM        0x3
+#define        BD_NOBIOS       0x4
+#define        BD_NOFEP        0x5
+#define        BD_FAILED       0x6
+#define BD_ALLOCATED   0x7
+#define BD_TRIBOOT     0x8
+#define        BD_BADKME       0x80
+
+#define DIGI_LOOPBACK        ('d'<<8) | 252            /* Enable/disable UART internal loopback */
+#define DIGI_SPOLL            ('d'<<8) | 254           /* change poller rate   */
+
+#define DIGI_SETCUSTOMBAUD     _IOW('e', 106, int)     /* Set integer baud rate */
+#define DIGI_GETCUSTOMBAUD     _IOR('e', 107, int)     /* Get integer baud rate */
+#define DIGI_RESET_PORT                ('e'<<8) | 93           /* Reset port           */
+
+/************************************************************************
+ * Channel information structure.
+ ************************************************************************/
+struct channel_t {
+       int magic;                      /* Channel Magic Number         */
+       struct bs_t     *ch_bs;         /* Base structure pointer       */
+       struct cm_t     *ch_cm;         /* Command queue pointer        */
+       struct board_t *ch_bd;          /* Board structure pointer      */
+       unsigned char *ch_vaddr;        /* FEP memory origin            */
+       unsigned char *ch_taddr;        /* Write buffer origin          */
+       unsigned char *ch_raddr;        /* Read buffer origin           */
+       struct digi_t  ch_digi;         /* Transparent Print structure  */
+       struct un_t ch_tun;             /* Terminal unit info           */
+       struct un_t ch_pun;             /* Printer unit info            */
+
+       spinlock_t      ch_lock;        /* provide for serialization */
+       wait_queue_head_t ch_flags_wait;
+
+       u32     pscan_state;
+       uchar   pscan_savechar;
+
+       u32 ch_portnum;                 /* Port number, 0 offset.       */
+       u32 ch_open_count;              /* open count                   */
+       u32     ch_flags;               /* Channel flags                */
+
+
+       u32     ch_close_delay;         /* How long we should drop RTS/DTR for */
+
+       u32     ch_cpstime;             /* Time for CPS calculations    */
+
+       tcflag_t ch_c_iflag;            /* channel iflags               */
+       tcflag_t ch_c_cflag;            /* channel cflags               */
+       tcflag_t ch_c_oflag;            /* channel oflags               */
+       tcflag_t ch_c_lflag;            /* channel lflags               */
+
+       u16  ch_fepiflag;            /* FEP tty iflags               */
+       u16  ch_fepcflag;               /* FEP tty cflags               */
+       u16  ch_fepoflag;               /* FEP tty oflags               */
+       u16  ch_wopen;                  /* Waiting for open process cnt */
+       u16  ch_tstart;                 /* Transmit buffer start        */
+       u16  ch_tsize;                  /* Transmit buffer size         */
+       u16  ch_rstart;                 /* Receive buffer start         */
+       u16  ch_rsize;                  /* Receive buffer size          */
+       u16  ch_rdelay;                 /* Receive delay time           */
+
+       u16     ch_tlw;                 /* Our currently set low water mark */
+
+       u16  ch_cook;                   /* Output character mask        */
+
+       uchar   ch_card;                /* Card channel is on           */
+       uchar   ch_stopc;               /* Stop character               */
+       uchar   ch_startc;              /* Start character              */
+
+       uchar   ch_mostat;              /* FEP output modem status      */
+       uchar   ch_mistat;              /* FEP input modem status       */
+       uchar   ch_mforce;              /* Modem values to be forced    */
+       uchar   ch_mval;                /* Force values                 */
+       uchar   ch_fepstopc;            /* FEP stop character           */
+       uchar   ch_fepstartc;           /* FEP start character          */
+
+       uchar   ch_astopc;              /* Auxiliary Stop character     */
+       uchar   ch_astartc;             /* Auxiliary Start character    */
+       uchar   ch_fepastopc;           /* Auxiliary FEP stop char      */
+       uchar   ch_fepastartc;          /* Auxiliary FEP start char     */
+
+       uchar   ch_hflow;               /* FEP hardware handshake       */
+       uchar   ch_dsr;                 /* stores real dsr value        */
+       uchar   ch_cd;                  /* stores real cd value         */
+       uchar   ch_tx_win;              /* channel tx buffer window     */
+       uchar   ch_rx_win;              /* channel rx buffer window     */
+       uint    ch_custom_speed;        /* Custom baud, if set          */
+       uint    ch_baud_info;           /* Current baud info for /proc output   */
+       ulong   ch_rxcount;             /* total of data received so far        */
+       ulong   ch_txcount;             /* total of data transmitted so far     */
+       ulong   ch_err_parity;          /* Count of parity errors on channel    */
+       ulong   ch_err_frame;           /* Count of framing errors on channel   */
+       ulong   ch_err_break;           /* Count of breaks on channel   */
+       ulong   ch_err_overrun;         /* Count of overruns on channel */
+
+       uint ch_sniff_in;
+       uint ch_sniff_out;
+       char *ch_sniff_buf;             /* Sniff buffer for proc */
+       ulong ch_sniff_flags;           /* Channel flags                */
+       wait_queue_head_t ch_sniff_wait;
+};
+
+/************************************************************************
+ * Command structure definition.
+ ************************************************************************/
+struct cm_t {
+       volatile unsigned short cm_head;        /* Command buffer head offset   */
+       volatile unsigned short cm_tail;        /* Command buffer tail offset   */
+       volatile unsigned short cm_start;       /* start offset of buffer       */
+       volatile unsigned short cm_max;         /* last offset of buffer        */
+};
+
+/************************************************************************
+ * Event structure definition.
+ ************************************************************************/
+struct ev_t {
+       volatile unsigned short ev_head;        /* Command buffer head offset   */
+       volatile unsigned short ev_tail;        /* Command buffer tail offset   */
+       volatile unsigned short ev_start;       /* start offset of buffer       */
+       volatile unsigned short ev_max;         /* last offset of buffer        */
+};
+
+/************************************************************************
+ * Download buffer structure.
+ ************************************************************************/
+struct downld_t {
+       uchar   dl_type;                /* Header                       */
+       uchar   dl_seq;                 /* Download sequence            */
+       ushort  dl_srev;                /* Software revision number     */
+       ushort  dl_lrev;                /* Low revision number          */
+       ushort  dl_hrev;                /* High revision number         */
+       ushort  dl_seg;                 /* Start segment address        */
+       ushort  dl_size;                /* Number of bytes to download  */
+       uchar   dl_data[1024];          /* Download data                */
+};
+
+/************************************************************************
+ * Per channel buffer structure
+ ************************************************************************
+ *              Base Structure Entries Usage Meanings to Host           *
+ *                                                                      *
+ *        W = read write        R = read only                           *
+ *        C = changed by commands only                                  *
+ *        U = unknown (may be changed w/o notice)                       *
+ ************************************************************************/
+struct bs_t {
+       volatile unsigned short  tp_jmp;        /* Transmit poll jump            */
+       volatile unsigned short  tc_jmp;        /* Cooked procedure jump         */
+       volatile unsigned short  ri_jmp;        /* Not currently used            */
+       volatile unsigned short  rp_jmp;        /* Receive poll jump             */
+
+       volatile unsigned short  tx_seg;        /* W  Tx segment         */
+       volatile unsigned short  tx_head;       /* W  Tx buffer head offset     */
+       volatile unsigned short  tx_tail;       /* R  Tx buffer tail offset     */
+       volatile unsigned short  tx_max;        /* W  Tx buffer size - 1         */
+
+       volatile unsigned short  rx_seg;        /* W  Rx segment                */
+       volatile unsigned short  rx_head;       /* W  Rx buffer head offset     */
+       volatile unsigned short  rx_tail;       /* R  Rx buffer tail offset     */
+       volatile unsigned short  rx_max;        /* W  Rx buffer size - 1         */
+
+       volatile unsigned short  tx_lw;         /* W  Tx buffer low water mark  */
+       volatile unsigned short  rx_lw;         /* W  Rx buffer low water mark  */
+       volatile unsigned short  rx_hw;         /* W  Rx buffer high water mark */
+       volatile unsigned short  incr;          /* W  Increment to next channel */
+
+       volatile unsigned short  fepdev;        /* U  SCC device base address    */
+       volatile unsigned short  edelay;        /* W  Exception delay            */
+       volatile unsigned short  blen;          /* W  Break length              */
+       volatile unsigned short  btime;         /* U  Break complete time       */
+
+       volatile unsigned short  iflag;         /* C  UNIX input flags          */
+       volatile unsigned short  oflag;         /* C  UNIX output flags         */
+       volatile unsigned short  cflag;         /* C  UNIX control flags        */
+       volatile unsigned short  wfill[13];     /* U  Reserved for expansion    */
+
+       volatile unsigned char   num;           /* U  Channel number            */
+       volatile unsigned char   ract;          /* U  Receiver active counter   */
+       volatile unsigned char   bstat;         /* U  Break status bits         */
+       volatile unsigned char   tbusy;         /* W  Transmit busy             */
+       volatile unsigned char   iempty;        /* W  Transmit empty event enable */
+       volatile unsigned char   ilow;          /* W  Transmit low-water event enable */
+       volatile unsigned char   idata;         /* W  Receive data interrupt enable */
+       volatile unsigned char   eflag;         /* U  Host event flags          */
+
+       volatile unsigned char   tflag;         /* U  Transmit flags            */
+       volatile unsigned char   rflag;         /* U  Receive flags             */
+       volatile unsigned char   xmask;         /* U  Transmit ready flags      */
+       volatile unsigned char   xval;          /* U  Transmit ready value      */
+       volatile unsigned char   m_stat;        /* RC Modem status bits          */
+       volatile unsigned char   m_change;      /* U  Modem bits which changed  */
+       volatile unsigned char   m_int;         /* W  Modem interrupt enable bits */
+       volatile unsigned char   m_last;        /* U  Last modem status         */
+
+       volatile unsigned char   mtran;         /* C   Unreported modem trans   */
+       volatile unsigned char   orun;          /* C   Buffer overrun occurred  */
+       volatile unsigned char   astartc;       /* W   Auxiliary Xon char       */
+       volatile unsigned char   astopc;        /* W   Auxiliary Xoff char      */
+       volatile unsigned char   startc;        /* W   Xon character             */
+       volatile unsigned char   stopc;         /* W   Xoff character           */
+       volatile unsigned char   vnextc;        /* W   Vnext character           */
+       volatile unsigned char   hflow;         /* C   Software flow control    */
+       
+       volatile unsigned char   fillc;         /* U   Delay Fill character     */
+       volatile unsigned char   ochar;         /* U   Saved output character   */
+       volatile unsigned char   omask;         /* U   Output character mask    */
+
+       volatile unsigned char   bfill[13];     /* U   Reserved for expansion   */
+
+       volatile unsigned char   scc[16];       /* U   SCC registers            */
+};
+
+struct cnode {
+       struct cnode *next;
+       int type;
+       int numbrd;
+
+       union {
+               struct {
+                       char  type;     /* Board Type           */
+                       short port;     /* I/O Address          */
+                       char  *portstr; /* I/O Address in string */
+                       long  addr;     /* Memory Address       */
+                       char  *addrstr; /* Memory Address in string */
+                       long  pcibus;   /* PCI BUS              */
+                       char  *pcibusstr; /* PCI BUS in string */
+                       long  pcislot;  /* PCI SLOT             */
+                       char  *pcislotstr; /* PCI SLOT in string */
+                       char  nport;    /* Number of Ports      */
+                       char  *id;      /* tty id               */
+                       int   start;    /* start of tty counting */
+                       char  *method;  /* Install method       */
+                       char  v_type;
+                       char  v_port;
+                       char  v_addr;
+                       char  v_pcibus;
+                       char  v_pcislot;
+                       char  v_nport;
+                       char  v_id;
+                       char  v_start;
+                       char  v_method;
+                       char  line1;
+                       char  line2;
+                       char  conc1;   /* total concs in line1 */
+                       char  conc2;   /* total concs in line2 */
+                       char  module1; /* total modules for line1 */
+                       char  module2; /* total modules for line2 */
+                       char  *status; /* config status */
+                       char  *dimstatus;        /* Y/N */
+                       int   status_index; /* field pointer */
+               } board;
+
+               struct {
+                       char  *cable;
+                       char  v_cable;
+                       char  speed;
+                       char  v_speed;
+               } line;
+
+               struct {
+                       char  type;
+                       char  *connect;
+                       char  speed;
+                       char  nport;
+                       char  *id;
+                       char  *idstr;
+                       int   start;
+                       char  v_type;
+                       char  v_connect;
+                       char  v_speed;
+                       char  v_nport;
+                       char  v_id;
+                       char  v_start;
+               } conc;
+
+               struct {
+                       char type;
+                       char nport;
+                       char *id;
+                       char *idstr;
+                       int  start;
+                       char v_type;
+                       char v_nport;
+                       char v_id;
+                       char v_start;
+               } module;
+
+               char *ttyname;
+
+               char *cuname;
+
+               char *printname;
+
+               int  majornumber;
+
+               int  altpin;
+
+               int  ttysize;
+
+               int  chsize;
+
+               int  bssize;
+
+               int  unsize;
+
+               int  f2size;
+
+               int  vpixsize;
+
+               int  useintr;
+       } u;
+};
+
+#endif
diff --git a/drivers/staging/dgap/dgap_conf.h b/drivers/staging/dgap/dgap_conf.h
deleted file mode 100644 (file)
index 484ed72..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *****************************************************************************
- *
- *     dgap_conf.h - Header file for installations and parse files.
- *
- *     $Id: dgap_conf.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef _DGAP_CONF_H
-#define _DGAP_CONF_H
-
-#define NULLNODE 0             /* header node, not used */
-#define BNODE 1                        /* Board node */
-#define LNODE 2                        /* Line node */
-#define CNODE 3                        /* Concentrator node */
-#define MNODE 4                        /* EBI Module node */
-#define TNODE 5                        /* tty name prefix node */
-#define        CUNODE 6                /* cu name prefix (non-SCO) */
-#define PNODE 7                        /* trans. print prefix node */
-#define JNODE 8                        /* maJor number node */
-#define ANODE 9                        /* altpin */
-#define        TSNODE 10               /* tty structure size */
-#define CSNODE 11              /* channel structure size */
-#define BSNODE 12              /* board structure size */
-#define USNODE 13              /* unit schedule structure size */
-#define FSNODE 14              /* f2200 structure size */
-#define VSNODE 15              /* size of VPIX structures */
-#define INTRNODE 16            /* enable interrupt */
-
-/* Enumeration of tokens */
-#define        BEGIN   1
-#define        END     2
-#define        BOARD   10
-
-#define EPCFS  11 /* start of EPC family definitions */
-#define        ICX             11
-#define        MCX             13
-#define PCX    14
-#define        IEPC    15
-#define        EEPC    16
-#define        MEPC    17
-#define        IPCM    18
-#define        EPCM    19
-#define        MPCM    20
-#define PEPC   21
-#define PPCM   22
-#ifdef CP
-#define ICP     23
-#define ECP     24
-#define MCP     25
-#endif
-#define EPCFE  25 /* end of EPC family definitions */
-#define        PC2E    26
-#define        PC4E    27
-#define        PC4E8K  28
-#define        PC8E    29
-#define        PC8E8K  30
-#define        PC16E   31
-#define MC2E8K  34
-#define MC4E8K  35
-#define MC8E8K  36
-
-#define AVANFS 42      /* start of Avanstar family definitions */
-#define A8P    42
-#define A16P   43
-#define AVANFE 43      /* end of Avanstar family definitions */
-
-#define DA2000FS       44      /* start of AccelePort 2000 family definitions */
-#define DA22           44 /* AccelePort 2002 */
-#define DA24           45 /* AccelePort 2004 */
-#define DA28           46 /* AccelePort 2008 */
-#define DA216          47 /* AccelePort 2016 */
-#define DAR4           48 /* AccelePort RAS 4 port */
-#define DAR8           49 /* AccelePort RAS 8 port */
-#define DDR24          50 /* DataFire RAS 24 port */
-#define DDR30          51 /* DataFire RAS 30 port */
-#define DDR48          52 /* DataFire RAS 48 port */
-#define DDR60          53 /* DataFire RAS 60 port */
-#define DA2000FE       53 /* end of AccelePort 2000/RAS family definitions */
-
-#define PCXRFS 106     /* start of PCXR family definitions */
-#define        APORT4  106
-#define        APORT8  107
-#define PAPORT4 108
-#define PAPORT8 109
-#define APORT4_920I    110
-#define APORT8_920I    111
-#define APORT4_920P    112
-#define APORT8_920P    113
-#define APORT2_920P 114
-#define PCXRFE 117     /* end of PCXR family definitions */
-
-#define        LINE    82
-#ifdef T1
-#define T1M    83
-#define E1M    84
-#endif
-#define        CONC    64
-#define        CX      65
-#define        EPC     66
-#define        MOD     67
-#define        PORTS   68
-#define METHOD 69
-#define CUSTOM 70
-#define BASIC  71
-#define STATUS 72
-#define MODEM  73
-/* The following tokens can appear in multiple places */
-#define        SPEED   74
-#define        NPORTS  75
-#define        ID      76
-#define CABLE  77
-#define CONNECT        78
-#define        IO      79
-#define        MEM     80
-#define DPSZ   81
-
-#define        TTYN    90
-#define        CU      91
-#define        PRINT   92
-#define        XPRINT  93
-#define CMAJOR   94
-#define ALTPIN  95
-#define STARTO 96
-#define USEINTR  97
-#define PCIINFO  98
-
-#define        TTSIZ   100
-#define        CHSIZ   101
-#define BSSIZ  102
-#define        UNTSIZ  103
-#define        F2SIZ   104
-#define        VPSIZ   105
-
-#define        TOTAL_BOARD     2
-#define        CURRENT_BRD     4
-#define        BOARD_TYPE      6
-#define        IO_ADDRESS      8
-#define        MEM_ADDRESS     10
-
-#define        FIELDS_PER_PAGE 18
-
-#define TB_FIELD       1
-#define CB_FIELD       3
-#define BT_FIELD       5
-#define IO_FIELD       7
-#define ID_FIELD       8
-#define ME_FIELD       9
-#define TTY_FIELD      11
-#define CU_FIELD       13
-#define PR_FIELD       15
-#define MPR_FIELD      17
-
-#define        MAX_FIELD       512
-
-#define        INIT            0
-#define        NITEMS          128
-#define MAX_ITEM       512
-
-#define        DSCRINST        1
-#define        DSCRNUM         3
-#define        ALTPINQ         5
-#define        SSAVE           7
-
-#define        DSCR            "32"
-#define        ONETONINE       "123456789"
-#define        ALL             "1234567890"
-
-
-struct cnode {
-       struct cnode *next;
-       int type;
-       int numbrd;
-
-       union {
-               struct {
-                       char  type;     /* Board Type           */
-                       short port;     /* I/O Address          */
-                       char  *portstr; /* I/O Address in string */
-                       long  addr;     /* Memory Address       */
-                       char  *addrstr; /* Memory Address in string */
-                       long  pcibus;   /* PCI BUS              */
-                       char  *pcibusstr; /* PCI BUS in string */
-                       long  pcislot;  /* PCI SLOT             */
-                       char  *pcislotstr; /* PCI SLOT in string */
-                       char  nport;    /* Number of Ports      */
-                       char  *id;      /* tty id               */
-                       int   start;    /* start of tty counting */
-                       char  *method;  /* Install method       */
-                       char  v_type;
-                       char  v_port;
-                       char  v_addr;
-                       char  v_pcibus;
-                       char  v_pcislot;
-                       char  v_nport;
-                       char  v_id;
-                       char  v_start;
-                       char  v_method;
-                       char  line1;
-                       char  line2;
-                       char  conc1;   /* total concs in line1 */
-                       char  conc2;   /* total concs in line2 */
-                       char  module1; /* total modules for line1 */
-                       char  module2; /* total modules for line2 */
-                       char  *status; /* config status */
-                       char  *dimstatus;        /* Y/N */
-                       int   status_index; /* field pointer */
-               } board;
-
-               struct {
-                       char  *cable;
-                       char  v_cable;
-                       char  speed;
-                       char  v_speed;
-               } line;
-
-               struct {
-                       char  type;
-                       char  *connect;
-                       char  speed;
-                       char  nport;
-                       char  *id;
-                       char  *idstr;
-                       int   start;
-                       char  v_type;
-                       char  v_connect;
-                       char  v_speed;
-                       char  v_nport;
-                       char  v_id;
-                       char  v_start;
-               } conc;
-
-               struct {
-                       char type;
-                       char nport;
-                       char *id;
-                       char *idstr;
-                       int  start;
-                       char v_type;
-                       char v_nport;
-                       char v_id;
-                       char v_start;
-               } module;
-
-               char *ttyname;
-
-               char *cuname;
-
-               char *printname;
-
-               int  majornumber;
-
-               int  altpin;
-
-               int  ttysize;
-
-               int  chsize;
-
-               int  bssize;
-
-               int  unsize;
-
-               int  f2size;
-
-               int  vpixsize;
-
-               int  useintr;
-       } u;
-};
-
-#endif
diff --git a/drivers/staging/dgap/dgap_downld.h b/drivers/staging/dgap/dgap_downld.h
deleted file mode 100644 (file)
index 910a45d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- * $Id: dgap_downld.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- */
-
-/*
-** downld.h
-**  - describes the interface between the user level download process
-**    and the concentrator download driver.
-*/
-
-#ifndef _DGAP_DOWNLD_H_
-#define _DGAP_DOWNLD_H_
-
-
-struct fepimg {
-    int type;                          /* board type */
-    int        len;                            /* length of image */
-    char fepimage[1];                  /* beginning of image */
-};
-
-struct downldio {
-    unsigned int req_type;             /* FEP or concentrator */
-    unsigned int bdid;                 /* opaque board identifier */
-    union {
-       struct downld_t dl;             /* download structure */
-       struct fepimg   fi;             /* fep/bios image structure */
-    } image;
-};
-
-#define DIGI_DLREQ_GET (('d'<<8) | 220)
-#define DIGI_DLREQ_SET (('d'<<8) | 221)
-
-#define DIGI_DL_NUKE    (('d'<<8) | 222) /* Not really a dl request, but
-                                         dangerous enuff to not put in
-                                         digi.h */
-/* Packed bits of intarg for DIGI_DL_NUKE */
-#define DIGI_NUKE_RESET_ALL     (1 << 31)
-#define DIGI_NUKE_INHIBIT_POLLER (1 << 30)
-#define DIGI_NUKE_BRD_NUMB        0x0f
-
-
-
-#define        DLREQ_BIOS      0
-#define        DLREQ_FEP       1
-#define        DLREQ_CONC      2
-#define        DLREQ_CONFIG    3
-#define DLREQ_DEVCREATE 4
-
-#endif
diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c
deleted file mode 100644 (file)
index 11dd6dd..0000000
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
- * $Id: dgap_driver.c,v 1.3 2011/06/21 10:35:16 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>       /* For udelay */
-#include <linux/slab.h>
-#include <asm/uaccess.h>       /* For copy_from_user/copy_to_user */
-#include <linux/sched.h>
-
-#include "dgap_driver.h"
-#include "dgap_pci.h"
-#include "dgap_fep5.h"
-#include "dgap_tty.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-#include "dgap_trace.h"
-#include "dgap_sysfs.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Digi International, http://www.digi.com");
-MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line");
-MODULE_SUPPORTED_DEVICE("dgap");
-
-/*
- * insmod command line overrideable parameters
- *
- * NOTE: we use a set of macros to create the variables, which allows
- * us to specify the variable type, name, initial value, and description.
- */
-PARM_INT(debug,                0x00,           0644,   "Driver debugging level");
-PARM_INT(rawreadok,    1,              0644,   "Bypass flip buffers on input");
-PARM_INT(trcbuf_size,  0x100000,       0644,   "Debugging trace buffer size.");
-
-
-/**************************************************************************
- *
- * protos for this file
- *
- */
-
-static int             dgap_start(void);
-static void            dgap_init_globals(void);
-static int             dgap_found_board(struct pci_dev *pdev, int id);
-static void            dgap_cleanup_board(struct board_t *brd);
-static void            dgap_poll_handler(ulong dummy);
-static int             dgap_init_pci(void);
-static int             dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void            dgap_remove_one(struct pci_dev *dev);
-static int             dgap_probe1(struct pci_dev *pdev, int card_type);
-static void            dgap_mbuf(struct board_t *brd, const char *fmt, ...);
-static int             dgap_do_remap(struct board_t *brd);
-static irqreturn_t     dgap_intr(int irq, void *voidbrd);
-
-/* Driver load/unload functions */
-int                    dgap_init_module(void);
-void                   dgap_cleanup_module(void);
-
-module_init(dgap_init_module);
-module_exit(dgap_cleanup_module);
-
-
-/*
- * File operations permitted on Control/Management major.
- */
-static struct file_operations DgapBoardFops =
-{
-       .owner          =       THIS_MODULE,
-};
-
-
-/*
- * Globals
- */
-uint                   dgap_NumBoards;
-struct board_t         *dgap_Board[MAXBOARDS];
-DEFINE_SPINLOCK(dgap_global_lock);
-ulong                  dgap_poll_counter;
-char                   *dgap_config_buf;
-int                    dgap_driver_state = DRIVER_INITIALIZED;
-DEFINE_SPINLOCK(dgap_dl_lock);
-wait_queue_head_t      dgap_dl_wait;
-int                    dgap_dl_action;
-int                    dgap_poll_tick = 20;    /* Poll interval - 20 ms */
-
-/*
- * Static vars.
- */
-static int             dgap_Major_Control_Registered = FALSE;
-static uint            dgap_driver_start = FALSE;
-
-static struct class *  dgap_class;
-
-/*
- * Poller stuff
- */
-static                         DEFINE_SPINLOCK(dgap_poll_lock);        /* Poll scheduling lock */
-static ulong           dgap_poll_time;                         /* Time of next poll */
-static uint            dgap_poll_stop;                         /* Used to tell poller to stop */
-static struct timer_list dgap_poll_timer;
-
-
-static struct pci_device_id dgap_pci_tbl[] = {
-       {       DIGI_VID, PCI_DEVICE_XEM_DID,   PCI_ANY_ID, PCI_ANY_ID, 0, 0,   0 },
-       {       DIGI_VID, PCI_DEVICE_CX_DID,    PCI_ANY_ID, PCI_ANY_ID, 0, 0,   1 },
-       {       DIGI_VID, PCI_DEVICE_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  2 },
-       {       DIGI_VID, PCI_DEVICE_EPCJ_DID,  PCI_ANY_ID, PCI_ANY_ID, 0, 0,   3 },
-       {       DIGI_VID, PCI_DEVICE_920_2_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,   4 },
-       {       DIGI_VID, PCI_DEVICE_920_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,   5 },
-       {       DIGI_VID, PCI_DEVICE_920_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,   6 },
-       {       DIGI_VID, PCI_DEVICE_XR_DID,    PCI_ANY_ID, PCI_ANY_ID, 0, 0,   7 },
-       {       DIGI_VID, PCI_DEVICE_XRJ_DID,   PCI_ANY_ID, PCI_ANY_ID, 0, 0,   8 },
-       {       DIGI_VID, PCI_DEVICE_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  9 },
-       {       DIGI_VID, PCI_DEVICE_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  10 },
-       {       DIGI_VID, PCI_DEVICE_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
-       {       DIGI_VID, PCI_DEVICE_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
-       {       DIGI_VID, PCI_DEVICE_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
-       {       DIGI_VID, PCI_DEVICE_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,  14 },
-       {0,}                                    /* 0 terminated list. */
-};
-MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
-
-
-/*
- * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
- */
-struct board_id {
-       uint config_type;
-       uchar *name;
-       uint maxports;
-       uint dpatype;
-};
-
-static struct board_id dgap_Ids[] =
-{
-       {       PPCM,           PCI_DEVICE_XEM_NAME,    64,     (T_PCXM | T_PCLITE | T_PCIBUS)  },
-       {       PCX,            PCI_DEVICE_CX_NAME,     128,    (T_CX | T_PCIBUS)               },
-       {       PCX,            PCI_DEVICE_CX_IBM_NAME, 128,    (T_CX | T_PCIBUS)               },
-       {       PEPC,           PCI_DEVICE_EPCJ_NAME,   224,    (T_EPC  | T_PCIBUS)             },
-       {       APORT2_920P,    PCI_DEVICE_920_2_NAME,  2,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       APORT4_920P,    PCI_DEVICE_920_4_NAME,  4,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       APORT8_920P,    PCI_DEVICE_920_8_NAME,  8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PAPORT8,        PCI_DEVICE_XR_NAME,     8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PAPORT8,        PCI_DEVICE_XRJ_NAME,    8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PAPORT8,        PCI_DEVICE_XR_422_NAME, 8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PAPORT8,        PCI_DEVICE_XR_IBM_NAME, 8,      (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PAPORT8,        PCI_DEVICE_XR_SAIP_NAME, 8,     (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PAPORT8,        PCI_DEVICE_XR_BULL_NAME, 8,     (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       APORT8_920P,    PCI_DEVICE_920_8_HP_NAME, 8,    (T_PCXR | T_PCLITE | T_PCIBUS)  },
-       {       PPCM,           PCI_DEVICE_XEM_HP_NAME, 64,     (T_PCXM | T_PCLITE | T_PCIBUS)  },
-       {0,}                                            /* 0 terminated list. */
-};
-
-static struct pci_driver dgap_driver = {
-       .name           = "dgap",
-       .probe          = dgap_init_one,
-       .id_table       = dgap_pci_tbl,
-       .remove         = dgap_remove_one,
-};
-
-
-char *dgap_state_text[] = {
-       "Board Failed",
-       "Configuration for board not found.\n\t\t\tRun mpi to configure board.",
-       "Board Found",
-       "Need Reset",
-       "Finished Reset",
-       "Need Config",
-       "Finished Config",
-       "Need Device Creation",
-       "Requested Device Creation",
-       "Finished Device Creation",
-       "Need BIOS Load",
-       "Requested BIOS",
-       "Doing BIOS Load",
-       "Finished BIOS Load",
-       "Need FEP Load",
-       "Requested FEP",
-       "Doing FEP Load",
-       "Finished FEP Load",
-       "Requested PROC creation",
-       "Finished PROC creation",
-       "Board READY",
-};
-
-char *dgap_driver_state_text[] = {
-       "Driver Initialized",
-       "Driver needs configuration load.",
-       "Driver requested configuration from download daemon.",
-       "Driver Ready."
-};
-
-
-
-/************************************************************************
- *
- * Driver load/unload functions
- *
- ************************************************************************/
-
-/*
- * init_module()
- *
- * Module load.  This is where it all starts.
- */
-int dgap_init_module(void)
-{
-       int rc = 0;
-
-       APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));
-
-       /*
-        * Initialize global stuff
-        */
-       rc = dgap_start();
-
-       if (rc < 0) {
-               return(rc);
-       }
-
-       /*
-        * Find and configure all the cards
-        */
-       rc = dgap_init_pci();
-
-       /*
-        * If something went wrong in the scan, bail out of driver.
-        */
-       if (rc < 0) {
-               /* Only unregister the pci driver if it was actually registered. */
-               if (dgap_NumBoards)
-                       pci_unregister_driver(&dgap_driver);
-               else
-                       printk("WARNING: dgap driver load failed.  No DGAP boards found.\n");
-
-               dgap_cleanup_module();
-       }
-       else {
-               dgap_create_driver_sysfiles(&dgap_driver);
-       }
-
-       DPR_INIT(("Finished init_module. Returning %d\n", rc));
-       return (rc);
-}
-
-
-/*
- * Start of driver.
- */
-static int dgap_start(void)
-{
-       int rc = 0;
-       unsigned long flags;
-
-       if (dgap_driver_start == FALSE) {
-
-               dgap_driver_start = TRUE;
-
-               /* make sure that the globals are init'd before we do anything else */
-               dgap_init_globals();
-
-               dgap_NumBoards = 0;
-
-               APR(("For the tools package or updated drivers please visit http://www.digi.com\n"));
-
-               /*
-                * Register our base character device into the kernel.
-                * This allows the download daemon to connect to the downld device
-                * before any of the boards are init'ed.
-                */
-               if (!dgap_Major_Control_Registered) {
-                       /*
-                        * Register management/dpa devices
-                        */
-                       rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops);
-                       if (rc < 0) {
-                               APR(("Can't register dgap driver device (%d)\n", rc));
-                               return (rc);
-                       }
-
-                       dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
-                       device_create(dgap_class, NULL,
-                               MKDEV(DIGI_DGAP_MAJOR, 0),
-                               NULL, "dgap_mgmt");
-                       device_create(dgap_class, NULL,
-                               MKDEV(DIGI_DGAP_MAJOR, 1),
-                               NULL, "dgap_downld");
-                       dgap_Major_Control_Registered = TRUE;
-               }
-
-               /*
-                * Init any global tty stuff.
-                */
-               rc = dgap_tty_preinit();
-
-               if (rc < 0) {
-                       APR(("tty preinit - not enough memory (%d)\n", rc));
-                       return(rc);
-               }
-
-               /* Start the poller */
-               DGAP_LOCK(dgap_poll_lock, flags);
-               init_timer(&dgap_poll_timer);
-               dgap_poll_timer.function = dgap_poll_handler;
-               dgap_poll_timer.data = 0;
-               dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
-               dgap_poll_timer.expires = dgap_poll_time;
-               DGAP_UNLOCK(dgap_poll_lock, flags);
-
-               add_timer(&dgap_poll_timer);
-
-               dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
-       }
-
-       return (rc);
-}
-
-
-/*
- * Register pci driver, and return how many boards we have.
- */
-static int dgap_init_pci(void)
-{
-       return pci_register_driver(&dgap_driver);
-}
-
-
-/* returns count (>= 0), or negative on error */
-static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       int rc;
-
-       /* wake up and enable device */
-       rc = pci_enable_device(pdev);
-
-       if (rc < 0) {
-               rc = -EIO;
-       } else {
-               rc = dgap_probe1(pdev, ent->driver_data);
-               if (rc == 0) {
-                       dgap_NumBoards++;
-                       DPR_INIT(("Incrementing numboards to %d\n", dgap_NumBoards));
-               }
-       }
-       return rc;
-}
-
-
-static int dgap_probe1(struct pci_dev *pdev, int card_type)
-{
-       return dgap_found_board(pdev, card_type);
-}
-
-
-static void dgap_remove_one(struct pci_dev *dev)
-{
-       /* Do Nothing */
-}
-
-
-/*
- * dgap_cleanup_module()
- *
- * Module unload.  This is where it all ends.
- */
-void dgap_cleanup_module(void)
-{
-       int i;
-       ulong lock_flags;
-
-       DGAP_LOCK(dgap_poll_lock, lock_flags);
-       dgap_poll_stop = 1;
-       DGAP_UNLOCK(dgap_poll_lock, lock_flags);
-
-       /* Turn off poller right away. */
-       del_timer_sync( &dgap_poll_timer);
-
-       dgap_remove_driver_sysfiles(&dgap_driver);
-
-
-       if (dgap_Major_Control_Registered) {
-               device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
-               device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1));
-               class_destroy(dgap_class);
-               unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
-       }
-
-       kfree(dgap_config_buf);
-
-       for (i = 0; i < dgap_NumBoards; ++i) {
-               dgap_remove_ports_sysfiles(dgap_Board[i]);
-               dgap_tty_uninit(dgap_Board[i]);
-               dgap_cleanup_board(dgap_Board[i]);
-       }
-
-       dgap_tty_post_uninit();
-
-#if defined(DGAP_TRACER)
-       /* last thing, make sure we release the tracebuffer */
-       dgap_tracer_free();
-#endif
-       if (dgap_NumBoards)
-               pci_unregister_driver(&dgap_driver);
-}
-
-
-/*
- * dgap_cleanup_board()
- *
- * Free all the memory associated with a board
- */
-static void dgap_cleanup_board(struct board_t *brd)
-{
-       int i = 0;
-
-        if(!brd || brd->magic != DGAP_BOARD_MAGIC)
-                return;
-
-       if (brd->intr_used && brd->irq)
-               free_irq(brd->irq, brd);
-
-       tasklet_kill(&brd->helper_tasklet);
-
-       if (brd->re_map_port) {
-               release_mem_region(brd->membase + 0x200000, 0x200000);
-               iounmap(brd->re_map_port);
-               brd->re_map_port = NULL;
-       }
-
-       if (brd->re_map_membase) {
-               release_mem_region(brd->membase, 0x200000);
-               iounmap(brd->re_map_membase);
-               brd->re_map_membase = NULL;
-       }
-
-        if (brd->msgbuf_head) {
-                unsigned long flags;
-
-                DGAP_LOCK(dgap_global_lock, flags);
-                brd->msgbuf = NULL;
-                printk("%s", brd->msgbuf_head);
-                kfree(brd->msgbuf_head);
-                brd->msgbuf_head = NULL;
-                DGAP_UNLOCK(dgap_global_lock, flags);
-        }
-
-       /* Free all allocated channels structs */
-       for (i = 0; i < MAXPORTS ; i++) {
-               if (brd->channels[i]) {
-                       kfree(brd->channels[i]);
-                       brd->channels[i] = NULL;
-               }
-       }
-
-       kfree(brd->flipbuf);
-       kfree(brd->flipflagbuf);
-
-       dgap_Board[brd->boardnum] = NULL;
-
-        kfree(brd);
-}
-
-
-/*
- * dgap_found_board()
- *
- * A board has been found, init it.
- */
-static int dgap_found_board(struct pci_dev *pdev, int id)
-{
-       struct board_t *brd;
-       unsigned int pci_irq;
-       int i = 0;
-       unsigned long flags;
-
-       /* get the board structure and prep it */
-       brd = dgap_Board[dgap_NumBoards] =
-       (struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
-       if (!brd) {
-               APR(("memory allocation for board structure failed\n"));
-               return(-ENOMEM);
-       }
-
-       /* make a temporary message buffer for the boot messages */
-       brd->msgbuf = brd->msgbuf_head =
-               (char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
-       if(!brd->msgbuf) {
-               kfree(brd);
-               APR(("memory allocation for board msgbuf failed\n"));
-               return(-ENOMEM);
-       }
-
-       /* store the info for the board we've found */
-       brd->magic = DGAP_BOARD_MAGIC;
-       brd->boardnum = dgap_NumBoards;
-       brd->firstminor = 0;
-       brd->vendor = dgap_pci_tbl[id].vendor;
-       brd->device = dgap_pci_tbl[id].device;
-       brd->pdev = pdev;
-       brd->pci_bus = pdev->bus->number;
-       brd->pci_slot = PCI_SLOT(pdev->devfn);
-       brd->name = dgap_Ids[id].name;
-       brd->maxports = dgap_Ids[id].maxports;
-       brd->type = dgap_Ids[id].config_type;
-       brd->dpatype = dgap_Ids[id].dpatype;
-       brd->dpastatus = BD_NOFEP;
-       init_waitqueue_head(&brd->state_wait);
-
-       DGAP_SPINLOCK_INIT(brd->bd_lock);
-
-       brd->state              = BOARD_FOUND;
-       brd->runwait            = 0;
-       brd->inhibit_poller     = FALSE;
-       brd->wait_for_bios      = 0;
-       brd->wait_for_fep       = 0;
-
-       for (i = 0; i < MAXPORTS; i++) {
-               brd->channels[i] = NULL;
-       }
-
-       /* store which card & revision we have */
-       pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
-       pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
-
-       pci_irq = pdev->irq;
-       brd->irq = pci_irq;
-
-       /* get the PCI Base Address Registers */
-
-       /* Xr Jupiter and EPC use BAR 2 */
-       if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == PCI_DEVICE_EPCJ_DID) {
-               brd->membase     = pci_resource_start(pdev, 2);
-               brd->membase_end = pci_resource_end(pdev, 2);
-       }
-       /* Everyone else uses BAR 0 */
-       else {
-               brd->membase     = pci_resource_start(pdev, 0);
-               brd->membase_end = pci_resource_end(pdev, 0);
-       }
-
-       if (!brd->membase) {
-               APR(("card has no PCI IO resources, failing board.\n"));
-               return -ENODEV;
-       }
-
-       if (brd->membase & 1)
-               brd->membase &= ~3;
-       else
-               brd->membase &= ~15;
-
-       /*
-        * On the PCI boards, there is no IO space allocated
-        * The I/O registers will be in the first 3 bytes of the
-        * upper 2MB of the 4MB memory space.  The board memory
-        * will be mapped into the low 2MB of the 4MB memory space
-        */
-       brd->port = brd->membase + PCI_IO_OFFSET;
-       brd->port_end = brd->port + PCI_IO_SIZE;
-
-
-       /*
-        * Special initialization for non-PLX boards
-        */
-       if (brd->device != PCI_DEVICE_XRJ_DID && brd->device != PCI_DEVICE_EPCJ_DID) {
-               unsigned short cmd;
-
-               pci_write_config_byte(pdev, 0x40, 0);
-               pci_write_config_byte(pdev, 0x46, 0);
-
-               /* Limit burst length to 2 doubleword transactions */
-               pci_write_config_byte(pdev, 0x42, 1);
-
-               /*
-                * Enable IO and mem if not already done.
-                * This was needed for support on Itanium.
-                */
-               pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-               cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-               pci_write_config_word(pdev, PCI_COMMAND, cmd);
-       }
-
-       /* init our poll helper tasklet */
-       tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd);
-
-        /* Log the information about the board */
-       dgap_mbuf(brd, DRVSTR": board %d: %s (rev %d), irq %d\n",
-               dgap_NumBoards, brd->name, brd->rev, brd->irq);
-
-       DPR_INIT(("dgap_scan(%d) - printing out the msgbuf\n", i));
-       DGAP_LOCK(dgap_global_lock, flags);
-       brd->msgbuf = NULL;
-       printk("%s", brd->msgbuf_head);
-       kfree(brd->msgbuf_head);
-       brd->msgbuf_head = NULL;
-       DGAP_UNLOCK(dgap_global_lock, flags);
-
-       i = dgap_do_remap(brd);
-       if (i)
-               brd->state = BOARD_FAILED;
-       else
-               brd->state = NEED_RESET;
-
-        return(0);
-}
-
-
-int dgap_finalize_board_init(struct board_t *brd) {
-
-        int rc;
-
-        DPR_INIT(("dgap_finalize_board_init() - start\n"));
-
-       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-                return(-ENODEV);
-
-        DPR_INIT(("dgap_finalize_board_init() - start #2\n"));
-
-       brd->use_interrupts = dgap_config_get_useintr(brd);
-
-       /*
-        * Set up our interrupt handler if we are set to do interrupts.
-        */
-       if (brd->use_interrupts && brd->irq) {
-
-               rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
-
-               if (rc) {
-                       dgap_mbuf(brd, DRVSTR": Failed to hook IRQ %d. Board will work in poll mode.\n",
-                                  brd->irq);
-                       brd->intr_used = 0;
-               }
-               else
-                       brd->intr_used = 1;
-       } else {
-               brd->intr_used = 0;
-       }
-
-       return(0);
-}
-
-
-/*
- * Remap PCI memory.
- */
-static int dgap_do_remap(struct board_t *brd)
-{
-       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-               return -ENXIO;
-
-       if (!request_mem_region(brd->membase, 0x200000, "dgap")) {
-               APR(("dgap: mem_region %lx already in use.\n", brd->membase));
-               return -ENOMEM;
-        }
-
-       if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) {
-               APR(("dgap: mem_region IO %lx already in use.\n",
-                       brd->membase + PCI_IO_OFFSET));
-               release_mem_region(brd->membase, 0x200000);
-               return -ENOMEM;
-        }
-
-       brd->re_map_membase = ioremap(brd->membase, 0x200000);
-       if (!brd->re_map_membase) {
-               APR(("dgap: ioremap mem %lx cannot be mapped.\n", brd->membase));
-               release_mem_region(brd->membase, 0x200000);
-               release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-               return -ENOMEM;
-       }
-
-       brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
-       if (!brd->re_map_port) {
-               release_mem_region(brd->membase, 0x200000);
-               release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-               iounmap(brd->re_map_membase);
-               APR(("dgap: ioremap IO mem %lx cannot be mapped.\n",
-                       brd->membase + PCI_IO_OFFSET));
-               return -ENOMEM;
-       }
-
-       DPR_INIT(("remapped io: 0x%p  remapped mem: 0x%p\n",
-               brd->re_map_port, brd->re_map_membase));
-       return 0;
-}
-
-
-/*****************************************************************************
-*
-* Function:
-*
-*    dgap_poll_handler
-*
-* Author:
-*
-*    Scott H Kilau
-*
-* Parameters:
-*
-*    dummy -- ignored
-*
-* Return Values:
-*
-*    none
-*
-* Description:
-*
-*    As each timer expires, it determines (a) whether the "transmit"
-*    waiter needs to be woken up, and (b) whether the poller needs to
-*    be rescheduled.
-*
-******************************************************************************/
-
-static void dgap_poll_handler(ulong dummy)
-{
-       int i;
-        struct board_t *brd;
-        unsigned long lock_flags;
-        unsigned long lock_flags2;
-       ulong new_time;
-
-       dgap_poll_counter++;
-
-
-       /*
-        * If driver needs the config file still,
-        * keep trying to wake up the downloader to
-        * send us the file.
-        */
-        if (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD) {
-               /*
-                * Signal downloader, its got some work to do.
-                */
-               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-               if (dgap_dl_action != 1) {
-                       dgap_dl_action = 1;
-                       wake_up_interruptible(&dgap_dl_wait);
-               }
-               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-               goto schedule_poller;
-        }
-       /*
-        * Do not start the board state machine until
-        * driver tells us its up and running, and has
-        * everything it needs.
-        */
-       else if (dgap_driver_state != DRIVER_READY) {
-               goto schedule_poller;
-       }
-
-       /*
-        * If we have just 1 board, or the system is not SMP,
-        * then use the typical old style poller.
-        * Otherwise, use our new tasklet based poller, which should
-        * speed things up for multiple boards.
-        */
-       if ( (dgap_NumBoards == 1) || (num_online_cpus() <= 1) ) {
-               for (i = 0; i < dgap_NumBoards; i++) {
-
-                       brd = dgap_Board[i];
-
-                       if (brd->state == BOARD_FAILED) {
-                               continue;
-                       }
-                       if (!brd->intr_running) {
-                               /* Call the real board poller directly */
-                               dgap_poll_tasklet((unsigned long) brd);
-                       }
-               }
-       }
-       else {
-               /* Go thru each board, kicking off a tasklet for each if needed */
-               for (i = 0; i < dgap_NumBoards; i++) {
-                       brd = dgap_Board[i];
-
-                       /*
-                        * Attempt to grab the board lock.
-                        *
-                        * If we can't get it, no big deal, the next poll will get it.
-                        * Basically, I just really don't want to spin in here, because I want
-                        * to kick off my tasklets as fast as I can, and then get out the poller.
-                        */
-                       if (!spin_trylock(&brd->bd_lock)) {
-                               continue;
-                       }
-
-                       /* If board is in a failed state, don't bother scheduling a tasklet */
-                       if (brd->state == BOARD_FAILED) {
-                               spin_unlock(&brd->bd_lock);
-                               continue;
-                       }
-
-                       /* Schedule a poll helper task */
-                       if (!brd->intr_running) {
-                               tasklet_schedule(&brd->helper_tasklet);
-                       }
-
-                       /*
-                        * Can't do DGAP_UNLOCK here, as we don't have
-                        * lock_flags because we did a trylock above.
-                        */
-                       spin_unlock(&brd->bd_lock);
-               }
-       }
-
-schedule_poller:
-
-       /*
-        * Schedule ourself back at the nominal wakeup interval.
-        */
-       DGAP_LOCK(dgap_poll_lock, lock_flags );
-       dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
-
-       new_time = dgap_poll_time - jiffies;
-
-       if ((ulong) new_time >= 2 * dgap_poll_tick) {
-               dgap_poll_time = jiffies +  dgap_jiffies_from_ms(dgap_poll_tick);
-       }
-
-       dgap_poll_timer.function = dgap_poll_handler;
-       dgap_poll_timer.data = 0;
-       dgap_poll_timer.expires = dgap_poll_time;
-       DGAP_UNLOCK(dgap_poll_lock, lock_flags );
-
-       if (!dgap_poll_stop)
-               add_timer(&dgap_poll_timer);
-}
-
-
-
-
-/*
- * dgap_intr()
- *
- * Driver interrupt handler.
- */
-static irqreturn_t dgap_intr(int irq, void *voidbrd)
-{
-       struct board_t *brd = (struct board_t *) voidbrd;
-
-       if (!brd) {
-               APR(("Received interrupt (%d) with null board associated\n", irq));
-               return IRQ_NONE;
-       }
-
-       /*
-        * Check to make sure its for us.
-        */
-       if (brd->magic != DGAP_BOARD_MAGIC) {
-               APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
-               return IRQ_NONE;
-       }
-
-       brd->intr_count++;
-
-       /*
-        * Schedule tasklet to run at a better time.
-        */
-       tasklet_schedule(&brd->helper_tasklet);
-       return IRQ_HANDLED;
-}
-
-
-/*
- * dgap_init_globals()
- *
- * This is where we initialize the globals from the static insmod
- * configuration variables.  These are declared near the head of
- * this file.
- */
-static void dgap_init_globals(void)
-{
-       int i = 0;
-
-       dgap_rawreadok          = rawreadok;
-        dgap_trcbuf_size       = trcbuf_size;
-       dgap_debug              = debug;
-
-       for (i = 0; i < MAXBOARDS; i++) {
-               dgap_Board[i] = NULL;
-       }
-
-       init_timer( &dgap_poll_timer );
-
-       init_waitqueue_head(&dgap_dl_wait);
-       dgap_dl_action = 0;
-}
-
-
-/************************************************************************
- *
- * Utility functions
- *
- ************************************************************************/
-
-
-/*
- * dgap_mbuf()
- *
- * Used to print to the message buffer during board init.
- */
-static void dgap_mbuf(struct board_t *brd, const char *fmt, ...) {
-       va_list         ap;
-       char            buf[1024];
-       int             i;
-       unsigned long   flags;
-       size_t          length;
-
-       DGAP_LOCK(dgap_global_lock, flags);
-
-       /* Format buf using fmt and arguments contained in ap. */
-       va_start(ap, fmt);
-       i = vsnprintf(buf, sizeof(buf), fmt,  ap);
-       va_end(ap);
-
-       DPR((buf));
-
-       if (!brd || !brd->msgbuf) {
-               printk("%s", buf);
-               DGAP_UNLOCK(dgap_global_lock, flags);
-               return;
-       }
-
-       length = strlen(buf) + 1;
-       if (brd->msgbuf - brd->msgbuf_head < length)
-               length = brd->msgbuf - brd->msgbuf_head;
-       memcpy(brd->msgbuf, buf, length);
-       brd->msgbuf += length;
-
-       DGAP_UNLOCK(dgap_global_lock, flags);
-}
-
-
-/*
- * dgap_ms_sleep()
- *
- * Put the driver to sleep for x ms's
- *
- * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
- */
-int dgap_ms_sleep(ulong ms)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout((ms * HZ) / 1000);
-       return (signal_pending(current));
-}
-
-
-
-/*
- *      dgap_ioctl_name() : Returns a text version of each ioctl value.
- */
-char *dgap_ioctl_name(int cmd)
-{
-       switch(cmd) {
-
-       case TCGETA:            return("TCGETA");
-       case TCGETS:            return("TCGETS");
-       case TCSETA:            return("TCSETA");
-       case TCSETS:            return("TCSETS");
-       case TCSETAW:           return("TCSETAW");
-       case TCSETSW:           return("TCSETSW");
-       case TCSETAF:           return("TCSETAF");
-       case TCSETSF:           return("TCSETSF");
-       case TCSBRK:            return("TCSBRK");
-       case TCXONC:            return("TCXONC");
-       case TCFLSH:            return("TCFLSH");
-       case TIOCGSID:          return("TIOCGSID");
-
-       case TIOCGETD:          return("TIOCGETD");
-       case TIOCSETD:          return("TIOCSETD");
-       case TIOCGWINSZ:        return("TIOCGWINSZ");
-       case TIOCSWINSZ:        return("TIOCSWINSZ");
-
-       case TIOCMGET:          return("TIOCMGET");
-       case TIOCMSET:          return("TIOCMSET");
-       case TIOCMBIS:          return("TIOCMBIS");
-       case TIOCMBIC:          return("TIOCMBIC");
-
-       /* from digi.h */
-       case DIGI_SETA:         return("DIGI_SETA");
-       case DIGI_SETAW:        return("DIGI_SETAW");
-       case DIGI_SETAF:        return("DIGI_SETAF");
-       case DIGI_SETFLOW:      return("DIGI_SETFLOW");
-       case DIGI_SETAFLOW:     return("DIGI_SETAFLOW");
-       case DIGI_GETFLOW:      return("DIGI_GETFLOW");
-       case DIGI_GETAFLOW:     return("DIGI_GETAFLOW");
-       case DIGI_GETA:         return("DIGI_GETA");
-       case DIGI_GEDELAY:      return("DIGI_GEDELAY");
-       case DIGI_SEDELAY:      return("DIGI_SEDELAY");
-       case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
-       case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
-       case TIOCMODG:          return("TIOCMODG");
-       case TIOCMODS:          return("TIOCMODS");
-       case TIOCSDTR:          return("TIOCSDTR");
-       case TIOCCDTR:          return("TIOCCDTR");
-
-       default:                return("unknown");
-       }
-}
diff --git a/drivers/staging/dgap/dgap_driver.h b/drivers/staging/dgap/dgap_driver.h
deleted file mode 100644 (file)
index 9296adc..0000000
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * Driver includes
- *
- *************************************************************************/
-
-#ifndef __DGAP_DRIVER_H
-#define __DGAP_DRIVER_H
-
-#include <linux/types.h>        /* To pick up the varions Linux types */
-#include <linux/tty.h>          /* To pick up the various tty structs/defines */
-#include <linux/interrupt.h>    /* For irqreturn_t type */
-
-#include "dgap_types.h"         /* Additional types needed by the Digi header files */
-#include "digi.h"               /* Digi specific ioctl header */
-#include "dgap_kcompat.h"       /* Kernel 2.4/2.6 compat includes */
-#include "dgap_sysfs.h"                /* Support for SYSFS */
-
-/*************************************************************************
- *
- * Driver defines
- *
- *************************************************************************/
-
-/*
- * Driver identification, error and debugging statments
- *
- * In theory, you can change all occurrences of "digi" in the next
- * three lines, and the driver printk's will all automagically change.
- *
- * APR((fmt, args, ...));      Always prints message
- * DPR((fmt, args, ...));      Only prints if DGAP_TRACER is defined at
- *                               compile time and dgap_debug!=0
- */
-#define        DG_NAME         "dgap-1.3-16"
-#define        DG_PART         "40002347_C"
-
-#define        PROCSTR         "dgap"                  /* /proc entries         */
-#define        DEVSTR          "/dev/dg/dgap"          /* /dev entries          */
-#define        DRVSTR          "dgap"                  /* Driver name string
-                                                * displayed by APR      */
-#define        APR(args)       do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
-                          } while (0)
-#define        RAPR(args)      do { PRINTF_TO_KMEM(args); printk args; } while (0)
-
-#define TRC_TO_CONSOLE 1
-
-/*
- * Debugging levels can be set using debug insmod variable
- * They can also be compiled out completely.
- */
-
-#define        DBG_INIT                (dgap_debug & 0x01)
-#define        DBG_BASIC               (dgap_debug & 0x02)
-#define        DBG_CORE                (dgap_debug & 0x04)
-
-#define        DBG_OPEN                (dgap_debug & 0x08)
-#define        DBG_CLOSE               (dgap_debug & 0x10)
-#define        DBG_READ                (dgap_debug & 0x20)
-#define        DBG_WRITE               (dgap_debug & 0x40)
-
-#define        DBG_IOCTL               (dgap_debug & 0x80)
-
-#define        DBG_PROC                (dgap_debug & 0x100)
-#define        DBG_PARAM               (dgap_debug & 0x200)
-#define        DBG_PSCAN               (dgap_debug & 0x400)
-#define        DBG_EVENT               (dgap_debug & 0x800)
-
-#define        DBG_DRAIN               (dgap_debug & 0x1000)
-#define        DBG_CARR                (dgap_debug & 0x2000)
-
-#define        DBG_MGMT                (dgap_debug & 0x4000)
-
-
-#if defined(DGAP_TRACER)
-
-# if defined(TRC_TO_KMEM)
-/* Choose one: */
-#  define TRC_ON_OVERFLOW_WRAP_AROUND
-#  undef  TRC_ON_OVERFLOW_SHIFT_BUFFER
-# endif //TRC_TO_KMEM
-
-# define TRC_MAXMSG            1024
-# define TRC_OVERFLOW          "(OVERFLOW)"
-# define TRC_DTRC              "/usr/bin/dtrc"
-
-#if defined TRC_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
-#else //!defined TRACE_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args)
-#endif
-
-#if defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args) dgap_tracef args
-#else //!defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args)
-#endif
-
-#define        TRC(args)       { PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
-
-# define DPR_INIT(ARGS)                if (DBG_INIT) TRC(ARGS)
-# define DPR_BASIC(ARGS)       if (DBG_BASIC) TRC(ARGS)
-# define DPR_CORE(ARGS)                if (DBG_CORE) TRC(ARGS)
-# define DPR_OPEN(ARGS)                if (DBG_OPEN)  TRC(ARGS)
-# define DPR_CLOSE(ARGS)       if (DBG_CLOSE)  TRC(ARGS)
-# define DPR_READ(ARGS)                if (DBG_READ)  TRC(ARGS)
-# define DPR_WRITE(ARGS)       if (DBG_WRITE) TRC(ARGS)
-# define DPR_IOCTL(ARGS)       if (DBG_IOCTL) TRC(ARGS)
-# define DPR_PROC(ARGS)                if (DBG_PROC)  TRC(ARGS)
-# define DPR_PARAM(ARGS)       if (DBG_PARAM)  TRC(ARGS)
-# define DPR_PSCAN(ARGS)       if (DBG_PSCAN)  TRC(ARGS)
-# define DPR_EVENT(ARGS)       if (DBG_EVENT)  TRC(ARGS)
-# define DPR_DRAIN(ARGS)       if (DBG_DRAIN)  TRC(ARGS)
-# define DPR_CARR(ARGS)                if (DBG_CARR)  TRC(ARGS)
-# define DPR_MGMT(ARGS)                if (DBG_MGMT)  TRC(ARGS)
-
-# define DPR(ARGS)             if (dgap_debug) TRC(ARGS)
-# define P(X)                  dgap_tracef(#X "=%p\n", X)
-# define X(X)                  dgap_tracef(#X "=%x\n", X)
-
-#else//!defined DGAP_TRACER
-
-#define PRINTF_TO_KMEM(args)
-# define TRC(ARGS)
-# define DPR_INIT(ARGS)
-# define DPR_BASIC(ARGS)
-# define DPR_CORE(ARGS)
-# define DPR_OPEN(ARGS)
-# define DPR_CLOSE(ARGS)
-# define DPR_READ(ARGS)
-# define DPR_WRITE(ARGS)
-# define DPR_IOCTL(ARGS)
-# define DPR_PROC(ARGS)
-# define DPR_PARAM(ARGS)
-# define DPR_PSCAN(ARGS)
-# define DPR_EVENT(ARGS)
-# define DPR_DRAIN(ARGS)
-# define DPR_CARR(ARGS)
-# define DPR_MGMT(ARGS)
-
-# define DPR(args)
-
-#endif//DGAP_TRACER
-
-/* Number of boards we support at once. */
-#define        MAXBOARDS       32
-#define        MAXPORTS        224
-#define MAXTTYNAMELEN  200
-
-/* Our 3 magic numbers for our board, channel and unit structs */
-#define DGAP_BOARD_MAGIC       0x5c6df104
-#define DGAP_CHANNEL_MAGIC     0x6c6df104
-#define DGAP_UNIT_MAGIC                0x7c6df104
-
-/* Serial port types */
-#define DGAP_SERIAL            0
-#define DGAP_PRINT             1
-
-#define        SERIAL_TYPE_NORMAL      1
-
-/* 4 extra for alignment play space */
-#define WRITEBUFLEN            ((4096) + 4)
-#define MYFLIPLEN              N_TTY_BUF_SIZE
-
-#define SBREAK_TIME 0x25
-#define U2BSIZE 0x400
-
-#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
-
-/*
- * Our major for the mgmt devices.
- *
- * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
- * 22 has now become obsolete now that the "cu" devices have
- * been removed from 2.6.
- * Also, this *IS* the epca driver, just PCI only now.
- */
-#ifndef DIGI_DGAP_MAJOR
-# define DIGI_DGAP_MAJOR         22
-#endif
-
-/*
- * The parameters we use to define the periods of the moving averages.
- */
-#define                MA_PERIOD       (HZ / 10)
-#define                SMA_DUR         (1 * HZ)
-#define                EMA_DUR         (1 * HZ)
-#define                SMA_NPERIODS    (SMA_DUR / MA_PERIOD)
-#define                EMA_NPERIODS    (EMA_DUR / MA_PERIOD)
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.  This is the same structure that is defined
- * as the default in tty_io.c with the same settings overriden as in serial.c
- *
- * In short, this should match the internal serial ports' defaults.
- */
-#define        DEFAULT_IFLAGS  (ICRNL | IXON)
-#define        DEFAULT_OFLAGS  (OPOST | ONLCR)
-#define        DEFAULT_CFLAGS  (B9600 | CS8 | CREAD | HUPCL | CLOCAL)
-#define        DEFAULT_LFLAGS  (ISIG | ICANON | ECHO | ECHOE | ECHOK | \
-                       ECHOCTL | ECHOKE | IEXTEN)
-
-#ifndef _POSIX_VDISABLE
-#define   _POSIX_VDISABLE '\0'
-#endif
-
-#define SNIFF_MAX      65536           /* Sniff buffer size (2^n) */
-#define SNIFF_MASK     (SNIFF_MAX - 1) /* Sniff wrap mask */
-
-#define VPDSIZE (512)
-
-/*
- * Lock function/defines.
- * Makes spotting lock/unlock locations easier.
- */
-# define DGAP_SPINLOCK_INIT(x)         spin_lock_init(&(x))
-# define DGAP_LOCK(x,y)                        spin_lock_irqsave(&(x), y)
-# define DGAP_UNLOCK(x,y)              spin_unlock_irqrestore(&(x), y)
-# define DGAP_TRYLOCK(x,y)             spin_trylock(&(x))
-
-/*
- * All the possible states the driver can be while being loaded.
- */
-enum {
-       DRIVER_INITIALIZED = 0,
-       DRIVER_NEED_CONFIG_LOAD,
-       DRIVER_REQUESTED_CONFIG,
-       DRIVER_READY
-};
-
-/*
- * All the possible states the board can be while booting up.
- */
-enum {
-       BOARD_FAILED = 0,
-       CONFIG_NOT_FOUND,
-       BOARD_FOUND,
-       NEED_RESET,
-       FINISHED_RESET,
-       NEED_CONFIG,
-       FINISHED_CONFIG,
-       NEED_DEVICE_CREATION,
-       REQUESTED_DEVICE_CREATION,
-       FINISHED_DEVICE_CREATION,
-       NEED_BIOS_LOAD,
-       REQUESTED_BIOS,
-       WAIT_BIOS_LOAD,
-       FINISHED_BIOS_LOAD,
-       NEED_FEP_LOAD,
-       REQUESTED_FEP,
-       WAIT_FEP_LOAD,
-       FINISHED_FEP_LOAD,
-       NEED_PROC_CREATION,
-       FINISHED_PROC_CREATION,
-       BOARD_READY
-};
-
-/*
- * All the possible states that a requested concentrator image can be in.
- */
-enum {
-       NO_PENDING_CONCENTRATOR_REQUESTS = 0,
-       NEED_CONCENTRATOR,
-       REQUESTED_CONCENTRATOR
-};
-
-extern char *dgap_state_text[];
-extern char *dgap_driver_state_text[];
-
-
-/*
- * Modem line constants are defined as macros because DSR and
- * DCD are swapable using the ditty altpin option.
- */
-#define D_CD(ch)        ch->ch_cd       /* Carrier detect       */
-#define D_DSR(ch)       ch->ch_dsr      /* Data set ready       */
-#define D_RTS(ch)       DM_RTS          /* Request to send      */
-#define D_CTS(ch)       DM_CTS          /* Clear to send        */
-#define D_RI(ch)        DM_RI           /* Ring indicator       */
-#define D_DTR(ch)       DM_DTR          /* Data terminal ready  */
-
-
-/*************************************************************************
- *
- * Structures and closely related defines.
- *
- *************************************************************************/
-
-
-/*
- * A structure to hold a statistics counter.  We also
- * compute moving averages for this counter.
- */
-struct macounter
-{
-       u32             cnt;    /* Total count */
-       ulong           accum;  /* Acuumulator per period */
-       ulong           sma;    /* Simple moving average */
-       ulong           ema;    /* Exponential moving average */
-};
-
-
-/************************************************************************
- * Device flag definitions for bd_flags.
- ************************************************************************/
-#define        BD_FEP5PLUS     0x0001          /* Supports FEP5 Plus commands */
-#define BD_HAS_VPD     0x0002          /* Board has VPD info available */
-
-
-/*
- *     Per-board information
- */
-struct board_t
-{
-       int             magic;          /* Board Magic number.  */
-       int             boardnum;       /* Board number: 0-3 */
-       int             firstminor;     /* First minor, e.g. 0, 30, 60 */
-
-       int             type;           /* Type of board */
-       char            *name;          /* Product Name */
-       struct pci_dev  *pdev;          /* Pointer to the pci_dev struct */
-       u16             vendor;         /* PCI vendor ID */
-       u16             device;         /* PCI device ID */
-       u16             subvendor;      /* PCI subsystem vendor ID */
-       u16             subdevice;      /* PCI subsystem device ID */
-       uchar           rev;            /* PCI revision ID */
-       uint            pci_bus;        /* PCI bus value */
-       uint            pci_slot;       /* PCI slot value */
-       u16             maxports;       /* MAX ports this board can handle */
-       uchar           vpd[VPDSIZE];   /* VPD of board, if found */
-       u32             bd_flags;       /* Board flags */
-
-       spinlock_t      bd_lock;        /* Used to protect board */
-
-       u32             state;          /* State of card. */
-       wait_queue_head_t state_wait;   /* Place to sleep on for state change */
-
-       struct          tasklet_struct helper_tasklet; /* Poll helper tasklet */
-
-       u32             wait_for_bios;
-       u32             wait_for_fep;
-
-       struct cnode *  bd_config;      /* Config of board */
-
-       u16             nasync;         /* Number of ports on card */
-
-       u32             use_interrupts; /* Should we be interrupt driven? */
-       ulong           irq;            /* Interrupt request number */
-       ulong           intr_count;     /* Count of interrupts */
-       u32             intr_used;      /* Non-zero if using interrupts */
-       u32             intr_running;   /* Non-zero if FEP knows its doing interrupts */
-
-       ulong           port;           /* Start of base io port of the card */
-       ulong           port_end;       /* End of base io port of the card */
-       ulong           membase;        /* Start of base memory of the card */
-       ulong           membase_end;    /* End of base memory of the card */
-
-       uchar           *re_map_port;   /* Remapped io port of the card */
-       uchar           *re_map_membase;/* Remapped memory of the card */
-
-       uchar           runwait;        /* # Processes waiting for FEP  */
-       uchar           inhibit_poller; /* Tells  the poller to leave us alone */
-
-       struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
-
-       struct tty_driver       *SerialDriver;
-       char            SerialName[200];
-       struct tty_driver       *PrintDriver;
-       char            PrintName[200];
-
-       u32             dgap_Major_Serial_Registered;
-       u32             dgap_Major_TransparentPrint_Registered;
-
-       u32             dgap_Serial_Major;
-       u32             dgap_TransparentPrint_Major;
-
-       struct bs_t     *bd_bs;                 /* Base structure pointer       */
-
-       char    *flipbuf;               /* Our flip buffer, alloced if board is found */
-       char    *flipflagbuf;           /* Our flip flag buffer, alloced if board is found */
-
-       u16             dpatype;        /* The board "type", as defined by DPA */
-       u16             dpastatus;      /* The board "status", as defined by DPA */
-       wait_queue_head_t kme_wait;     /* Needed for DPA support */
-
-       u32             conc_dl_status; /* Status of any pending conc download */
-       /*
-        *      Mgmt data.
-        */
-        char           *msgbuf_head;
-        char           *msgbuf;
-};
-
-
-
-/************************************************************************
- * Unit flag definitions for un_flags.
- ************************************************************************/
-#define UN_ISOPEN      0x0001          /* Device is open               */
-#define UN_CLOSING     0x0002          /* Line is being closed         */
-#define UN_IMM         0x0004          /* Service immediately          */
-#define UN_BUSY                0x0008          /* Some work this channel       */
-#define UN_BREAKI      0x0010          /* Input break received         */
-#define UN_PWAIT       0x0020          /* Printer waiting for terminal */
-#define UN_TIME                0x0040          /* Waiting on time              */
-#define UN_EMPTY       0x0080          /* Waiting output queue empty   */
-#define UN_LOW         0x0100          /* Waiting output low water mark*/
-#define UN_EXCL_OPEN   0x0200          /* Open for exclusive use       */
-#define UN_WOPEN       0x0400          /* Device waiting for open      */
-#define UN_WIOCTL      0x0800          /* Device waiting for open      */
-#define UN_HANGUP      0x8000          /* Carrier lost                 */
-
-struct device;
-
-/************************************************************************
- * Structure for terminal or printer unit.
- ************************************************************************/
-struct un_t {
-       int     magic;          /* Unit Magic Number.                   */
-       struct  channel_t *un_ch;
-       u32     un_time;
-       u32     un_type;
-       u32     un_open_count;  /* Counter of opens to port             */
-       struct tty_struct *un_tty;/* Pointer to unit tty structure      */
-       u32     un_flags;       /* Unit flags                           */
-       wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
-       u32     un_dev;         /* Minor device number                  */
-       tcflag_t un_oflag;      /* oflags being done on board           */
-       tcflag_t un_lflag;      /* lflags being done on board           */
-       struct device *un_sysfs;
-};
-
-
-/************************************************************************
- * Device flag definitions for ch_flags.
- ************************************************************************/
-#define CH_PRON         0x0001          /* Printer on string                */
-#define CH_OUT          0x0002          /* Dial-out device open             */
-#define CH_STOP         0x0004          /* Output is stopped                */
-#define CH_STOPI        0x0008          /* Input is stopped                 */
-#define CH_CD           0x0010          /* Carrier is present               */
-#define CH_FCAR         0x0020          /* Carrier forced on                */
-
-#define CH_RXBLOCK      0x0080          /* Enable rx blocked flag           */
-#define CH_WLOW         0x0100          /* Term waiting low event           */
-#define CH_WEMPTY       0x0200          /* Term waiting empty event         */
-#define CH_RENABLE      0x0400          /* Buffer just emptied          */
-#define CH_RACTIVE      0x0800          /* Process active in xxread()   */
-#define CH_RWAIT        0x1000          /* Process waiting in xxread()  */
-#define CH_BAUD0       0x2000          /* Used for checking B0 transitions */
-#define CH_HANGUP       0x8000         /* Hangup received                  */
-
-/*
- * Definitions for ch_sniff_flags
- */
-#define SNIFF_OPEN     0x1
-#define SNIFF_WAIT_DATA        0x2
-#define SNIFF_WAIT_SPACE 0x4
-
-
-/************************************************************************
- * Channel information structure.
- ************************************************************************/
-struct channel_t {
-       int magic;                      /* Channel Magic Number         */
-       struct bs_t     *ch_bs;         /* Base structure pointer       */
-       struct cm_t     *ch_cm;         /* Command queue pointer        */
-       struct board_t *ch_bd;          /* Board structure pointer      */
-       unsigned char *ch_vaddr;        /* FEP memory origin            */
-       unsigned char *ch_taddr;        /* Write buffer origin          */
-       unsigned char *ch_raddr;        /* Read buffer origin           */
-       struct digi_t  ch_digi;         /* Transparent Print structure  */
-       struct un_t ch_tun;             /* Terminal unit info           */
-       struct un_t ch_pun;             /* Printer unit info            */
-
-       spinlock_t      ch_lock;        /* provide for serialization */
-       wait_queue_head_t ch_flags_wait;
-
-       u32     pscan_state;
-       uchar   pscan_savechar;
-
-       u32 ch_portnum;                 /* Port number, 0 offset.       */
-       u32 ch_open_count;              /* open count                   */
-       u32     ch_flags;               /* Channel flags                */
-
-
-       u32     ch_close_delay;         /* How long we should drop RTS/DTR for */
-
-       u32     ch_cpstime;             /* Time for CPS calculations    */
-
-       tcflag_t ch_c_iflag;            /* channel iflags               */
-       tcflag_t ch_c_cflag;            /* channel cflags               */
-       tcflag_t ch_c_oflag;            /* channel oflags               */
-       tcflag_t ch_c_lflag;            /* channel lflags               */
-
-       u16  ch_fepiflag;            /* FEP tty iflags               */
-       u16  ch_fepcflag;               /* FEP tty cflags               */
-       u16  ch_fepoflag;               /* FEP tty oflags               */
-       u16  ch_wopen;                  /* Waiting for open process cnt */
-       u16  ch_tstart;                 /* Transmit buffer start        */
-       u16  ch_tsize;                  /* Transmit buffer size         */
-       u16  ch_rstart;                 /* Receive buffer start         */
-       u16  ch_rsize;                  /* Receive buffer size          */
-       u16  ch_rdelay;                 /* Receive delay time           */
-
-       u16     ch_tlw;                 /* Our currently set low water mark */
-
-       u16  ch_cook;                   /* Output character mask        */
-
-       uchar   ch_card;                /* Card channel is on           */
-       uchar   ch_stopc;               /* Stop character               */
-       uchar   ch_startc;              /* Start character              */
-
-       uchar   ch_mostat;              /* FEP output modem status      */
-       uchar   ch_mistat;              /* FEP input modem status       */
-       uchar   ch_mforce;              /* Modem values to be forced    */
-       uchar   ch_mval;                /* Force values                 */
-       uchar   ch_fepstopc;            /* FEP stop character           */
-       uchar   ch_fepstartc;           /* FEP start character          */
-
-       uchar   ch_astopc;              /* Auxiliary Stop character     */
-       uchar   ch_astartc;             /* Auxiliary Start character    */
-       uchar   ch_fepastopc;           /* Auxiliary FEP stop char      */
-       uchar   ch_fepastartc;          /* Auxiliary FEP start char     */
-
-       uchar   ch_hflow;               /* FEP hardware handshake       */
-       uchar   ch_dsr;                 /* stores real dsr value        */
-       uchar   ch_cd;                  /* stores real cd value         */
-       uchar   ch_tx_win;              /* channel tx buffer window     */
-       uchar   ch_rx_win;              /* channel rx buffer window     */
-       uint    ch_custom_speed;        /* Custom baud, if set          */
-       uint    ch_baud_info;           /* Current baud info for /proc output   */
-       ulong   ch_rxcount;             /* total of data received so far        */
-       ulong   ch_txcount;             /* total of data transmitted so far     */
-       ulong   ch_err_parity;          /* Count of parity errors on channel    */
-       ulong   ch_err_frame;           /* Count of framing errors on channel   */
-       ulong   ch_err_break;           /* Count of breaks on channel   */
-       ulong   ch_err_overrun;         /* Count of overruns on channel */
-
-       uint ch_sniff_in;
-       uint ch_sniff_out;
-       char *ch_sniff_buf;             /* Sniff buffer for proc */
-       ulong ch_sniff_flags;           /* Channel flags                */
-       wait_queue_head_t ch_sniff_wait;
-};
-
-
-/*************************************************************************
- *
- * Prototypes for non-static functions used in more than one module
- *
- *************************************************************************/
-
-extern int             dgap_ms_sleep(ulong ms);
-extern char            *dgap_ioctl_name(int cmd);
-extern void            dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len);
-extern void            dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
-extern void            dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
-extern void            dgap_do_config_load(uchar __user *uaddr, int len);
-extern int             dgap_after_config_loaded(void);
-extern int             dgap_finalize_board_init(struct board_t *brd);
-
-/*
- * Our Global Variables.
- */
-extern int             dgap_driver_state;      /* The state of the driver      */
-extern int             dgap_debug;             /* Debug variable               */
-extern int             dgap_rawreadok;         /* Set if user wants rawreads   */
-extern int             dgap_poll_tick;         /* Poll interval - 20 ms        */
-extern spinlock_t      dgap_global_lock;       /* Driver global spinlock       */
-extern uint            dgap_NumBoards;         /* Total number of boards       */
-extern struct board_t  *dgap_Board[MAXBOARDS]; /* Array of board structs       */
-extern ulong           dgap_poll_counter;      /* Times the poller has run     */
-extern char            *dgap_config_buf;       /* The config file buffer       */
-extern spinlock_t      dgap_dl_lock;           /* Downloader spinlock          */
-extern wait_queue_head_t dgap_dl_wait;         /* Wait queue for downloader    */
-extern int             dgap_dl_action;         /* Action flag for downloader   */
-extern int             dgap_registerttyswithsysfs; /* Should we register the   */
-                                                   /* ttys with sysfs or not   */
-
-/*
- * Global functions declared in dgap_fep5.c, but must be hidden from
- * user space programs.
- */
-extern void    dgap_poll_tasklet(unsigned long data);
-extern void    dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds);
-extern void    dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
-extern void    dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
-extern int     dgap_param(struct tty_struct *tty);
-extern void    dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len);
-extern uint    dgap_get_custom_baud(struct channel_t *ch);
-extern void    dgap_firmware_reset_port(struct channel_t *ch);
-
-#endif
diff --git a/drivers/staging/dgap/dgap_fep5.c b/drivers/staging/dgap/dgap_fep5.c
deleted file mode 100644 (file)
index 51cda71..0000000
+++ /dev/null
@@ -1,1903 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
- * $Id: dgap_fep5.c,v 1.2 2011/06/21 10:35:40 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>       /* For udelay */
-#include <asm/uaccess.h>       /* For copy_from_user/copy_to_user */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>    /* For tty_schedule_flip */
-#include <linux/slab.h>
-#include <linux/sched.h>
-
-#include "dgap_driver.h"
-#include "dgap_pci.h"
-#include "dgap_fep5.h"
-#include "dgap_tty.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-#include "dgap_trace.h"
-
-/*
- * Our function prototypes
- */
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds);
-static int dgap_event(struct board_t *bd);
-
-/*
- * internal variables
- */
-static uint dgap_count = 500;
-
-
-/*
- * Loads the dgap.conf config file from the user.
- */
-void dgap_do_config_load(uchar __user *uaddr, int len)
-{
-       int orig_len = len;
-       char *to_addr;
-       uchar __user *from_addr = uaddr;
-       char buf[U2BSIZE];
-       int n;
-
-       to_addr = dgap_config_buf = kzalloc(len + 1, GFP_ATOMIC);
-       if (!dgap_config_buf) {
-               DPR_INIT(("dgap_do_config_load - unable to allocate memory for file\n"));
-               dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
-               return;
-       }
-
-       n = U2BSIZE;
-       while (len) {
-
-               if (n > len)
-                       n = len;
-
-               if (copy_from_user((char *) &buf, from_addr, n) == -1 )
-                       return;
-
-               /* Copy data from buffer to kernel memory */
-               memcpy(to_addr, buf, n);
-
-               /* increment counts */
-               len -= n;
-               to_addr += n;
-               from_addr += n;
-               n = U2BSIZE;
-       }
-
-       dgap_config_buf[orig_len] = '\0';
-
-       to_addr = dgap_config_buf;
-       dgap_parsefile(&to_addr, TRUE);
-
-       DPR_INIT(("dgap_config_load() finish\n"));
-
-       return;
-}
-
-
-int dgap_after_config_loaded(void)
-{
-       int i = 0;
-       int rc = 0;
-
-       /*
-        * Register our ttys, now that we have the config loaded.
-        */
-       for (i = 0; i < dgap_NumBoards; ++i) {
-
-               /*
-                * Initialize KME waitqueues...
-                */
-               init_waitqueue_head(&(dgap_Board[i]->kme_wait));
-
-               /*
-                * allocate flip buffer for board.
-                */
-               dgap_Board[i]->flipbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
-               dgap_Board[i]->flipflagbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
-       }
-
-       return rc;
-}
-
-
-
-/*=======================================================================
- *
- *      usertoboard - copy from user space to board space.
- *
- *=======================================================================*/
-static int dgap_usertoboard(struct board_t *brd, char *to_addr, char __user *from_addr, int len)
-{
-       char buf[U2BSIZE];
-       int n = U2BSIZE;
-
-       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-               return -EFAULT;
-
-       while (len) {
-               if (n > len)
-                       n = len;
-
-               if (copy_from_user((char *) &buf, from_addr, n) == -1 ) {
-                       return -EFAULT;
-               }
-
-               /* Copy data from buffer to card memory */
-               memcpy_toio(to_addr, buf, n);
-
-               /* increment counts */
-               len -= n;
-               to_addr += n;
-               from_addr += n;
-               n = U2BSIZE;
-       }
-       return 0;
-}
-
-
-/*
- * Copies the BIOS code from the user to the board,
- * and starts the BIOS running.
- */
-void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len)
-{
-       uchar *addr;
-       uint offset;
-       int i;
-
-       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-               return;
-
-       DPR_INIT(("dgap_do_bios_load() start\n"));
-
-       addr = brd->re_map_membase;
-
-       /*
-        * clear POST area
-        */
-       for (i = 0; i < 16; i++)
-               writeb(0, addr + POSTAREA + i);
-
-       /*
-        * Download bios
-        */
-       offset = 0x1000;
-       if (dgap_usertoboard(brd, addr + offset, ubios, len) == -1 ) {
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-               return;
-       }
-
-       writel(0x0bf00401, addr);
-       writel(0, (addr + 4));
-
-       /* Clear the reset, and change states. */
-       writeb(FEPCLR, brd->re_map_port);
-       brd->state = WAIT_BIOS_LOAD;
-}
-
-
-/*
- * Checks to see if the BIOS completed running on the card.
- */
-static void dgap_do_wait_for_bios(struct board_t *brd)
-{
-       uchar *addr;
-       u16 word;
-
-       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-               return;
-
-       addr = brd->re_map_membase;
-       word = readw(addr + POSTAREA);
-
-       /* Check to see if BIOS thinks board is good. (GD). */
-       if (word == *(u16 *) "GD") {
-               DPR_INIT(("GOT GD in memory, moving states.\n"));
-               brd->state = FINISHED_BIOS_LOAD;
-               return;
-       }
-
-       /* Give up on board after too long of time taken */
-       if (brd->wait_for_bios++ > 5000) {
-               u16 err1 = readw(addr + SEQUENCE);
-               u16 err2 = readw(addr + ERROR);
-               APR(("***WARNING*** %s failed diagnostics.  Error #(%x,%x).\n",
-                       brd->name, err1, err2));
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-       }
-}
-
-
-/*
- * Copies the FEP code from the user to the board,
- * and starts the FEP running.
- */
-void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len)
-{
-       uchar *addr;
-       uint offset;
-
-       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-               return;
-
-       addr = brd->re_map_membase;
-
-       DPR_INIT(("dgap_do_fep_load() for board %s : start\n", brd->name));
-
-       /*
-        * Download FEP
-        */
-       offset = 0x1000;
-       if (dgap_usertoboard(brd, addr + offset, ufep, len) == -1 ) {
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-               return;
-       }
-
-       /*
-        * If board is a concentrator product, we need to give
-        * it its config string describing how the concentrators look.
-        */
-       if ((brd->type == PCX) || (brd->type == PEPC)) {
-               uchar string[100];
-               uchar *config, *xconfig;
-               int i = 0;
-
-               xconfig = dgap_create_config_string(brd, string);
-
-               /* Write string to board memory */
-               config = addr + CONFIG;
-               for (; i < CONFIGSIZE; i++, config++, xconfig++) {
-                       writeb(*xconfig, config);
-                       if ((*xconfig & 0xff) == 0xff)
-                               break;
-               }
-       }
-
-       writel(0xbfc01004, (addr + 0xc34));
-       writel(0x3, (addr + 0xc30));
-
-       /* change states. */
-       brd->state = WAIT_FEP_LOAD;
-
-       DPR_INIT(("dgap_do_fep_load() for board %s : finish\n", brd->name));
-
-}
-
-
-/*
- * Waits for the FEP to report thats its ready for us to use.
- */
-static void dgap_do_wait_for_fep(struct board_t *brd)
-{
-       uchar *addr;
-       u16 word;
-
-       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-               return;
-
-       addr = brd->re_map_membase;
-
-       DPR_INIT(("dgap_do_wait_for_fep() for board %s : start. addr: %p\n", brd->name, addr));
-
-       word = readw(addr + FEPSTAT);
-
-       /* Check to see if FEP is up and running now. */
-       if (word == *(u16 *) "OS") {
-               DPR_INIT(("GOT OS in memory for board %s, moving states.\n", brd->name));
-               brd->state = FINISHED_FEP_LOAD;
-
-               /*
-                * Check to see if the board can support FEP5+ commands.
-                */
-               word = readw(addr + FEP5_PLUS);
-               if (word == *(u16 *) "5A") {
-                       DPR_INIT(("GOT 5A in memory for board %s, board supports extended FEP5 commands.\n", brd->name));
-                       brd->bd_flags |= BD_FEP5PLUS;
-               }
-
-               return;
-       }
-
-       /* Give up on board after too long of time taken */
-       if (brd->wait_for_fep++ > 5000) {
-               u16 err1 = readw(addr + SEQUENCE);
-               u16 err2 = readw(addr + ERROR);
-               APR(("***WARNING*** FEPOS for %s not functioning.  Error #(%x,%x).\n",
-                       brd->name, err1, err2));
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-       }
-
-       DPR_INIT(("dgap_do_wait_for_fep() for board %s : finish\n", brd->name));
-}
-
-
-/*
- * Physically forces the FEP5 card to reset itself.
- */
-static void dgap_do_reset_board(struct board_t *brd)
-{
-       uchar check;
-       u32 check1;
-       u32 check2;
-       int i = 0;
-
-       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase || !brd->re_map_port) {
-               DPR_INIT(("dgap_do_reset_board() start. bad values. brd: %p mem: %p io: %p\n",
-                       brd, brd ? brd->re_map_membase : 0, brd ? brd->re_map_port : 0));
-               return;
-       }
-
-       DPR_INIT(("dgap_do_reset_board() start. io: %p\n", brd->re_map_port));
-
-       /* FEPRST does not vary among supported boards */
-       writeb(FEPRST, brd->re_map_port);
-
-       for (i = 0; i <= 1000; i++) {
-               check = readb(brd->re_map_port) & 0xe;
-               if (check == FEPRST)
-                       break;
-               udelay(10);
-
-       }
-       if (i > 1000) {
-               APR(("*** WARNING *** Board not resetting...  Failing board.\n"));
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-               goto failed;
-       }
-
-       /*
-        * Make sure there really is memory out there.
-        */
-       writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
-       writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
-       check1 = readl(brd->re_map_membase + LOWMEM);
-       check2 = readl(brd->re_map_membase + HIGHMEM);
-
-       if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
-               APR(("*** Warning *** No memory at %p for board.\n", brd->re_map_membase));
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-               goto failed;
-       }
-
-       if (brd->state != BOARD_FAILED)
-               brd->state = FINISHED_RESET;
-
-failed:
-       DPR_INIT(("dgap_do_reset_board() finish\n"));
-}
-
-
-/*
- * Sends a concentrator image into the FEP5 board.
- */
-void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
-{
-       char *vaddr;
-       u16 offset = 0;
-       struct downld_t *to_dp;
-
-       if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-               return;
-
-       vaddr = brd->re_map_membase;
-
-       offset = readw((u16 *) (vaddr + DOWNREQ));
-       to_dp = (struct downld_t *) (vaddr + (int) offset);
-
-       /*
-        * The image was already read into kernel space,
-        * we do NOT need a user space read here
-        */
-       memcpy_toio((char *) to_dp, uaddr, sizeof(struct downld_t));
-
-       /* Tell card we have data for it */
-       writew(0, vaddr + (DOWNREQ));
-
-       brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
-}
-
-
-#define EXPANSION_ROM_SIZE     (64 * 1024)
-#define FEP5_ROM_MAGIC         (0xFEFFFFFF)
-
-static void dgap_get_vpd(struct board_t *brd)
-{
-       u32 magic;
-       u32 base_offset;
-       u16 rom_offset;
-       u16 vpd_offset;
-       u16 image_length;
-       u16 i;
-       uchar byte1;
-       uchar byte2;
-
-       /*
-        * Poke the magic number at the PCI Rom Address location.
-        * If VPD is supported, the value read from that address
-        * will be non-zero.
-        */
-       magic = FEP5_ROM_MAGIC;
-       pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-       pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
-       /* VPD not supported, bail */
-       if (!magic)
-               return;
-
-       /*
-        * To get to the OTPROM memory, we have to send the boards base
-        * address or'ed with 1 into the PCI Rom Address location.
-        */
-       magic = brd->membase | 0x01;
-       pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-       pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
-       byte1 = readb(brd->re_map_membase);
-       byte2 = readb(brd->re_map_membase + 1);
-
-       /*
-        * If the board correctly swapped to the OTPROM memory,
-        * the first 2 bytes (header) should be 0x55, 0xAA
-        */
-       if (byte1 == 0x55 && byte2 == 0xAA) {
-
-               base_offset = 0;
-
-               /*
-                * We have to run through all the OTPROM memory looking
-                * for the VPD offset.
-                */
-               while (base_offset <= EXPANSION_ROM_SIZE) {
-
-                       /*
-                        * Lots of magic numbers here.
-                        *
-                        * The VPD offset is located inside the ROM Data Structure.
-                        * We also have to remember the length of each
-                        * ROM Data Structure, so we can "hop" to the next
-                        * entry if the VPD isn't in the current
-                        * ROM Data Structure.
-                        */
-                       rom_offset = readw(brd->re_map_membase + base_offset + 0x18);
-                       image_length = readw(brd->re_map_membase + rom_offset + 0x10) * 512;
-                       vpd_offset = readw(brd->re_map_membase + rom_offset + 0x08);
-
-                       /* Found the VPD entry */
-                       if (vpd_offset)
-                               break;
-
-                       /* We didn't find a VPD entry, go to next ROM entry. */
-                       base_offset += image_length;
-
-                       byte1 = readb(brd->re_map_membase + base_offset);
-                       byte2 = readb(brd->re_map_membase + base_offset + 1);
-
-                       /*
-                        * If the new ROM offset doesn't have 0x55, 0xAA
-                        * as its header, we have run out of ROM.
-                        */
-                       if (byte1 != 0x55 || byte2 != 0xAA)
-                               break;
-               }
-
-               /*
-                * If we have a VPD offset, then mark the board
-                * as having a valid VPD, and copy VPDSIZE (512) bytes of
-                * that VPD to the buffer we have in our board structure.
-                */
-               if (vpd_offset) {
-                       brd->bd_flags |= BD_HAS_VPD;
-                       for (i = 0; i < VPDSIZE; i++)
-                               brd->vpd[i] = readb(brd->re_map_membase + vpd_offset + i);
-               }
-       }
-
-       /*
-        * We MUST poke the magic number at the PCI Rom Address location again.
-        * This makes the card report the regular board memory back to us,
-        * rather than the OTPROM memory.
-        */
-       magic = FEP5_ROM_MAGIC;
-       pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-}
-
-
-/*
- * Our board poller function.
- */
-void dgap_poll_tasklet(unsigned long data)
-{
-       struct board_t *bd = (struct board_t *) data;
-       ulong  lock_flags;
-       ulong  lock_flags2;
-       char *vaddr;
-       u16 head, tail;
-       u16 *chk_addr;
-       u16 check = 0;
-
-       if (!bd || (bd->magic != DGAP_BOARD_MAGIC)) {
-               APR(("dgap_poll_tasklet() - NULL or bad bd.\n"));
-               return;
-       }
-
-       if (bd->inhibit_poller)
-               return;
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-
-       vaddr = bd->re_map_membase;
-
-       /*
-        * If board is ready, parse deeper to see if there is anything to do.
-        */
-       if (bd->state == BOARD_READY) {
-
-               struct ev_t *eaddr = NULL;
-
-               if (!bd->re_map_membase) {
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       return;
-               }
-               if (!bd->re_map_port) {
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       return;
-               }
-
-               if (!bd->nasync) {
-                       goto out;
-               }
-
-               /*
-                * If this is a CX or EPCX, we need to see if the firmware
-                * is requesting a concentrator image from us.
-                */
-               if ((bd->type == PCX) || (bd->type == PEPC)) {
-                       chk_addr = (u16 *) (vaddr + DOWNREQ);
-                       check = readw(chk_addr);
-                       /* Nonzero if FEP is requesting concentrator image. */
-                       if (check) {
-                               if (bd->conc_dl_status == NO_PENDING_CONCENTRATOR_REQUESTS)
-                                       bd->conc_dl_status = NEED_CONCENTRATOR;
-                               /*
-                                * Signal downloader, its got some work to do.
-                                */
-                               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-                               if (dgap_dl_action != 1) {
-                                       dgap_dl_action = 1;
-                                       wake_up_interruptible(&dgap_dl_wait);
-                               }
-                               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-
-                       }
-               }
-
-               eaddr = (struct ev_t *) (vaddr + EVBUF);
-
-               /* Get our head and tail */
-               head = readw(&(eaddr->ev_head));
-               tail = readw(&(eaddr->ev_tail));
-
-               /*
-                * If there is an event pending. Go service it.
-                */
-               if (head != tail) {
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       dgap_event(bd);
-                       DGAP_LOCK(bd->bd_lock, lock_flags);
-               }
-
-out:
-               /*
-                * If board is doing interrupts, ACK the interrupt.
-                */
-               if (bd && bd->intr_running) {
-                       readb(bd->re_map_port + 2);
-               }
-
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return;
-       }
-
-       /* Our state machine to get the board up and running */
-
-       /* Reset board */
-       if (bd->state == NEED_RESET) {
-
-               /* Get VPD info */
-               dgap_get_vpd(bd);
-
-               dgap_do_reset_board(bd);
-       }
-
-       /* Move to next state */
-       if (bd->state == FINISHED_RESET) {
-               bd->state = NEED_CONFIG;
-       }
-
-       if (bd->state == NEED_CONFIG) {
-               /*
-                * Match this board to a config the user created for us.
-                */
-               bd->bd_config = dgap_find_config(bd->type, bd->pci_bus, bd->pci_slot);
-
-               /*
-                * Because the 4 port Xr products share the same PCI ID
-                * as the 8 port Xr products, if we receive a NULL config
-                * back, and this is a PAPORT8 board, retry with a
-                * PAPORT4 attempt as well.
-                */
-               if (bd->type == PAPORT8 && !bd->bd_config) {
-                       bd->bd_config = dgap_find_config(PAPORT4, bd->pci_bus, bd->pci_slot);
-               }
-
-               /*
-                * Register the ttys (if any) into the kernel.
-                */
-               if (bd->bd_config) {
-                       bd->state = FINISHED_CONFIG;
-               }
-               else {
-                       bd->state = CONFIG_NOT_FOUND;
-               }
-       }
-
-       /* Move to next state */
-       if (bd->state == FINISHED_CONFIG) {
-               bd->state = NEED_DEVICE_CREATION;
-       }
-
-       /* Move to next state */
-       if (bd->state == NEED_DEVICE_CREATION) {
-               /*
-                * Signal downloader, its got some work to do.
-                */
-               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-               if (dgap_dl_action != 1) {
-                       dgap_dl_action = 1;
-                       wake_up_interruptible(&dgap_dl_wait);
-               }
-               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-       }
-
-       /* Move to next state */
-       if (bd->state == FINISHED_DEVICE_CREATION) {
-               bd->state = NEED_BIOS_LOAD;
-       }
-
-       /* Move to next state */
-       if (bd->state == NEED_BIOS_LOAD) {
-               /*
-                * Signal downloader, its got some work to do.
-                */
-               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-               if (dgap_dl_action != 1) {
-                       dgap_dl_action = 1;
-                       wake_up_interruptible(&dgap_dl_wait);
-               }
-               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-       }
-
-       /* Wait for BIOS to test board... */
-       if (bd->state == WAIT_BIOS_LOAD) {
-               dgap_do_wait_for_bios(bd);
-       }
-
-       /* Move to next state */
-       if (bd->state == FINISHED_BIOS_LOAD) {
-               bd->state = NEED_FEP_LOAD;
-
-               /*
-                * Signal downloader, its got some work to do.
-                */
-               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-               if (dgap_dl_action != 1) {
-                       dgap_dl_action = 1;
-                       wake_up_interruptible(&dgap_dl_wait);
-               }
-               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-       }
-
-       /* Wait for FEP to load on board... */
-       if (bd->state == WAIT_FEP_LOAD) {
-               dgap_do_wait_for_fep(bd);
-       }
-
-
-       /* Move to next state */
-       if (bd->state == FINISHED_FEP_LOAD) {
-
-               /*
-                * Do tty device initialization.
-                */
-               int rc = dgap_tty_init(bd);
-
-               if (rc < 0) {
-                       dgap_tty_uninit(bd);
-                       APR(("Can't init tty devices (%d)\n", rc));
-                       bd->state = BOARD_FAILED;
-                       bd->dpastatus = BD_NOFEP;
-               }
-               else {
-                       bd->state = NEED_PROC_CREATION;
-
-                       /*
-                        * Signal downloader, its got some work to do.
-                        */
-                       DGAP_LOCK(dgap_dl_lock, lock_flags2);
-                       if (dgap_dl_action != 1) {
-                               dgap_dl_action = 1;
-                               wake_up_interruptible(&dgap_dl_wait);
-                       }
-                       DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-               }
-       }
-
-       /* Move to next state */
-       if (bd->state == FINISHED_PROC_CREATION) {
-
-               bd->state = BOARD_READY;
-               bd->dpastatus = BD_RUNNING;
-
-               /*
-                * If user requested the board to run in interrupt mode,
-                * go and set it up on the board.
-                */
-               if (bd->intr_used) {
-                       writew(1, (bd->re_map_membase + ENABLE_INTR));
-                       /*
-                        * Tell the board to poll the UARTS as fast as possible.
-                        */
-                       writew(FEPPOLL_MIN, (bd->re_map_membase + FEPPOLL));
-                       bd->intr_running = 1;
-               }
-
-               /* Wake up anyone waiting for board state to change to ready */
-               wake_up_interruptible(&bd->state_wait);
-       }
-
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-}
-
-
-/*=======================================================================
- *
- *      dgap_cmdb - Sends a 2 byte command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              byte1   - Integer containing first byte to be sent.
- *              byte2   - Integer containing second byte to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds)
-{
-       char            *vaddr = NULL;
-       struct cm_t     *cm_addr = NULL;
-       uint            count;
-       uint            n;
-       u16             head;
-       u16             tail;
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       /*
-        * Check if board is still alive.
-        */
-       if (ch->ch_bd->state == BOARD_FAILED) {
-               DPR_CORE(("%s:%d board is in failed state.\n", __FILE__, __LINE__));
-               return;
-       }
-
-       /*
-        * Make sure the pointers are in range before
-        * writing to the FEP memory.
-        */
-       vaddr = ch->ch_bd->re_map_membase;
-
-       if (!vaddr)
-               return;
-
-       cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-       head = readw(&(cm_addr->cm_head));
-
-       /*
-        * Forget it if pointers out of range.
-        */
-       if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-               DPR_CORE(("%s:%d pointers out of range, failing board!\n", __FILE__, __LINE__));
-               ch->ch_bd->state = BOARD_FAILED;
-               return;
-       }
-
-       /*
-        * Put the data in the circular command buffer.
-        */
-       writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
-       writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
-       writeb(byte1, (char *) (vaddr + head + CMDSTART + 2));
-       writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
-
-       head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
-       writew(head, &(cm_addr->cm_head));
-
-       /*
-        * Wait if necessary before updating the head
-        * pointer to limit the number of outstanding
-        * commands to the FEP.   If the time spent waiting
-        * is outlandish, declare the FEP dead.
-        */
-       for (count = dgap_count ;;) {
-
-               head = readw(&(cm_addr->cm_head));
-               tail = readw(&(cm_addr->cm_tail));
-
-               n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-               if (n <= ncmds * sizeof(struct cm_t))
-                       break;
-
-               if (--count == 0) {
-                       DPR_CORE(("%s:%d failing board.\n",__FILE__, __LINE__));
-                       ch->ch_bd->state = BOARD_FAILED;
-                       return;
-               }
-               udelay(10);
-       }
-}
-
-
-/*=======================================================================
- *
- *      dgap_cmdw - Sends a 1 word command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              word    - Integer containing word to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
-{
-       char            *vaddr = NULL;
-       struct cm_t     *cm_addr = NULL;
-       uint            count;
-       uint            n;
-       u16             head;
-       u16             tail;
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       /*
-        * Check if board is still alive.
-        */
-       if (ch->ch_bd->state == BOARD_FAILED) {
-               DPR_CORE(("%s:%d board is failed!\n", __FILE__, __LINE__));
-               return;
-       }
-
-       /*
-        * Make sure the pointers are in range before
-        * writing to the FEP memory.
-        */
-       vaddr = ch->ch_bd->re_map_membase;
-       if (!vaddr)
-               return;
-
-       cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-       head = readw(&(cm_addr->cm_head));
-
-       /*
-        * Forget it if pointers out of range.
-        */
-       if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-               DPR_CORE(("%s:%d Pointers out of range.  Failing board.\n",__FILE__, __LINE__));
-               ch->ch_bd->state = BOARD_FAILED;
-               return;
-       }
-
-       /*
-        * Put the data in the circular command buffer.
-        */
-       writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
-       writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
-       writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
-
-       head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
-       writew(head, &(cm_addr->cm_head));
-
-       /*
-        * Wait if necessary before updating the head
-        * pointer to limit the number of outstanding
-        * commands to the FEP.   If the time spent waiting
-        * is outlandish, declare the FEP dead.
-        */
-       for (count = dgap_count ;;) {
-
-               head = readw(&(cm_addr->cm_head));
-               tail = readw(&(cm_addr->cm_tail));
-
-               n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-               if (n <= ncmds * sizeof(struct cm_t))
-                       break;
-
-               if (--count == 0) {
-                       DPR_CORE(("%s:%d Failing board.\n",__FILE__, __LINE__));
-                       ch->ch_bd->state = BOARD_FAILED;
-                       return;
-               }
-               udelay(10);
-       }
-}
-
-
-
-/*=======================================================================
- *
- *      dgap_cmdw_ext - Sends a extended word command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              word    - Integer containing word to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
-{
-       char            *vaddr = NULL;
-       struct cm_t     *cm_addr = NULL;
-       uint            count;
-       uint            n;
-       u16             head;
-       u16             tail;
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       /*
-        * Check if board is still alive.
-        */
-       if (ch->ch_bd->state == BOARD_FAILED) {
-               DPR_CORE(("%s:%d board is failed!\n", __FILE__, __LINE__));
-               return;
-       }
-
-       /*
-        * Make sure the pointers are in range before
-        * writing to the FEP memory.
-        */
-       vaddr = ch->ch_bd->re_map_membase;
-       if (!vaddr)
-               return;
-
-       cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-       head = readw(&(cm_addr->cm_head));
-
-       /*
-        * Forget it if pointers out of range.
-        */
-       if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-               DPR_CORE(("%s:%d Pointers out of range.  Failing board.\n",__FILE__, __LINE__));
-               ch->ch_bd->state = BOARD_FAILED;
-               return;
-       }
-
-       /*
-        * Put the data in the circular command buffer.
-        */
-
-       /* Write an FF to tell the FEP that we want an extended command */
-       writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
-
-       writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
-       writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
-
-       /*
-        * If the second part of the command won't fit,
-        * put it at the beginning of the circular buffer.
-        */
-       if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03))) {
-               writew((u16) word, (char *) (vaddr + CMDSTART));
-       } else {
-               writew((u16) word, (char *) (vaddr + head + CMDSTART + 4));
-       }
-
-       head = (head + 8) & (CMDMAX - CMDSTART - 4);
-
-       writew(head, &(cm_addr->cm_head));
-
-       /*
-        * Wait if necessary before updating the head
-        * pointer to limit the number of outstanding
-        * commands to the FEP.   If the time spent waiting
-        * is outlandish, declare the FEP dead.
-        */
-       for (count = dgap_count ;;) {
-
-               head = readw(&(cm_addr->cm_head));
-               tail = readw(&(cm_addr->cm_tail));
-
-               n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-               if (n <= ncmds * sizeof(struct cm_t))
-                       break;
-
-               if (--count == 0) {
-                       DPR_CORE(("%s:%d Failing board.\n",__FILE__, __LINE__));
-                       ch->ch_bd->state = BOARD_FAILED;
-                       return;
-               }
-               udelay(10);
-       }
-}
-
-
-/*=======================================================================
- *
- *      dgap_wmove - Write data to FEP buffer.
- *
- *              ch      - Pointer to channel structure.
- *              buf     - Poiter to characters to be moved.
- *              cnt     - Number of characters to move.
- *
- *=======================================================================*/
-void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
-{
-       int    n;
-       char   *taddr;
-       struct bs_t    *bs;
-       u16    head;
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       /*
-        * Check parameters.
-        */
-       bs   = ch->ch_bs;
-       head = readw(&(bs->tx_head));
-
-       /*
-        * If pointers are out of range, just return.
-        */
-       if ((cnt > ch->ch_tsize) || (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize) {
-               DPR_CORE(("%s:%d pointer out of range", __FILE__, __LINE__));
-               return;
-       }
-
-       /*
-        * If the write wraps over the top of the circular buffer,
-        * move the portion up to the wrap point, and reset the
-        * pointers to the bottom.
-        */
-       n = ch->ch_tstart + ch->ch_tsize - head;
-
-       if (cnt >= n) {
-               cnt -= n;
-               taddr = ch->ch_taddr + head;
-               memcpy_toio(taddr, buf, n);
-               head = ch->ch_tstart;
-               buf += n;
-       }
-
-       /*
-        * Move rest of data.
-        */
-       taddr = ch->ch_taddr + head;
-       n = cnt;
-       memcpy_toio(taddr, buf, n);
-       head += cnt;
-
-       writew(head, &(bs->tx_head));
-}
-
-/*
- * Retrives the current custom baud rate from FEP memory,
- * and returns it back to the user.
- * Returns 0 on error.
- */
-uint dgap_get_custom_baud(struct channel_t *ch)
-{
-       uchar *vaddr;
-       ulong offset = 0;
-       uint value = 0;
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-               return 0;
-       }
-
-       if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) {
-               return 0;
-       }
-
-       if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
-               return 0;
-
-       vaddr = ch->ch_bd->re_map_membase;
-
-       if (!vaddr)
-               return 0;
-
-       /*
-        * Go get from fep mem, what the fep
-        * believes the custom baud rate is.
-        */
-       offset = ((((*(unsigned short *)(vaddr + ECS_SEG)) << 4) +
-               (ch->ch_portnum * 0x28) + LINE_SPEED));
-
-       value = readw(vaddr + offset);
-       return value;
-}
-
-
-/*
- * Calls the firmware to reset this channel.
- */
-void dgap_firmware_reset_port(struct channel_t *ch)
-{
-       dgap_cmdb(ch, CHRESET, 0, 0, 0);
-
-       /*
-        * Now that the channel is reset, we need to make sure
-        * all the current settings get reapplied to the port
-        * in the firmware.
-        *
-        * So we will set the driver's cache of firmware
-        * settings all to 0, and then call param.
-        */
-       ch->ch_fepiflag = 0;
-       ch->ch_fepcflag = 0;
-       ch->ch_fepoflag = 0;
-       ch->ch_fepstartc = 0;
-       ch->ch_fepstopc = 0;
-       ch->ch_fepastartc = 0;
-       ch->ch_fepastopc = 0;
-       ch->ch_mostat = 0;
-       ch->ch_hflow = 0;
-}
-
-
-/*=======================================================================
- *
- *      dgap_param - Set Digi parameters.
- *
- *              struct tty_struct *     - TTY for port.
- *
- *=======================================================================*/
-int dgap_param(struct tty_struct *tty)
-{
-       struct ktermios *ts;
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct bs_t   *bs;
-       struct un_t   *un;
-       u16     head;
-       u16     cflag;
-       u16     iflag;
-       uchar   mval;
-       uchar   hflow;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return -ENXIO;
-
-       un = (struct un_t *) tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return -ENXIO;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return -ENXIO;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return -ENXIO;
-
-       bs = ch->ch_bs;
-       if (!bs)
-               return -ENXIO;
-
-       DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
-               ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
-
-       ts = &tty->termios;
-
-       /*
-        * If baud rate is zero, flush queues, and set mval to drop DTR.
-        */
-       if ((ch->ch_c_cflag & (CBAUD)) == 0) {
-
-               /* flush rx */
-               head = readw(&(ch->ch_bs->rx_head));
-               writew(head, &(ch->ch_bs->rx_tail));
-
-               /* flush tx */
-               head = readw(&(ch->ch_bs->tx_head));
-               writew(head, &(ch->ch_bs->tx_tail));
-
-               ch->ch_flags |= (CH_BAUD0);
-
-               /* Drop RTS and DTR */
-               ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
-               mval = D_DTR(ch) | D_RTS(ch);
-               ch->ch_baud_info = 0;
-
-       } else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
-               /*
-                * Tell the fep to do the command
-                */
-
-               DPR_PARAM(("param: Want %d speed\n", ch->ch_custom_speed));
-
-               dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
-
-               /*
-                * Now go get from fep mem, what the fep
-                * believes the custom baud rate is.
-                */
-               ch->ch_baud_info = ch->ch_custom_speed = dgap_get_custom_baud(ch);
-
-               DPR_PARAM(("param: Got %d speed\n", ch->ch_custom_speed));
-
-               /* Handle transition from B0 */
-               if (ch->ch_flags & CH_BAUD0) {
-                       ch->ch_flags &= ~(CH_BAUD0);
-                       ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
-               }
-               mval = D_DTR(ch) | D_RTS(ch);
-
-       } else {
-               /*
-                * Set baud rate, character size, and parity.
-                */
-
-
-               int iindex = 0;
-               int jindex = 0;
-               int baud = 0;
-
-               ulong bauds[4][16] = {
-                       { /* slowbaud */
-                               0,      50,     75,     110,
-                               134,    150,    200,    300,
-                               600,    1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 },
-                       { /* slowbaud & CBAUDEX */
-                               0,      57600,  115200, 230400,
-                               460800, 150,    200,    921600,
-                               600,    1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 },
-                       { /* fastbaud */
-                               0,      57600,  76800,  115200,
-                               14400,  57600,  230400, 76800,
-                               115200, 230400, 28800,  460800,
-                               921600, 9600,   19200,  38400 },
-                       { /* fastbaud & CBAUDEX */
-                               0,      57600,  115200, 230400,
-                               460800, 150,    200,    921600,
-                               600,    1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 }
-               };
-
-               /* Only use the TXPrint baud rate if the terminal unit is NOT open */
-               if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGAP_PRINT))
-                       baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
-               else
-                       baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
-
-               if (ch->ch_c_cflag & CBAUDEX)
-                       iindex = 1;
-
-               if (ch->ch_digi.digi_flags & DIGI_FAST)
-                       iindex += 2;
-
-               jindex = baud;
-
-               if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
-                       baud = bauds[iindex][jindex];
-               } else {
-                       DPR_IOCTL(("baud indices were out of range (%d)(%d)",
-                               iindex, jindex));
-                       baud = 0;
-               }
-
-               if (baud == 0)
-                       baud = 9600;
-
-               ch->ch_baud_info = baud;
-
-
-               /*
-                * CBAUD has bit position 0x1000 set these days to indicate Linux
-                * baud rate remap.
-                * We use a different bit assignment for high speed.  Clear this
-                * bit out while grabbing the parts of "cflag" we want.
-                */
-               cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-
-               /*
-                * HUPCL bit is used by FEP to indicate fast baud
-                * table is to be used.
-                */
-               if ((ch->ch_digi.digi_flags & DIGI_FAST) || (ch->ch_c_cflag & CBAUDEX))
-                       cflag |= HUPCL;
-
-
-               if ((ch->ch_c_cflag & CBAUDEX) && !(ch->ch_digi.digi_flags & DIGI_FAST)) {
-               /*
-                * The below code is trying to guarantee that only baud rates
-                * 115200, 230400, 460800, 921600 are remapped.  We use exclusive or
-                * because the various baud rates share common bit positions
-                * and therefore can't be tested for easily.
-                */
-                       tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
-                       int baudpart = 0;
-
-                       /* Map high speed requests to index into FEP's baud table */
-                       switch (tcflag) {
-                       case B57600 :
-                               baudpart = 1;
-                               break;
-#ifdef B76800
-                       case B76800 :
-                               baudpart = 2;
-                               break;
-#endif
-                       case B115200 :
-                               baudpart = 3;
-                               break;
-                       case B230400 :
-                               baudpart = 9;
-                               break;
-                       case B460800 :
-                               baudpart = 11;
-                               break;
-#ifdef B921600
-                       case B921600 :
-                               baudpart = 12;
-                               break;
-#endif
-                       default:
-                               baudpart = 0;
-                       }
-
-                       if (baudpart)
-                               cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
-               }
-
-               cflag &= 0xffff;
-
-               if (cflag != ch->ch_fepcflag) {
-                       ch->ch_fepcflag = (u16) (cflag & 0xffff);
-
-                       /* Okay to have channel and board locks held calling this */
-                       dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
-               }
-
-               /* Handle transition from B0 */
-               if (ch->ch_flags & CH_BAUD0) {
-                       ch->ch_flags &= ~(CH_BAUD0);
-                       ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
-               }
-               mval = D_DTR(ch) | D_RTS(ch);
-       }
-
-       /*
-        * Get input flags.
-        */
-       iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON | IXANY | IXOFF);
-
-       if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) {
-               iflag &= ~(IXON | IXOFF);
-               ch->ch_c_iflag &= ~(IXON | IXOFF);
-       }
-
-       /*
-        * Only the IBM Xr card can switch between
-        * 232 and 422 modes on the fly
-        */
-       if (bd->device == PCI_DEVICE_XR_IBM_DID) {
-               if (ch->ch_digi.digi_flags & DIGI_422)
-                       dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
-               else
-                       dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
-       }
-
-       if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
-               iflag |= IALTPIN ;
-
-       if (iflag != ch->ch_fepiflag) {
-               ch->ch_fepiflag = iflag;
-
-               /* Okay to have channel and board locks held calling this */
-               dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
-       }
-
-       /*
-        * Select hardware handshaking.
-        */
-       hflow = 0;
-
-       if (ch->ch_c_cflag & CRTSCTS) {
-               hflow |= (D_RTS(ch) | D_CTS(ch));
-       }
-       if (ch->ch_digi.digi_flags & RTSPACE)
-               hflow |= D_RTS(ch);
-       if (ch->ch_digi.digi_flags & DTRPACE)
-               hflow |= D_DTR(ch);
-       if (ch->ch_digi.digi_flags & CTSPACE)
-               hflow |= D_CTS(ch);
-       if (ch->ch_digi.digi_flags & DSRPACE)
-               hflow |= D_DSR(ch);
-       if (ch->ch_digi.digi_flags & DCDPACE)
-               hflow |= D_CD(ch);
-
-       if (hflow != ch->ch_hflow) {
-               ch->ch_hflow = hflow;
-
-               /* Okay to have channel and board locks held calling this */
-               dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
-       }
-
-
-       /*
-        * Set RTS and/or DTR Toggle if needed, but only if product is FEP5+ based.
-        */
-       if (bd->bd_flags & BD_FEP5PLUS) {
-               u16 hflow2 = 0;
-               if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
-                       hflow2 |= (D_RTS(ch));
-               }
-               if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
-                       hflow2 |= (D_DTR(ch));
-               }
-
-               dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
-       }
-
-       /*
-        * Set modem control lines.
-        */
-
-       mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
-
-       DPR_PARAM(("dgap_param: mval: %x ch_mforce: %x ch_mval: %x ch_mostat: %x\n",
-               mval, ch->ch_mforce, ch->ch_mval, ch->ch_mostat));
-
-       if (ch->ch_mostat ^ mval) {
-               ch->ch_mostat = mval;
-
-               /* Okay to have channel and board locks held calling this */
-               DPR_PARAM(("dgap_param: Sending SMODEM mval: %x\n", mval));
-               dgap_cmdb(ch, SMODEM, (uchar) mval, D_RTS(ch)|D_DTR(ch), 0);
-       }
-
-       /*
-        * Read modem signals, and then call carrier function.
-        */
-       ch->ch_mistat = readb(&(bs->m_stat));
-       dgap_carrier(ch);
-
-       /*
-        * Set the start and stop characters.
-        */
-       if (ch->ch_startc != ch->ch_fepstartc || ch->ch_stopc != ch->ch_fepstopc) {
-               ch->ch_fepstartc = ch->ch_startc;
-               ch->ch_fepstopc =  ch->ch_stopc;
-
-               /* Okay to have channel and board locks held calling this */
-               dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
-       }
-
-       /*
-        * Set the Auxiliary start and stop characters.
-        */
-       if (ch->ch_astartc != ch->ch_fepastartc || ch->ch_astopc != ch->ch_fepastopc) {
-               ch->ch_fepastartc = ch->ch_astartc;
-               ch->ch_fepastopc = ch->ch_astopc;
-
-               /* Okay to have channel and board locks held calling this */
-               dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
-       }
-
-       DPR_PARAM(("param finish\n"));
-
-       return 0;
-}
-
-
-/*
- * dgap_parity_scan()
- *
- * Convert the FEP5 way of reporting parity errors and breaks into
- * the Linux line discipline way.
- */
-void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len)
-{
-       int l = *len;
-       int count = 0;
-       unsigned char *in, *cout, *fout;
-       unsigned char c;
-
-       in = cbuf;
-       cout = cbuf;
-       fout = fbuf;
-
-       DPR_PSCAN(("dgap_parity_scan start\n"));
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       while (l--) {
-               c = *in++;
-               switch (ch->pscan_state) {
-               default:
-                       /* reset to sanity and fall through */
-                       ch->pscan_state = 0;
-
-               case 0:
-                       /* No FF seen yet */
-                       if (c == (unsigned char) '\377') {
-                               /* delete this character from stream */
-                               ch->pscan_state = 1;
-                       } else {
-                               *cout++ = c;
-                               *fout++ = TTY_NORMAL;
-                               count += 1;
-                       }
-                       break;
-
-               case 1:
-                       /* first FF seen */
-                       if (c == (unsigned char) '\377') {
-                               /* doubled ff, transform to single ff */
-                               *cout++ = c;
-                               *fout++ = TTY_NORMAL;
-                               count += 1;
-                               ch->pscan_state = 0;
-                       } else {
-                               /* save value examination in next state */
-                               ch->pscan_savechar = c;
-                               ch->pscan_state = 2;
-                       }
-                       break;
-
-               case 2:
-                       /* third character of ff sequence */
-
-                       *cout++ = c;
-
-                       if (ch->pscan_savechar == 0x0) {
-
-                               if (c == 0x0) {
-                                       DPR_PSCAN(("dgap_parity_scan in 3rd char of ff seq. c: %x setting break.\n", c));
-                                       ch->ch_err_break++;
-                                       *fout++ = TTY_BREAK;
-                               }
-                               else {
-                                       DPR_PSCAN(("dgap_parity_scan in 3rd char of ff seq. c: %x setting parity.\n", c));
-                                       ch->ch_err_parity++;
-                                       *fout++ = TTY_PARITY;
-                               }
-                       }
-                       else {
-                               DPR_PSCAN(("%s:%d Logic Error.\n", __FILE__, __LINE__));
-                       }
-
-                       count += 1;
-                       ch->pscan_state = 0;
-               }
-       }
-       *len = count;
-       DPR_PSCAN(("dgap_parity_scan finish\n"));
-}
-
-
-
-
-/*=======================================================================
- *
- *      dgap_event - FEP to host event processing routine.
- *
- *              bd     - Board of current event.
- *
- *=======================================================================*/
-static int dgap_event(struct board_t *bd)
-{
-       struct channel_t *ch;
-       ulong           lock_flags;
-       ulong           lock_flags2;
-       struct bs_t     *bs;
-       uchar           *event;
-       uchar           *vaddr = NULL;
-       struct ev_t     *eaddr = NULL;
-       uint            head;
-       uint            tail;
-       int             port;
-       int             reason;
-       int             modem;
-       int             b1;
-
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return -ENXIO;
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-
-       vaddr = bd->re_map_membase;
-
-       if (!vaddr) {
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return -ENXIO;
-       }
-
-       eaddr = (struct ev_t *) (vaddr + EVBUF);
-
-       /* Get our head and tail */
-       head = readw(&(eaddr->ev_head));
-       tail = readw(&(eaddr->ev_tail));
-
-       /*
-        * Forget it if pointers out of range.
-        */
-
-       if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
-           (head | tail) & 03) {
-               DPR_EVENT(("should be calling xxfail %d\n", __LINE__));
-               /* Let go of board lock */
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return -ENXIO;
-       }
-
-       /*
-        * Loop to process all the events in the buffer.
-        */
-       while (tail != head) {
-
-               /*
-                * Get interrupt information.
-                */
-
-               event = bd->re_map_membase + tail + EVSTART;
-
-               port   = event[0];
-               reason = event[1];
-               modem  = event[2];
-               b1     = event[3];
-
-               DPR_EVENT(("event: jiffies: %ld port: %d reason: %x modem: %x\n",
-                       jiffies, port, reason, modem));
-
-               /*
-                * Make sure the interrupt is valid.
-                */
-               if (port >= bd->nasync)
-                       goto next;
-
-               if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) {
-                       goto next;
-               }
-
-               ch = bd->channels[port];
-
-               if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-                       goto next;
-               }
-
-               /*
-                * If we have made it here, the event was valid.
-                * Lock down the channel.
-                */
-               DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-               bs = ch->ch_bs;
-
-               if (!bs) {
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       goto next;
-               }
-
-               /*
-                * Process received data.
-                */
-               if (reason & IFDATA) {
-
-                       /*
-                        * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
-                        * input could send some data to ld, which in turn
-                        * could do a callback to one of our other functions.
-                        */
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-                       dgap_input(ch);
-
-                       DGAP_LOCK(bd->bd_lock, lock_flags);
-                       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-                       if (ch->ch_flags & CH_RACTIVE)
-                               ch->ch_flags |= CH_RENABLE;
-                       else
-                               writeb(1, &(bs->idata));
-
-                       if (ch->ch_flags & CH_RWAIT) {
-                               ch->ch_flags &= ~CH_RWAIT;
-
-                               wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-                       }
-               }
-
-               /*
-                * Process Modem change signals.
-                */
-               if (reason & IFMODEM) {
-                       ch->ch_mistat = modem;
-                       dgap_carrier(ch);
-               }
-
-               /*
-                * Process break.
-                */
-               if (reason & IFBREAK) {
-
-                       DPR_EVENT(("got IFBREAK\n"));
-
-                       if (ch->ch_tun.un_tty) {
-                               /* A break has been indicated */
-                               ch->ch_err_break++;
-                               tty_buffer_request_room(ch->ch_tun.un_tty->port, 1);
-                               tty_insert_flip_char(ch->ch_tun.un_tty->port, 0, TTY_BREAK);
-                               tty_flip_buffer_push(ch->ch_tun.un_tty->port);
-                       }
-               }
-
-               /*
-                * Process Transmit low.
-                */
-               if (reason & IFTLW) {
-
-                       DPR_EVENT(("event: got low event\n"));
-
-                       if (ch->ch_tun.un_flags & UN_LOW) {
-                               ch->ch_tun.un_flags &= ~UN_LOW;
-
-                               if (ch->ch_tun.un_flags & UN_ISOPEN) {
-                                       if ((ch->ch_tun.un_tty->flags &
-                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                               ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
-                                       {
-                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                                               (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
-                                               DGAP_LOCK(bd->bd_lock, lock_flags);
-                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
-                                       }
-                                       wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
-                                       wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-
-                                       DPR_EVENT(("event: Got low event. jiffies: %lu\n", jiffies));
-                               }
-                       }
-
-                       if (ch->ch_pun.un_flags & UN_LOW) {
-                               ch->ch_pun.un_flags &= ~UN_LOW;
-                               if (ch->ch_pun.un_flags & UN_ISOPEN) {
-                                       if ((ch->ch_pun.un_tty->flags &
-                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                               ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
-                                       {
-                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                                               (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
-                                               DGAP_LOCK(bd->bd_lock, lock_flags);
-                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
-                                       }
-                                       wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
-                                       wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-                               }
-                       }
-
-                       if (ch->ch_flags & CH_WLOW) {
-                               ch->ch_flags &= ~CH_WLOW;
-                               wake_up_interruptible(&ch->ch_flags_wait);
-                       }
-               }
-
-               /*
-                * Process Transmit empty.
-                */
-               if (reason & IFTEM) {
-                       DPR_EVENT(("event: got empty event\n"));
-
-                       if (ch->ch_tun.un_flags & UN_EMPTY) {
-                               ch->ch_tun.un_flags &= ~UN_EMPTY;
-                               if (ch->ch_tun.un_flags & UN_ISOPEN) {
-                                       if ((ch->ch_tun.un_tty->flags &
-                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                               ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
-                                       {
-                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-                                               (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
-                                               DGAP_LOCK(bd->bd_lock, lock_flags);
-                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
-                                       }
-                                       wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
-                                       wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-                               }
-                       }
-
-                       if (ch->ch_pun.un_flags & UN_EMPTY) {
-                               ch->ch_pun.un_flags &= ~UN_EMPTY;
-                               if (ch->ch_pun.un_flags & UN_ISOPEN) {
-                                       if ((ch->ch_pun.un_tty->flags &
-                                          (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                               ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
-                                       {
-                                               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                                               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                                               (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
-                                               DGAP_LOCK(bd->bd_lock, lock_flags);
-                                               DGAP_LOCK(ch->ch_lock, lock_flags2);
-                                       }
-                                       wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
-                                       wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-                               }
-                       }
-
-
-                       if (ch->ch_flags & CH_WEMPTY) {
-                               ch->ch_flags &= ~CH_WEMPTY;
-                               wake_up_interruptible(&ch->ch_flags_wait);
-                       }
-               }
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-
-next:
-               tail = (tail + 4) & (EVMAX - EVSTART - 4);
-       }
-
-       writew(tail, &(eaddr->ev_tail));
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       return 0;
-}
diff --git a/drivers/staging/dgap/dgap_fep5.h b/drivers/staging/dgap/dgap_fep5.h
deleted file mode 100644 (file)
index d0650ae..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- ************************************************************************
- ***   FEP Version 5 dependent definitions
- ************************************************************************/
-
-#ifndef __DGAP_FEP5_H
-#define __DGAP_FEP5_H
-
-/************************************************************************
- *      FEP memory offsets
- ************************************************************************/
-#define START           0x0004L         /* Execution start address      */
-
-#define CMDBUF          0x0d10L         /* Command (cm_t) structure offset */
-#define CMDSTART        0x0400L         /* Start of command buffer      */
-#define CMDMAX          0x0800L         /* End of command buffer        */
-
-#define EVBUF           0x0d18L         /* Event (ev_t) structure       */
-#define EVSTART         0x0800L         /* Start of event buffer        */
-#define EVMAX           0x0c00L         /* End of event buffer          */
-#define FEP5_PLUS       0x0E40          /* ASCII '5' and ASCII 'A' is here  */
-#define ECS_SEG         0x0E44          /* Segment of the extended channel structure */
-#define LINE_SPEED      0x10            /* Offset into ECS_SEG for line speed   */
-                                        /* if the fep has extended capabilities */
-
-/* BIOS MAGIC SPOTS */
-#define ERROR           0x0C14L                /* BIOS error code              */
-#define SEQUENCE       0x0C12L         /* BIOS sequence indicator      */
-#define POSTAREA       0x0C00L         /* POST complete message area   */
-
-/* FEP MAGIC SPOTS */
-#define FEPSTAT         POSTAREA        /* OS here when FEP comes up    */
-#define NCHAN           0x0C02L         /* number of ports FEP sees     */
-#define PANIC           0x0C10L         /* PANIC area for FEP           */
-#define KMEMEM          0x0C30L         /* Memory for KME use           */
-#define CONFIG          0x0CD0L         /* Concentrator configuration info */
-#define CONFIGSIZE      0x0030          /* configuration info size      */
-#define DOWNREQ         0x0D00          /* Download request buffer pointer */
-
-#define CHANBUF         0x1000L         /* Async channel (bs_t) structs */
-#define FEPOSSIZE       0x1FFF          /* 8K FEPOS                     */
-
-#define XEMPORTS    0xC02      /*
-                                * Offset in board memory where FEP5 stores
-                                * how many ports it has detected.
-                                * NOTE: FEP5 reports 64 ports when the user
-                                * has the cable in EBI OUT instead of EBI IN.
-                                */
-
-#define FEPCLR      0x00
-#define FEPMEM      0x02
-#define FEPRST      0x04
-#define FEPINT      0x08
-#define FEPMASK     0x0e
-#define FEPWIN      0x80
-
-#define LOWMEM      0x0100
-#define HIGHMEM     0x7f00
-
-#define FEPTIMEOUT 200000
-
-#define ENABLE_INTR            0x0e04          /* Enable interrupts flag */
-#define FEPPOLL_MIN            1               /* minimum of 1 millisecond */
-#define FEPPOLL_MAX            20              /* maximum of 20 milliseconds */
-#define FEPPOLL                        0x0c26          /* Fep event poll interval */
-
-#define        IALTPIN                 0x0080          /* Input flag to swap DSR <-> DCD */
-
-/************************************************************************
- * Command structure definition.
- ************************************************************************/
-struct cm_t {
-       volatile unsigned short cm_head;        /* Command buffer head offset   */
-       volatile unsigned short cm_tail;        /* Command buffer tail offset   */
-       volatile unsigned short cm_start;       /* start offset of buffer       */
-       volatile unsigned short cm_max;         /* last offset of buffer        */
-};
-
-/************************************************************************
- * Event structure definition.
- ************************************************************************/
-struct ev_t {
-       volatile unsigned short ev_head;        /* Command buffer head offset   */
-       volatile unsigned short ev_tail;        /* Command buffer tail offset   */
-       volatile unsigned short ev_start;       /* start offset of buffer       */
-       volatile unsigned short ev_max;         /* last offset of buffer        */
-};
-
-/************************************************************************
- * Download buffer structure.
- ************************************************************************/
-struct downld_t {
-       uchar   dl_type;                /* Header                       */
-       uchar   dl_seq;                 /* Download sequence            */
-       ushort  dl_srev;                /* Software revision number     */
-       ushort  dl_lrev;                /* Low revision number          */
-       ushort  dl_hrev;                /* High revision number         */
-       ushort  dl_seg;                 /* Start segment address        */
-       ushort  dl_size;                /* Number of bytes to download  */
-       uchar   dl_data[1024];          /* Download data                */
-};
-
-/************************************************************************
- * Per channel buffer structure
- ************************************************************************
- *              Base Structure Entries Usage Meanings to Host           *
- *                                                                      *
- *        W = read write        R = read only                           *
- *        C = changed by commands only                                  *
- *        U = unknown (may be changed w/o notice)                       *
- ************************************************************************/
-struct bs_t {
-       volatile unsigned short  tp_jmp;        /* Transmit poll jump            */
-       volatile unsigned short  tc_jmp;        /* Cooked procedure jump         */
-       volatile unsigned short  ri_jmp;        /* Not currently used            */
-       volatile unsigned short  rp_jmp;        /* Receive poll jump             */
-
-       volatile unsigned short  tx_seg;        /* W  Tx segment         */
-       volatile unsigned short  tx_head;       /* W  Tx buffer head offset     */
-       volatile unsigned short  tx_tail;       /* R  Tx buffer tail offset     */
-       volatile unsigned short  tx_max;        /* W  Tx buffer size - 1         */
-
-       volatile unsigned short  rx_seg;        /* W  Rx segment                */
-       volatile unsigned short  rx_head;       /* W  Rx buffer head offset     */
-       volatile unsigned short  rx_tail;       /* R  Rx buffer tail offset     */
-       volatile unsigned short  rx_max;        /* W  Rx buffer size - 1         */
-
-       volatile unsigned short  tx_lw;         /* W  Tx buffer low water mark  */
-       volatile unsigned short  rx_lw;         /* W  Rx buffer low water mark  */
-       volatile unsigned short  rx_hw;         /* W  Rx buffer high water mark */
-       volatile unsigned short  incr;          /* W  Increment to next channel */
-
-       volatile unsigned short  fepdev;        /* U  SCC device base address    */
-       volatile unsigned short  edelay;        /* W  Exception delay            */
-       volatile unsigned short  blen;          /* W  Break length              */
-       volatile unsigned short  btime;         /* U  Break complete time       */
-
-       volatile unsigned short  iflag;         /* C  UNIX input flags          */
-       volatile unsigned short  oflag;         /* C  UNIX output flags         */
-       volatile unsigned short  cflag;         /* C  UNIX control flags        */
-       volatile unsigned short  wfill[13];     /* U  Reserved for expansion    */
-
-       volatile unsigned char   num;           /* U  Channel number            */
-       volatile unsigned char   ract;          /* U  Receiver active counter   */
-       volatile unsigned char   bstat;         /* U  Break status bits         */
-       volatile unsigned char   tbusy;         /* W  Transmit busy             */
-       volatile unsigned char   iempty;        /* W  Transmit empty event enable */
-       volatile unsigned char   ilow;          /* W  Transmit low-water event enable */
-       volatile unsigned char   idata;         /* W  Receive data interrupt enable */
-       volatile unsigned char   eflag;         /* U  Host event flags          */
-
-       volatile unsigned char   tflag;         /* U  Transmit flags            */
-       volatile unsigned char   rflag;         /* U  Receive flags             */
-       volatile unsigned char   xmask;         /* U  Transmit ready flags      */
-       volatile unsigned char   xval;          /* U  Transmit ready value      */
-       volatile unsigned char   m_stat;        /* RC Modem status bits          */
-       volatile unsigned char   m_change;      /* U  Modem bits which changed  */
-       volatile unsigned char   m_int;         /* W  Modem interrupt enable bits */
-       volatile unsigned char   m_last;        /* U  Last modem status         */
-
-       volatile unsigned char   mtran;         /* C   Unreported modem trans   */
-       volatile unsigned char   orun;          /* C   Buffer overrun occurred  */
-       volatile unsigned char   astartc;       /* W   Auxiliary Xon char       */
-       volatile unsigned char   astopc;        /* W   Auxiliary Xoff char      */
-       volatile unsigned char   startc;        /* W   Xon character             */
-       volatile unsigned char   stopc;         /* W   Xoff character           */
-       volatile unsigned char   vnextc;        /* W   Vnext character           */
-       volatile unsigned char   hflow;         /* C   Software flow control    */
-
-       volatile unsigned char   fillc;         /* U   Delay Fill character     */
-       volatile unsigned char   ochar;         /* U   Saved output character   */
-       volatile unsigned char   omask;         /* U   Output character mask    */
-
-       volatile unsigned char   bfill[13];     /* U   Reserved for expansion   */
-
-       volatile unsigned char   scc[16];       /* U   SCC registers            */
-};
-
-
-/************************************************************************
- * FEP supported functions
- ************************************************************************/
-#define SRLOW          0xe0            /* Set receive low water        */
-#define SRHIGH         0xe1            /* Set receive high water       */
-#define FLUSHTX                0xe2            /* Flush transmit buffer        */
-#define PAUSETX                0xe3            /* Pause data transmission      */
-#define RESUMETX       0xe4            /* Resume data transmission     */
-#define SMINT          0xe5            /* Set Modem Interrupt          */
-#define SAFLOWC                0xe6            /* Set Aux. flow control chars  */
-#define SBREAK         0xe8            /* Send break                   */
-#define SMODEM         0xe9            /* Set 8530 modem control lines */
-#define SIFLAG         0xea            /* Set UNIX iflags              */
-#define SFLOWC         0xeb            /* Set flow control characters  */
-#define STLOW          0xec            /* Set transmit low water mark  */
-#define RPAUSE         0xee            /* Pause receive                */
-#define RRESUME                0xef            /* Resume receive               */
-#define CHRESET                0xf0            /* Reset Channel                */
-#define BUFSETALL      0xf2            /* Set Tx & Rx buffer size avail*/
-#define SOFLAG         0xf3            /* Set UNIX oflags              */
-#define SHFLOW         0xf4            /* Set hardware handshake       */
-#define SCFLAG         0xf5            /* Set UNIX cflags              */
-#define SVNEXT         0xf6            /* Set VNEXT character          */
-#define SPINTFC                0xfc            /* Reserved                     */
-#define SCOMMODE       0xfd            /* Set RS232/422 mode           */
-
-
-/************************************************************************
- *     Modes for SCOMMODE
- ************************************************************************/
-#define MODE_232       0x00
-#define MODE_422       0x01
-
-
-/************************************************************************
- *      Event flags.
- ************************************************************************/
-#define IFBREAK         0x01            /* Break received               */
-#define IFTLW           0x02            /* Transmit low water           */
-#define IFTEM           0x04            /* Transmitter empty            */
-#define IFDATA          0x08            /* Receive data present         */
-#define IFMODEM         0x20            /* Modem status change          */
-
-/************************************************************************
- *      Modem flags
- ************************************************************************/
-#       define  DM_RTS          0x02    /* Request to send              */
-#       define  DM_CD           0x80    /* Carrier detect               */
-#       define  DM_DSR          0x20    /* Data set ready               */
-#       define  DM_CTS          0x10    /* Clear to send                */
-#       define  DM_RI           0x40    /* Ring indicator               */
-#       define  DM_DTR          0x01    /* Data terminal ready          */
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_kcompat.h b/drivers/staging/dgap/dgap_kcompat.h
deleted file mode 100644 (file)
index 0dc2404..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * This file is intended to contain all the kernel "differences" between the
- * various kernels that we support.
- *
- *************************************************************************/
-
-#ifndef __DGAP_KCOMPAT_H
-#define __DGAP_KCOMPAT_H
-
-#if !defined(TTY_FLIPBUF_SIZE)
-# define TTY_FLIPBUF_SIZE 512
-#endif
-
-
-/* Sparse stuff */
-# ifndef __user
-#  define __user
-#  define __kernel
-#  define __safe
-#  define __force
-#  define __chk_user_ptr(x) (void)0
-# endif
-
-
-#  define PARM_STR(VAR, INIT, PERM, DESC) \
-               static char *VAR = INIT; \
-               char *dgap_##VAR; \
-               module_param(VAR, charp, PERM); \
-               MODULE_PARM_DESC(VAR, DESC);
-
-#  define PARM_INT(VAR, INIT, PERM, DESC) \
-               static int VAR = INIT; \
-               int dgap_##VAR; \
-               module_param(VAR, int, PERM); \
-               MODULE_PARM_DESC(VAR, DESC);
-
-#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
-               static ulong VAR = INIT; \
-               ulong dgap_##VAR; \
-               module_param(VAR, long, PERM); \
-               MODULE_PARM_DESC(VAR, DESC);
-
-#endif /* ! __DGAP_KCOMPAT_H */
diff --git a/drivers/staging/dgap/dgap_parse.c b/drivers/staging/dgap/dgap_parse.c
deleted file mode 100644 (file)
index 7bc5bc3..0000000
+++ /dev/null
@@ -1,1374 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
- *
- *****************************************************************************
- *
- * dgap_parse.c - Parses the configuration information from the input file.
- *
- * $Id: dgap_parse.c,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- */
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
-
-#include "dgap_types.h"
-#include "dgap_fep5.h"
-#include "dgap_driver.h"
-#include "dgap_parse.h"
-#include "dgap_conf.h"
-
-
-/*
- * Function prototypes.
- */
-static int dgap_gettok(char **in, struct cnode *p);
-static char *dgap_getword(char **in);
-static char *dgap_savestring(char *s);
-static struct cnode *dgap_newnode(int t);
-static int dgap_checknode(struct cnode *p);
-static void dgap_err(char *s);
-
-/*
- * Our needed internal static variables...
- */
-static struct cnode dgap_head;
-#define MAXCWORD 200
-static char dgap_cword[MAXCWORD];
-
-struct toklist {
-       int     token;
-       char    *string;
-};
-
-static struct toklist dgap_tlist[] = {
-       {       BEGIN,          "config_begin"                  },
-       {       END,            "config_end"                    },
-       {       BOARD,          "board"                         },
-       {       PCX,            "Digi_AccelePort_C/X_PCI"       },      /* C/X_PCI */
-       {       PEPC,           "Digi_AccelePort_EPC/X_PCI"     },      /* EPC/X_PCI */
-       {       PPCM,           "Digi_AccelePort_Xem_PCI"       },      /* PCI/Xem */
-       {       APORT2_920P,    "Digi_AccelePort_2r_920_PCI"    },
-       {       APORT4_920P,    "Digi_AccelePort_4r_920_PCI"    },
-       {       APORT8_920P,    "Digi_AccelePort_8r_920_PCI"    },
-       {       PAPORT4,        "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
-       {       PAPORT8,        "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
-       {       IO,             "io"                            },
-       {       PCIINFO,        "pciinfo"                       },
-       {       LINE,           "line"                          },
-       {       CONC,           "conc"                          },
-       {       CONC,           "concentrator"                  },
-       {       CX,             "cx"                            },
-       {       CX,             "ccon"                          },
-       {       EPC,            "epccon"                        },
-       {       EPC,            "epc"                           },
-       {       MOD,            "module"                        },
-       {       ID,             "id"                            },
-       {       STARTO,         "start"                         },
-       {       SPEED,          "speed"                         },
-       {       CABLE,          "cable"                         },
-       {       CONNECT,        "connect"                       },
-       {       METHOD,         "method"                        },
-       {       STATUS,         "status"                        },
-       {       CUSTOM,         "Custom"                        },
-       {       BASIC,          "Basic"                         },
-       {       MEM,            "mem"                           },
-       {       MEM,            "memory"                        },
-       {       PORTS,          "ports"                         },
-       {       MODEM,          "modem"                         },
-       {       NPORTS,         "nports"                        },
-       {       TTYN,           "ttyname"                       },
-       {       CU,             "cuname"                        },
-       {       PRINT,          "prname"                        },
-       {       CMAJOR,         "major"                         },
-       {       ALTPIN,         "altpin"                        },
-       {       USEINTR,        "useintr"                       },
-       {       TTSIZ,          "ttysize"                       },
-       {       CHSIZ,          "chsize"                        },
-       {       BSSIZ,          "boardsize"                     },
-       {       UNTSIZ,         "schedsize"                     },
-       {       F2SIZ,          "f2200size"                     },
-       {       VPSIZ,          "vpixsize"                      },
-       {       0,              NULL                            }
-};
-
-
-/*
- * Parse a configuration file read into memory as a string.
- */
-int    dgap_parsefile(char **in, int Remove)
-{
-       struct cnode *p, *brd, *line, *conc;
-       int     rc;
-       char    *s = NULL, *s2 = NULL;
-       int     linecnt = 0;
-
-       p = &dgap_head;
-       brd = line = conc = NULL;
-
-       /* perhaps we are adding to an existing list? */
-       while (p->next != NULL) {
-               p = p->next;
-       }
-
-       /* file must start with a BEGIN */
-       while ( (rc = dgap_gettok(in,p)) != BEGIN ) {
-               if (rc == 0) {
-                       dgap_err("unexpected EOF");
-                       return(-1);
-               }
-       }
-
-       for (; ; ) {
-               rc = dgap_gettok(in,p);
-               if (rc == 0) {
-                       dgap_err("unexpected EOF");
-                       return(-1);
-               }
-
-               switch (rc) {
-               case 0:
-                       dgap_err("unexpected end of file");
-                       return(-1);
-
-               case BEGIN:     /* should only be 1 begin */
-                       dgap_err("unexpected config_begin\n");
-                       return(-1);
-
-               case END:
-                       return(0);
-
-               case BOARD:     /* board info */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(BNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-
-                       p->u.board.status = dgap_savestring("No");
-                       line = conc = NULL;
-                       brd = p;
-                       linecnt = -1;
-                       break;
-
-               case APORT2_920P:       /* AccelePort_4 */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected Digi_2r_920 string");
-                               return(-1);
-                       }
-                       p->u.board.type = APORT2_920P;
-                       p->u.board.v_type = 1;
-                       DPR_INIT(("Adding Digi_2r_920 PCI to config...\n"));
-                       break;
-
-               case APORT4_920P:       /* AccelePort_4 */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected Digi_4r_920 string");
-                               return(-1);
-                       }
-                       p->u.board.type = APORT4_920P;
-                       p->u.board.v_type = 1;
-                       DPR_INIT(("Adding Digi_4r_920 PCI to config...\n"));
-                       break;
-
-               case APORT8_920P:       /* AccelePort_8 */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected Digi_8r_920 string");
-                               return(-1);
-                       }
-                       p->u.board.type = APORT8_920P;
-                       p->u.board.v_type = 1;
-                       DPR_INIT(("Adding Digi_8r_920 PCI to config...\n"));
-                       break;
-
-               case PAPORT4:   /* AccelePort_4 PCI */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected Digi_4r(PCI) string");
-                               return(-1);
-                       }
-                       p->u.board.type = PAPORT4;
-                       p->u.board.v_type = 1;
-                       DPR_INIT(("Adding Digi_4r PCI to config...\n"));
-                       break;
-
-               case PAPORT8:   /* AccelePort_8 PCI */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected Digi_8r string");
-                               return(-1);
-                       }
-                       p->u.board.type = PAPORT8;
-                       p->u.board.v_type = 1;
-                       DPR_INIT(("Adding Digi_8r PCI to config...\n"));
-                       break;
-
-               case PCX:       /* PCI C/X */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected Digi_C/X_(PCI) string");
-                               return(-1);
-                       }
-                       p->u.board.type = PCX;
-                       p->u.board.v_type = 1;
-                       p->u.board.conc1 = 0;
-                       p->u.board.conc2 = 0;
-                       p->u.board.module1 = 0;
-                       p->u.board.module2 = 0;
-                       DPR_INIT(("Adding PCI C/X to config...\n"));
-                       break;
-
-               case PEPC:      /* PCI EPC/X */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
-                               return(-1);
-                       }
-                       p->u.board.type = PEPC;
-                       p->u.board.v_type = 1;
-                       p->u.board.conc1 = 0;
-                       p->u.board.conc2 = 0;
-                       p->u.board.module1 = 0;
-                       p->u.board.module2 = 0;
-                       DPR_INIT(("Adding PCI EPC/X to config...\n"));
-                       break;
-
-               case PPCM:      /* PCI/Xem */
-                       if (p->type != BNODE) {
-                               dgap_err("unexpected PCI/Xem string");
-                               return(-1);
-                       }
-                       p->u.board.type = PPCM;
-                       p->u.board.v_type = 1;
-                       p->u.board.conc1 = 0;
-                       p->u.board.conc2 = 0;
-                       DPR_INIT(("Adding PCI XEM to config...\n"));
-                       break;
-
-               case IO:        /* i/o port */
-                       if (p->type != BNODE) {
-                               dgap_err("IO port only vaild for boards");
-                               return(-1);
-                       }
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.board.portstr = dgap_savestring(s);
-                       p->u.board.port = (short)simple_strtol(s, &s2, 0);
-                       if ((short)strlen(s) > (short)(s2 - s)) {
-                               dgap_err("bad number for IO port");
-                               return(-1);
-                       }
-                       p->u.board.v_port = 1;
-                       DPR_INIT(("Adding IO (%s) to config...\n", s));
-                       break;
-
-               case MEM:       /* memory address */
-                       if (p->type != BNODE) {
-                               dgap_err("memory address only vaild for boards");
-                               return(-1);
-                       }
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.board.addrstr = dgap_savestring(s);
-                       p->u.board.addr = simple_strtoul(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for memory address");
-                               return(-1);
-                       }
-                       p->u.board.v_addr = 1;
-                       DPR_INIT(("Adding MEM (%s) to config...\n", s));
-                       break;
-
-               case PCIINFO:   /* pci information */
-                       if (p->type != BNODE) {
-                               dgap_err("memory address only vaild for boards");
-                               return(-1);
-                       }
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.board.pcibusstr = dgap_savestring(s);
-                       p->u.board.pcibus = simple_strtoul(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for pci bus");
-                               return(-1);
-                       }
-                       p->u.board.v_pcibus = 1;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.board.pcislotstr = dgap_savestring(s);
-                       p->u.board.pcislot = simple_strtoul(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for pci slot");
-                               return(-1);
-                       }
-                       p->u.board.v_pcislot = 1;
-
-                       DPR_INIT(("Adding PCIINFO (%s %s) to config...\n", p->u.board.pcibusstr,
-                               p->u.board.pcislotstr));
-                       break;
-
-               case METHOD:
-                       if (p->type != BNODE) {
-                               dgap_err("install method only vaild for boards");
-                               return(-1);
-                       }
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.board.method = dgap_savestring(s);
-                       p->u.board.v_method = 1;
-                       DPR_INIT(("Adding METHOD (%s) to config...\n", s));
-                       break;
-
-               case STATUS:
-                       if (p->type != BNODE) {
-                               dgap_err("config status only vaild for boards");
-                               return(-1);
-                       }
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.board.status = dgap_savestring(s);
-                       DPR_INIT(("Adding STATUS (%s) to config...\n", s));
-                       break;
-
-               case NPORTS:    /* number of ports */
-                       if (p->type == BNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.board.nport = (char)simple_strtol(s, &s2, 0);
-                               if ((int)strlen(s) > (int)(s2 - s)) {
-                                       dgap_err("bad number for number of ports");
-                                       return(-1);
-                               }
-                               p->u.board.v_nport = 1;
-                       } else if (p->type == CNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
-                               if ((int)strlen(s) > (int)(s2 - s)) {
-                                       dgap_err("bad number for number of ports");
-                                       return(-1);
-                               }
-                               p->u.conc.v_nport = 1;
-                       } else if (p->type == MNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.module.nport = (char)simple_strtol(s, &s2, 0);
-                               if ((int)strlen(s) > (int)(s2 - s)) {
-                                       dgap_err("bad number for number of ports");
-                                       return(-1);
-                               }
-                               p->u.module.v_nport = 1;
-                       } else {
-                               dgap_err("nports only valid for concentrators or modules");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding NPORTS (%s) to config...\n", s));
-                       break;
-
-               case ID:        /* letter ID used in tty name */
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-
-                       p->u.board.status = dgap_savestring(s);
-
-                       if (p->type == CNODE) {
-                               p->u.conc.id = dgap_savestring(s);
-                               p->u.conc.v_id = 1;
-                       } else if (p->type == MNODE) {
-                               p->u.module.id = dgap_savestring(s);
-                               p->u.module.v_id = 1;
-                       } else {
-                               dgap_err("id only valid for concentrators or modules");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding ID (%s) to config...\n", s));
-                       break;
-
-               case STARTO:    /* start offset of ID */
-                       if (p->type == BNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.board.start = simple_strtol(s, &s2, 0);
-                               if ((int)strlen(s) > (int)(s2 - s)) {
-                                       dgap_err("bad number for start of tty count");
-                                       return(-1);
-                               }
-                               p->u.board.v_start = 1;
-                       } else if (p->type == CNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.conc.start = simple_strtol(s, &s2, 0);
-                               if ((int)strlen(s) > (int)(s2 - s)) {
-                                       dgap_err("bad number for start of tty count");
-                                       return(-1);
-                               }
-                               p->u.conc.v_start = 1;
-                       } else if (p->type == MNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.module.start = simple_strtol(s, &s2, 0);
-                               if ((int)strlen(s) > (int)(s2 - s)) {
-                                       dgap_err("bad number for start of tty count");
-                                       return(-1);
-                               }
-                               p->u.module.v_start = 1;
-                       } else {
-                               dgap_err("start only valid for concentrators or modules");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding START (%s) to config...\n", s));
-                       break;
-
-               case TTYN:      /* tty name prefix */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(TNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       if ( (s = dgap_getword(in)) == NULL ) {
-                               dgap_err("unexpeced end of file");
-                               return(-1);
-                       }
-                       if ( (p->u.ttyname = dgap_savestring(s)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding TTY (%s) to config...\n", s));
-                       break;
-
-               case CU:        /* cu name prefix */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(CUNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       if ( (s = dgap_getword(in)) == NULL ) {
-                               dgap_err("unexpeced end of file");
-                               return(-1);
-                       }
-                       if ( (p->u.cuname = dgap_savestring(s)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding CU (%s) to config...\n", s));
-                       break;
-
-               case LINE:      /* line information */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if (brd == NULL) {
-                               dgap_err("must specify board before line info");
-                               return(-1);
-                       }
-                       switch (brd->u.board.type) {
-                       case PPCM:
-                               dgap_err("line not vaild for PC/em");
-                               return(-1);
-                       }
-                       if ( (p->next = dgap_newnode(LNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       conc = NULL;
-                       line = p;
-                       linecnt++;
-                       DPR_INIT(("Adding LINE to config...\n"));
-                       break;
-
-               case CONC:      /* concentrator information */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if (line == NULL) {
-                               dgap_err("must specify line info before concentrator");
-                               return(-1);
-                       }
-                       if ( (p->next = dgap_newnode(CNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       conc = p;
-                       if (linecnt)
-                               brd->u.board.conc2++;
-                       else
-                               brd->u.board.conc1++;
-
-                       DPR_INIT(("Adding CONC to config...\n"));
-                       break;
-
-               case CX:        /* c/x type concentrator */
-                       if (p->type != CNODE) {
-                               dgap_err("cx only valid for concentrators");
-                               return(-1);
-                       }
-                       p->u.conc.type = CX;
-                       p->u.conc.v_type = 1;
-                       DPR_INIT(("Adding CX to config...\n"));
-                       break;
-
-               case EPC:       /* epc type concentrator */
-                       if (p->type != CNODE) {
-                               dgap_err("cx only valid for concentrators");
-                               return(-1);
-                       }
-                       p->u.conc.type = EPC;
-                       p->u.conc.v_type = 1;
-                       DPR_INIT(("Adding EPC to config...\n"));
-                       break;
-
-               case MOD:       /* EBI module */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if (brd == NULL) {
-                               dgap_err("must specify board info before EBI modules");
-                               return(-1);
-                       }
-                       switch (brd->u.board.type) {
-                       case PPCM:
-                               linecnt = 0;
-                               break;
-                       default:
-                               if (conc == NULL) {
-                                       dgap_err("must specify concentrator info before EBI module");
-                                       return(-1);
-                               }
-                       }
-                       if ( (p->next = dgap_newnode(MNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       if (linecnt)
-                               brd->u.board.module2++;
-                       else
-                               brd->u.board.module1++;
-
-                       DPR_INIT(("Adding MOD to config...\n"));
-                       break;
-
-               case PORTS:     /* ports type EBI module */
-                       if (p->type != MNODE) {
-                               dgap_err("ports only valid for EBI modules");
-                               return(-1);
-                       }
-                       p->u.module.type = PORTS;
-                       p->u.module.v_type = 1;
-                       DPR_INIT(("Adding PORTS to config...\n"));
-                       break;
-
-               case MODEM:     /* ports type EBI module */
-                       if (p->type != MNODE) {
-                               dgap_err("modem only valid for modem modules");
-                               return(-1);
-                       }
-                       p->u.module.type = MODEM;
-                       p->u.module.v_type = 1;
-                       DPR_INIT(("Adding MODEM to config...\n"));
-                       break;
-
-               case CABLE:
-                       if (p->type == LNODE) {
-                               if ((s = dgap_getword(in)) == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.line.cable = dgap_savestring(s);
-                               p->u.line.v_cable = 1;
-                       }
-                       DPR_INIT(("Adding CABLE (%s) to config...\n", s));
-                       break;
-
-               case SPEED:     /* sync line speed indication */
-                       if (p->type == LNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.line.speed = (char)simple_strtol(s, &s2, 0);
-                               if ((short)strlen(s) > (short)(s2 - s)) {
-                                       dgap_err("bad number for line speed");
-                                       return(-1);
-                               }
-                               p->u.line.v_speed = 1;
-                       } else if (p->type == CNODE) {
-                               s = dgap_getword(in);
-                               if (s == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
-                               if ((short)strlen(s) > (short)(s2 - s)) {
-                                       dgap_err("bad number for line speed");
-                                       return(-1);
-                               }
-                               p->u.conc.v_speed = 1;
-                       } else {
-                               dgap_err("speed valid only for lines or concentrators.");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding SPEED (%s) to config...\n", s));
-                       break;
-
-               case CONNECT:
-                       if (p->type == CNODE) {
-                               if ((s = dgap_getword(in)) == NULL) {
-                                       dgap_err("unexpected end of file");
-                                       return(-1);
-                               }
-                               p->u.conc.connect = dgap_savestring(s);
-                               p->u.conc.v_connect = 1;
-                       }
-                       DPR_INIT(("Adding CONNECT (%s) to config...\n", s));
-                       break;
-               case PRINT:     /* transparent print name prefix */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(PNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       if ( (s = dgap_getword(in)) == NULL ) {
-                               dgap_err("unexpeced end of file");
-                               return(-1);
-                       }
-                       if ( (p->u.printname = dgap_savestring(s)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding PRINT (%s) to config...\n", s));
-                       break;
-
-               case CMAJOR:    /* major number */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(JNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.majornumber = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for major number");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding CMAJOR (%s) to config...\n", s));
-                       break;
-
-               case ALTPIN:    /* altpin setting */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(ANODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.altpin = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for altpin");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding ALTPIN (%s) to config...\n", s));
-                       break;
-
-               case USEINTR:           /* enable interrupt setting */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(INTRNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.useintr = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for useintr");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding USEINTR (%s) to config...\n", s));
-                       break;
-
-               case TTSIZ:     /* size of tty structure */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(TSNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.ttysize = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for ttysize");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding TTSIZ (%s) to config...\n", s));
-                       break;
-
-               case CHSIZ:     /* channel structure size */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(CSNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.chsize = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for chsize");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding CHSIZE (%s) to config...\n", s));
-                       break;
-
-               case BSSIZ:     /* board structure size */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(BSNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.bssize = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for bssize");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding BSSIZ (%s) to config...\n", s));
-                       break;
-
-               case UNTSIZ:    /* sched structure size */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(USNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.unsize = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for schedsize");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding UNTSIZ (%s) to config...\n", s));
-                       break;
-
-               case F2SIZ:     /* f2200 structure size */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(FSNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.f2size = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for f2200size");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding F2SIZ (%s) to config...\n", s));
-                       break;
-
-               case VPSIZ:     /* vpix structure size */
-                       if (dgap_checknode(p))
-                               return(-1);
-                       if ( (p->next = dgap_newnode(VSNODE)) == NULL ) {
-                               dgap_err("out of memory");
-                               return(-1);
-                       }
-                       p = p->next;
-                       s = dgap_getword(in);
-                       if (s == NULL) {
-                               dgap_err("unexpected end of file");
-                               return(-1);
-                       }
-                       p->u.vpixsize = simple_strtol(s, &s2, 0);
-                       if ((int)strlen(s) > (int)(s2 - s)) {
-                               dgap_err("bad number for vpixsize");
-                               return(-1);
-                       }
-                       DPR_INIT(("Adding VPSIZ (%s) to config...\n", s));
-                       break;
-               }
-       }
-}
-
-
-/*
- * dgap_sindex: much like index(), but it looks for a match of any character in
- * the group, and returns that position.  If the first character is a ^, then
- * this will match the first occurrence not in that group.
- */
-static char *dgap_sindex (char *string, char *group)
-{
-       char    *ptr;
-
-       if (!string || !group)
-               return (char *) NULL;
-
-       if (*group == '^') {
-               group++;
-               for (; *string; string++) {
-                       for (ptr = group; *ptr; ptr++) {
-                               if (*ptr == *string)
-                                       break;
-                       }
-                       if (*ptr == '\0')
-                               return string;
-               }
-       }
-       else {
-               for (; *string; string++) {
-                       for (ptr = group; *ptr; ptr++) {
-                               if (*ptr == *string)
-                                       return string;
-                       }
-               }
-       }
-
-       return (char *) NULL;
-}
-
-
-/*
- * Get a token from the input file; return 0 if end of file is reached
- */
-static int dgap_gettok(char **in, struct cnode *p)
-{
-       char    *w;
-       struct toklist *t;
-
-       if (strstr(dgap_cword, "boar")) {
-               w = dgap_getword(in);
-               snprintf(dgap_cword, MAXCWORD, "%s", w);
-               for (t = dgap_tlist; t->token != 0; t++) {
-                       if ( !strcmp(w, t->string)) {
-                               return(t->token);
-                       }
-               }
-               dgap_err("board !!type not specified");
-               return(1);
-       }
-       else {
-               while ( (w = dgap_getword(in)) != NULL ) {
-                       snprintf(dgap_cword, MAXCWORD, "%s", w);
-                       for (t = dgap_tlist; t->token != 0; t++) {
-                               if ( !strcmp(w, t->string) )
-                                       return(t->token);
-                       }
-               }
-               return(0);
-       }
-}
-
-
-/*
- * get a word from the input stream, also keep track of current line number.
- * words are separated by whitespace.
- */
-static char *dgap_getword(char **in)
-{
-       char *ret_ptr = *in;
-
-        char *ptr = dgap_sindex(*in, " \t\n");
-
-       /* If no word found, return null */
-       if (!ptr)
-               return NULL;
-
-       /* Mark new location for our buffer */
-       *ptr = '\0';
-       *in = ptr + 1;
-
-       /* Eat any extra spaces/tabs/newlines that might be present */
-       while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
-               **in = '\0';
-               *in = *in + 1;
-       }
-
-       return ret_ptr;
-}
-
-
-/*
- * print an error message, giving the line number in the file where
- * the error occurred.
- */
-static void dgap_err(char *s)
-{
-       printk("DGAP: parse: %s\n", s);
-}
-
-
-/*
- * allocate a new configuration node of type t
- */
-static struct cnode *dgap_newnode(int t)
-{
-       struct cnode *n;
-
-       n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
-       if (n != NULL) {
-               memset((char *)n, 0, sizeof(struct cnode));
-               n->type = t;
-       }
-       return(n);
-}
-
-
-/*
- * dgap_checknode: see if all the necessary info has been supplied for a node
- * before creating the next node.
- */
-static int dgap_checknode(struct cnode *p)
-{
-       switch (p->type) {
-       case BNODE:
-               if (p->u.board.v_type == 0) {
-                       dgap_err("board type !not specified");
-                       return(1);
-               }
-
-               return(0);
-
-       case LNODE:
-               if (p->u.line.v_speed == 0) {
-                       dgap_err("line speed not specified");
-                       return(1);
-               }
-               return(0);
-
-       case CNODE:
-               if (p->u.conc.v_type == 0) {
-                       dgap_err("concentrator type not specified");
-                       return(1);
-               }
-               if (p->u.conc.v_speed == 0) {
-                       dgap_err("concentrator line speed not specified");
-                       return(1);
-               }
-               if (p->u.conc.v_nport == 0) {
-                       dgap_err("number of ports on concentrator not specified");
-                       return(1);
-               }
-               if (p->u.conc.v_id == 0) {
-                       dgap_err("concentrator id letter not specified");
-                       return(1);
-               }
-               return(0);
-
-       case MNODE:
-               if (p->u.module.v_type == 0) {
-                       dgap_err("EBI module type not specified");
-                       return(1);
-               }
-               if (p->u.module.v_nport == 0) {
-                       dgap_err("number of ports on EBI module not specified");
-                       return(1);
-               }
-               if (p->u.module.v_id == 0) {
-                       dgap_err("EBI module id letter not specified");
-                       return(1);
-               }
-               return(0);
-       }
-       return(0);
-}
-
-/*
- * save a string somewhere
- */
-static char    *dgap_savestring(char *s)
-{
-       char    *p;
-       if ( (p = kmalloc(strlen(s) + 1, GFP_ATOMIC) ) != NULL) {
-               strcpy(p, s);
-       }
-       return(p);
-}
-
-
-/*
- * Given a board pointer, returns whether we should use interrupts or not.
- */
-uint dgap_config_get_useintr(struct board_t *bd)
-{
-       struct cnode *p = NULL;
-
-       if (!bd)
-               return(0);
-
-       for (p = bd->bd_config; p; p = p->next) {
-               switch (p->type) {
-               case INTRNODE:
-                       /*
-                        * check for pcxr types.
-                        */
-                       return p->u.useintr;
-               default:
-                       break;
-               }
-       }
-
-       /* If not found, then don't turn on interrupts. */
-       return 0;
-}
-
-
-/*
- * Given a board pointer, returns whether we turn on altpin or not.
- */
-uint dgap_config_get_altpin(struct board_t *bd)
-{
-       struct cnode *p = NULL;
-
-       if (!bd)
-               return(0);
-
-       for (p = bd->bd_config; p; p = p->next) {
-               switch (p->type) {
-               case ANODE:
-                       /*
-                        * check for pcxr types.
-                        */
-                       return p->u.altpin;
-               default:
-                       break;
-               }
-       }
-
-       /* If not found, then don't turn on interrupts. */
-       return 0;
-}
-
-
-
-/*
- * Given a specific type of board, if found, detached link and
- * returns the first occurrence in the list.
- */
-struct cnode *dgap_find_config(int type, int bus, int slot)
-{
-       struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
-
-       p = &dgap_head;
-
-       while (p->next != NULL) {
-               prev = p;
-               p = p->next;
-
-               if (p->type == BNODE) {
-
-                       if (p->u.board.type == type) {
-
-                               if (p->u.board.v_pcibus && p->u.board.pcibus != bus) {
-                                       DPR(("Found matching board, but wrong bus position. System says bus %d, we want bus %ld\n",
-                                               bus, p->u.board.pcibus));
-                                       continue;
-                               }
-                               if (p->u.board.v_pcislot && p->u.board.pcislot != slot) {
-                                       DPR_INIT(("Found matching board, but wrong slot position. System says slot %d, we want slot %ld\n",
-                                               slot, p->u.board.pcislot));
-                                       continue;
-                               }
-
-                               DPR_INIT(("Matched type in config file\n"));
-
-                               found = p;
-                               /*
-                                * Keep walking thru the list till we find the next board.
-                                */
-                               while (p->next != NULL) {
-                                       prev2 = p;
-                                       p = p->next;
-                                       if (p->type == BNODE) {
-
-                                               /*
-                                                * Mark the end of our 1 board chain of configs.
-                                                */
-                                               prev2->next = NULL;
-
-                                               /*
-                                                * Link the "next" board to the previous board,
-                                                * effectively "unlinking" our board from the main config.
-                                                */
-                                               prev->next = p;
-
-                                               return found;
-                                       }
-                               }
-                               /*
-                                * It must be the last board in the list.
-                                */
-                               prev->next = NULL;
-                               return found;
-                       }
-               }
-       }
-       return NULL;
-}
-
-/*
- * Given a board pointer, walks the config link, counting up
- * all ports user specified should be on the board.
- * (This does NOT mean they are all actually present right now tho)
- */
-uint dgap_config_get_number_of_ports(struct board_t *bd)
-{
-       int count = 0;
-       struct cnode *p = NULL;
-
-       if (!bd)
-               return(0);
-
-       for (p = bd->bd_config; p; p = p->next) {
-
-               switch (p->type) {
-               case BNODE:
-                       /*
-                        * check for pcxr types.
-                        */
-                       if (p->u.board.type > EPCFE)
-                               count += p->u.board.nport;
-                       break;
-               case CNODE:
-                       count += p->u.conc.nport;
-                       break;
-               case MNODE:
-                       count += p->u.module.nport;
-                       break;
-               }
-       }
-       return (count);
-}
-
-char *dgap_create_config_string(struct board_t *bd, char *string)
-{
-       char *ptr = string;
-       struct cnode *p = NULL;
-       struct cnode *q = NULL;
-       int speed;
-
-       if (!bd) {
-               *ptr = 0xff;
-               return string;
-       }
-
-       for (p = bd->bd_config; p; p = p->next) {
-
-               switch (p->type) {
-               case LNODE:
-                       *ptr = '\0';
-                       ptr++;
-                       *ptr = p->u.line.speed;
-                       ptr++;
-                       break;
-               case CNODE:
-                       /*
-                        * Because the EPC/con concentrators can have EM modules
-                        * hanging off of them, we have to walk ahead in the list
-                        * and keep adding the number of ports on each EM to the config.
-                        * UGH!
-                        */
-                       speed = p->u.conc.speed;
-                       q = p->next;
-                       if ((q != NULL) && (q->type == MNODE) ) {
-                               *ptr = (p->u.conc.nport + 0x80);
-                               ptr++;
-                               p = q;
-                               while ((q->next != NULL) && (q->next->type) == MNODE) {
-                                       *ptr = (q->u.module.nport + 0x80);
-                                       ptr++;
-                                       p = q;
-                                       q = q->next;
-                               }
-                               *ptr = q->u.module.nport;
-                               ptr++;
-                       } else {
-                               *ptr = p->u.conc.nport;
-                               ptr++;
-                       }
-
-                       *ptr = speed;
-                       ptr++;
-                       break;
-               }
-       }
-
-       *ptr = 0xff;
-       return string;
-}
-
-
-
-char *dgap_get_config_letters(struct board_t *bd, char *string)
-{
-       int found = FALSE;
-       char *ptr = string;
-       struct cnode *cptr = NULL;
-       int len = 0;
-       int left = MAXTTYNAMELEN;
-
-       if (!bd) {
-               return "<NULL>";
-       }
-
-       for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
-               if ((cptr->type == BNODE) &&
-                    ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
-                    (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
-                    (cptr->u.board.type == PAPORT8))) {
-
-                       found = TRUE;
-               }
-
-               if (cptr->type == TNODE && found == TRUE) {
-                       char *ptr1;
-                       if (strstr(cptr->u.ttyname, "tty")) {
-                               ptr1 = cptr->u.ttyname;
-                               ptr1 += 3;
-                       }
-                       else {
-                               ptr1 = cptr->u.ttyname;
-                       }
-                       if (ptr1) {
-                               len = snprintf(ptr, left, "%s", ptr1);
-                               left -= len;
-                               ptr  += len;
-                               if (left <= 0)
-                                       break;
-                       }
-               }
-
-               if (cptr->type == CNODE) {
-                       if (cptr->u.conc.id) {
-                               len = snprintf(ptr, left, "%s", cptr->u.conc.id);
-                               left -= len;
-                               ptr  += len;
-                               if (left <= 0)
-                                       break;
-                       }
-                }
-
-               if (cptr->type == MNODE) {
-                       if (cptr->u.module.id) {
-                               len = snprintf(ptr, left, "%s", cptr->u.module.id);
-                               left -= len;
-                               ptr  += len;
-                               if (left <= 0)
-                                       break;
-                       }
-               }
-       }
-
-       return string;
-}
diff --git a/drivers/staging/dgap/dgap_parse.h b/drivers/staging/dgap/dgap_parse.h
deleted file mode 100644 (file)
index 8128c47..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef _DGAP_PARSE_H
-#define _DGAP_PARSE_H
-
-#include "dgap_driver.h"
-
-extern int dgap_parsefile(char **in, int Remove);
-extern struct cnode *dgap_find_config(int type, int bus, int slot);
-extern uint dgap_config_get_number_of_ports(struct board_t *bd);
-extern char *dgap_create_config_string(struct board_t *bd, char *string);
-extern char *dgap_get_config_letters(struct board_t *bd, char *string);
-extern uint dgap_config_get_useintr(struct board_t *bd);
-extern uint dgap_config_get_altpin(struct board_t *bd);
-
-#endif
diff --git a/drivers/staging/dgap/dgap_pci.h b/drivers/staging/dgap/dgap_pci.h
deleted file mode 100644 (file)
index 05ed374..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-/* $Id: dgap_pci.h,v 1.1 2009/10/23 14:01:57 markh Exp $ */
-
-#ifndef __DGAP_PCI_H
-#define __DGAP_PCI_H
-
-#define PCIMAX 32                      /* maximum number of PCI boards */
-
-#define DIGI_VID               0x114F
-
-#define PCI_DEVICE_EPC_DID     0x0002
-#define PCI_DEVICE_XEM_DID     0x0004
-#define PCI_DEVICE_XR_DID      0x0005
-#define PCI_DEVICE_CX_DID      0x0006
-#define PCI_DEVICE_XRJ_DID     0x0009  /* PLX-based Xr adapter */
-#define PCI_DEVICE_XR_IBM_DID  0x0011  /* IBM 8-port Async Adapter */
-#define PCI_DEVICE_XR_BULL_DID 0x0013  /* BULL 8-port Async Adapter */
-#define PCI_DEVICE_XR_SAIP_DID 0x001c  /* SAIP card - Xr adapter */
-#define PCI_DEVICE_XR_422_DID  0x0012  /* Xr-422 */
-#define PCI_DEVICE_920_2_DID   0x0034  /* XR-Plus 920 K, 2 port */
-#define PCI_DEVICE_920_4_DID   0x0026  /* XR-Plus 920 K, 4 port */
-#define PCI_DEVICE_920_8_DID   0x0027  /* XR-Plus 920 K, 8 port */
-#define PCI_DEVICE_EPCJ_DID    0x000a  /* PLX 9060 chip for PCI  */
-#define PCI_DEVICE_CX_IBM_DID  0x001b  /* IBM 128-port Async Adapter */
-#define PCI_DEVICE_920_8_HP_DID        0x0058  /* HP XR-Plus 920 K, 8 port */
-#define PCI_DEVICE_XEM_HP_DID  0x0059  /* HP Xem PCI */
-
-#define PCI_DEVICE_XEM_NAME    "AccelePort XEM"
-#define PCI_DEVICE_CX_NAME     "AccelePort CX"
-#define PCI_DEVICE_XR_NAME     "AccelePort Xr"
-#define PCI_DEVICE_XRJ_NAME    "AccelePort Xr (PLX)"
-#define PCI_DEVICE_XR_SAIP_NAME        "AccelePort Xr (SAIP)"
-#define PCI_DEVICE_920_2_NAME  "AccelePort Xr920 2 port"
-#define PCI_DEVICE_920_4_NAME  "AccelePort Xr920 4 port"
-#define PCI_DEVICE_920_8_NAME  "AccelePort Xr920 8 port"
-#define PCI_DEVICE_XR_422_NAME "AccelePort Xr 422"
-#define PCI_DEVICE_EPCJ_NAME   "AccelePort EPC (PLX)"
-#define PCI_DEVICE_XR_BULL_NAME        "AccelePort Xr (BULL)"
-#define PCI_DEVICE_XR_IBM_NAME "AccelePort Xr (IBM)"
-#define PCI_DEVICE_CX_IBM_NAME "AccelePort CX (IBM)"
-#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
-#define PCI_DEVICE_XEM_HP_NAME "AccelePort XEM (HP)"
-
-
-/*
- * On the PCI boards, there is no IO space allocated
- * The I/O registers will be in the first 3 bytes of the
- * upper 2MB of the 4MB memory space.  The board memory
- * will be mapped into the low 2MB of the 4MB memory space
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE          0x00020000
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE           0x00400000
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE           0x00200000
-
-/* Max PCI Window Size (2MB) */
-#define PCI_WIN_SIZE           0x00200000
-
-#define PCI_WIN_SHIFT          21 /* 21 bits max */
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET          0x00200000
-
-/* Size of IO (2MB) */
-#define PCI_IO_SIZE            0x00200000
-
-#endif
diff --git a/drivers/staging/dgap/dgap_sysfs.c b/drivers/staging/dgap/dgap_sysfs.c
deleted file mode 100644 (file)
index aa7e36f..0000000
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *
- *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *      This is shared code between Digi's CVS archive and the
- *      Linux Kernel sources.
- *      Changing the source just for reformatting needlessly breaks
- *      our CVS diff history.
- *
- *      Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *      Thank you.
- *
- *
- *
- * $Id: dgap_sysfs.c,v 1.1 2009/10/23 14:01:57 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/serial_reg.h>
-#include <linux/device.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-
-#include "dgap_driver.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-
-
-static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
-}
-static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
-
-
-static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
-}
-static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
-
-
-static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
-}
-static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
-
-
-static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
-}
-static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
-
-
-static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
-}
-static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
-
-
-static ssize_t dgap_driver_debug_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_debug);
-}
-
-static ssize_t dgap_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-       sscanf(buf, "0x%x\n", &dgap_debug);
-       return count;
-}
-static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgap_driver_debug_show, dgap_driver_debug_store);
-
-
-static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
-}
-
-static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-       sscanf(buf, "0x%x\n", &dgap_rawreadok);
-       return count;
-}
-static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
-
-
-static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
-}
-
-static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-       sscanf(buf, "%d\n", &dgap_poll_tick);
-       return count;
-}
-static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
-
-
-void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
-{
-       int rc = 0;
-       struct device_driver *driverfs = &dgap_driver->driver;
-
-       rc |= driver_create_file(driverfs, &driver_attr_version);
-       rc |= driver_create_file(driverfs, &driver_attr_boards);
-       rc |= driver_create_file(driverfs, &driver_attr_maxboards);
-       rc |= driver_create_file(driverfs, &driver_attr_debug);
-       rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
-       rc |= driver_create_file(driverfs, &driver_attr_pollrate);
-       rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
-       rc |= driver_create_file(driverfs, &driver_attr_state);
-       if (rc) {
-               printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
-       }
-}
-
-
-void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
-{
-       struct device_driver *driverfs = &dgap_driver->driver;
-       driver_remove_file(driverfs, &driver_attr_version);
-       driver_remove_file(driverfs, &driver_attr_boards);
-       driver_remove_file(driverfs, &driver_attr_maxboards);
-       driver_remove_file(driverfs, &driver_attr_debug);
-       driver_remove_file(driverfs, &driver_attr_rawreadok);
-       driver_remove_file(driverfs, &driver_attr_pollrate);
-       driver_remove_file(driverfs, &driver_attr_pollcounter);
-       driver_remove_file(driverfs, &driver_attr_state);
-}
-
-
-#define DGAP_VERIFY_BOARD(p, bd)                       \
-       if (!p)                                         \
-               return (0);                             \
-                                                       \
-       bd = dev_get_drvdata(p);                        \
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)       \
-               return (0);                             \
-       if (bd->state != BOARD_READY)                   \
-               return (0);                             \
-
-
-static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count,
-                       "%d %s\n", bd->channels[i]->ch_portnum,
-                       bd->channels[i]->ch_open_count ? "Open" : "Closed");
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
-
-
-static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count +=  snprintf(buf + count, PAGE_SIZE - count,
-                       "%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
-
-
-static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               if (bd->channels[i]->ch_open_count) {
-                       count += snprintf(buf + count, PAGE_SIZE - count,
-                               "%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
-                               (bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
-                               (bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
-                               (bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
-                               (bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
-                               (bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
-                               (bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
-               } else {
-                       count += snprintf(buf + count, PAGE_SIZE - count,
-                               "%d\n", bd->channels[i]->ch_portnum);
-               }
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
-
-
-static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
-
-
-static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
-
-
-static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
-
-
-static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
-
-
-static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
-
-
-static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
-
-
-static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       int count = 0;
-       int i = 0;
-
-       DGAP_VERIFY_BOARD(p, bd);
-
-       for (i = 0; i < bd->nasync; i++) {
-               count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
-                       bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
-       }
-       return count;
-}
-static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
-
-
-/* this function creates the sys files that will export each signal status
- * to sysfs each value will be put in a separate filename
- */
-void dgap_create_ports_sysfiles(struct board_t *bd)
-{
-       int rc = 0;
-
-       dev_set_drvdata(&bd->pdev->dev, bd);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
-       rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
-       if (rc) {
-               printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
-       }
-}
-
-
-/* removes all the sys files created for that port */
-void dgap_remove_ports_sysfiles(struct board_t *bd)
-{
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
-       device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
-}
-
-
-static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
-}
-static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
-
-
-static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
-}
-static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
-
-
-static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       if (ch->ch_open_count) {
-               return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
-                       (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
-                       (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
-                       (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
-                       (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
-                       (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
-                       (ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
-       }
-       return 0;
-}
-static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
-
-
-static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
-}
-static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
-
-
-static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
-}
-static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
-
-
-static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
-}
-static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
-
-
-static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
-}
-static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
-
-
-static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
-}
-static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
-
-
-static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
-}
-static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
-
-
-static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-       return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
-}
-static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
-
-
-static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       int     cn;
-       int     bn;
-       struct cnode *cptr = NULL;
-       int found = FALSE;
-       int ncount = 0;
-       int starto = 0;
-       int i = 0;
-
-       if (!d)
-               return (0);
-       un = dev_get_drvdata(d);
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-       if (bd->state != BOARD_READY)
-               return (0);
-
-        bn = bd->boardnum;
-       cn = ch->ch_portnum;
-
-       for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
-               if ((cptr->type == BNODE) &&
-                   ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
-                    (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
-                    (cptr->u.board.type == PAPORT8))) {
-
-                               found = TRUE;
-                               if (cptr->u.board.v_start)
-                                       starto = cptr->u.board.start;
-                               else
-                                       starto = 1;
-               }
-
-               if (cptr->type == TNODE && found == TRUE) {
-                       char *ptr1;
-                       if (strstr(cptr->u.ttyname, "tty")) {
-                               ptr1 = cptr->u.ttyname;
-                               ptr1 += 3;
-                       }
-                       else {
-                               ptr1 = cptr->u.ttyname;
-                       }
-
-                       for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
-                               if (cn == i) {
-                                       return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-                                               (un->un_type == DGAP_PRINT) ? "pr" : "tty",
-                                               ptr1, i + starto);
-                               }
-                       }
-               }
-
-               if (cptr->type == CNODE) {
-
-                       for (i = 0; i < cptr->u.conc.nport; i++) {
-                               if (cn == (i + ncount)) {
-
-                                       return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-                                               (un->un_type == DGAP_PRINT) ? "pr" : "tty",
-                                               cptr->u.conc.id,
-                                               i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
-                               }
-                       }
-
-                       ncount += cptr->u.conc.nport;
-               }
-
-               if (cptr->type == MNODE) {
-
-                       for (i = 0; i < cptr->u.module.nport; i++) {
-                               if (cn == (i + ncount)) {
-                                       return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-                                               (un->un_type == DGAP_PRINT) ? "pr" : "tty",
-                                               cptr->u.module.id,
-                                               i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
-                               }
-                       }
-
-                       ncount += cptr->u.module.nport;
-
-               }
-       }
-
-       return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
-               (un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
-
-}
-static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
-
-
-static struct attribute *dgap_sysfs_tty_entries[] = {
-       &dev_attr_state.attr,
-       &dev_attr_baud.attr,
-       &dev_attr_msignals.attr,
-       &dev_attr_iflag.attr,
-       &dev_attr_cflag.attr,
-       &dev_attr_oflag.attr,
-       &dev_attr_lflag.attr,
-       &dev_attr_digi_flag.attr,
-       &dev_attr_rxcount.attr,
-       &dev_attr_txcount.attr,
-       &dev_attr_custom_name.attr,
-       NULL
-};
-
-
-static struct attribute_group dgap_tty_attribute_group = {
-       .name = NULL,
-       .attrs = dgap_sysfs_tty_entries,
-};
-
-
-
-
-void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
-{
-       int ret;
-
-       ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
-       if (ret) {
-               printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
-               sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-               return;
-       }
-
-       dev_set_drvdata(c, un);
-
-}
-
-
-void dgap_remove_tty_sysfs(struct device *c)
-{
-       sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-}
diff --git a/drivers/staging/dgap/dgap_sysfs.h b/drivers/staging/dgap/dgap_sysfs.h
deleted file mode 100644 (file)
index 151f1b3..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_SYSFS_H
-#define __DGAP_SYSFS_H
-
-#include "dgap_driver.h"
-
-#include <linux/device.h>
-
-struct board_t;
-struct channel_t;
-struct un_t;
-struct pci_driver;
-struct class_device;
-
-extern void dgap_create_ports_sysfiles(struct board_t *bd);
-extern void dgap_remove_ports_sysfiles(struct board_t *bd);
-
-extern void dgap_create_driver_sysfiles(struct pci_driver *);
-extern void dgap_remove_driver_sysfiles(struct pci_driver *);
-
-extern int dgap_tty_class_init(void);
-extern int dgap_tty_class_destroy(void);
-
-extern void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
-extern void dgap_remove_tty_sysfs(struct device *c);
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_trace.c b/drivers/staging/dgap/dgap_trace.c
deleted file mode 100644 (file)
index a53db9e..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
- */
-
-/* $Id: dgap_trace.c,v 1.1 2009/10/23 14:01:57 markh Exp $ */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>       /* For jiffies, task states */
-#include <linux/interrupt.h>   /* For tasklet and interrupt structs/defines */
-#include <linux/vmalloc.h>
-
-#include "dgap_driver.h"
-#include "dgap_trace.h"
-
-#define TRC_TO_CONSOLE 1
-
-/* file level globals */
-static char *dgap_trcbuf;              /* the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static int dgap_trcbufi = 0;           /* index of the tilde at the end of */
-#endif
-
-extern int dgap_trcbuf_size;           /* size of the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static DEFINE_SPINLOCK(dgap_tracef_lock);
-#endif
-
-#if 0
-
-#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
-void dgap_tracef(const char *fmt, ...)
-{
-       return;
-}
-
-#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-void dgap_tracef(const char *fmt, ...)
-{
-       va_list          ap;
-       char             buf[TRC_MAXMSG+1];
-       size_t           lenbuf;
-       int              i;
-       static int       failed = FALSE;
-# if defined(TRC_TO_KMEM)
-       unsigned long    flags;
-#endif
-
-       if(failed)
-               return;
-# if defined(TRC_TO_KMEM)
-       DGAP_LOCK(dgap_tracef_lock, flags);
-#endif
-
-       /* Format buf using fmt and arguments contained in ap. */
-       va_start(ap, fmt);
-       i = vsprintf(buf, fmt,  ap);
-       va_end(ap);
-       lenbuf = strlen(buf);
-
-# if defined(TRC_TO_KMEM)
-       {
-               static int       initd=0;
-
-               /*
-                * Now, in addition to (or instead of) printing this stuff out
-                * (which is a buffered operation), also tuck it away into a
-                * corner of memory which can be examined post-crash in kdb.
-                */
-               if (!initd) {
-                       dgap_trcbuf = (char *) vmalloc(dgap_trcbuf_size);
-                       if(!dgap_trcbuf) {
-                               failed = TRUE;
-                               printk("dgap: tracing init failed!\n");
-                               return;
-                       }
-
-                       memset(dgap_trcbuf, '\0',  dgap_trcbuf_size);
-                       dgap_trcbufi = 0;
-                       initd++;
-
-                       printk("dgap: tracing enabled - " TRC_DTRC
-                               " 0x%lx 0x%x\n",
-                               (unsigned long)dgap_trcbuf,
-                               dgap_trcbuf_size);
-               }
-
-#  if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
-               /*
-                * This is the less CPU-intensive way to do things.  We simply
-                * wrap around before we fall off the end of the buffer.  A
-                * tilde (~) demarcates the current end of the trace.
-                *
-                * This method should be used if you are concerned about race
-                * conditions as it is less likely to affect the timing of
-                * things.
-                */
-
-               if (dgap_trcbufi + lenbuf >= dgap_trcbuf_size) {
-                       /* We are wrapping, so wipe out the last tilde. */
-                       dgap_trcbuf[dgap_trcbufi] = '\0';
-                       /* put the new string at the beginning of the buffer */
-                       dgap_trcbufi = 0;
-               }
-
-               strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
-               dgap_trcbufi += lenbuf;
-               dgap_trcbuf[dgap_trcbufi] = '~';
-
-#  elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
-               /*
-                * This is the more CPU-intensive way to do things.  If we
-                * venture into the last 1/8 of the buffer, we shift the
-                * last 7/8 of the buffer forward, wiping out the first 1/8.
-                * Advantage: No wrap-around, only truncation from the
-                * beginning.
-                *
-                * This method should not be used if you are concerned about
-                * timing changes affecting the behaviour of the driver (ie,
-                * race conditions).
-                */
-               strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
-               dgap_trcbufi += lenbuf;
-               dgap_trcbuf[dgap_trcbufi] = '~';
-               dgap_trcbuf[dgap_trcbufi+1] = '\0';
-
-               /* If we're near the end of the trace buffer... */
-               if (dgap_trcbufi > (dgap_trcbuf_size/8)*7) {
-                       /* Wipe out the first eighth to make some more room. */
-                       strcpy(dgap_trcbuf, &dgap_trcbuf[dgap_trcbuf_size/8]);
-                       dgap_trcbufi = strlen(dgap_trcbuf)-1;
-                       /* Plop overflow message at the top of the buffer. */
-                       bcopy(TRC_OVERFLOW, dgap_trcbuf, strlen(TRC_OVERFLOW));
-               }
-#  else
-#   error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
-#  endif
-       }
-       DGAP_UNLOCK(dgap_tracef_lock, flags);
-
-# endif /* defined(TRC_TO_KMEM) */
-}
-
-#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-#endif
-
-/*
- * dgap_tracer_free()
- *
- *
- */
-void dgap_tracer_free(void)
-{
-       if(dgap_trcbuf)
-               vfree(dgap_trcbuf);
-}
diff --git a/drivers/staging/dgap/dgap_trace.h b/drivers/staging/dgap/dgap_trace.h
deleted file mode 100644 (file)
index b21f461..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *****************************************************************************
- * Header file for dgap_trace.c
- *
- * $Id: dgap_trace.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- */
-
-#ifndef __DGAP_TRACE_H
-#define __DGAP_TRACE_H
-
-#include "dgap_driver.h"
-
-void dgap_tracef(const char *fmt, ...);
-void dgap_tracer_free(void);
-
-#endif
-
diff --git a/drivers/staging/dgap/dgap_tty.c b/drivers/staging/dgap/dgap_tty.c
deleted file mode 100644 (file)
index 565319f..0000000
+++ /dev/null
@@ -1,3556 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- */
-
-/************************************************************************
- *
- * This file implements the tty driver functionality for the
- * FEP5 based product lines.
- *
- ************************************************************************
- *
- * $Id: dgap_tty.c,v 1.3 2011/06/23 12:11:31 markh Exp $
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>       /* For jiffies, task states */
-#include <linux/interrupt.h>   /* For tasklet and interrupt structs/defines */
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/slab.h>
-#include <linux/delay.h>       /* For udelay */
-#include <asm/uaccess.h>       /* For copy_from_user/copy_to_user */
-#include <asm/io.h>            /* For read[bwl]/write[bwl] */
-#include <linux/pci.h>
-
-#include "dgap_driver.h"
-#include "dgap_tty.h"
-#include "dgap_types.h"
-#include "dgap_fep5.h"
-#include "dgap_parse.h"
-#include "dgap_conf.h"
-#include "dgap_sysfs.h"
-
-#define init_MUTEX(sem)         sema_init(sem, 1)
-#define DECLARE_MUTEX(name)     \
-        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
-
-/*
- * internal variables
- */
-static struct board_t  *dgap_BoardsByMajor[256];
-static uchar           *dgap_TmpWriteBuf = NULL;
-static DECLARE_MUTEX(dgap_TmpWriteSem);
-
-/*
- * Default transparent print information.
- */
-static struct digi_t dgap_digi_init = {
-       .digi_flags =   DIGI_COOK,      /* Flags                        */
-       .digi_maxcps =  100,            /* Max CPS                      */
-       .digi_maxchar = 50,             /* Max chars in print queue     */
-       .digi_bufsize = 100,            /* Printer buffer size          */
-       .digi_onlen =   4,              /* size of printer on string    */
-       .digi_offlen =  4,              /* size of printer off string   */
-       .digi_onstr =   "\033[5i",      /* ANSI printer on string ]     */
-       .digi_offstr =  "\033[4i",      /* ANSI printer off string ]    */
-       .digi_term =    "ansi"          /* default terminal type        */
-};
-
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.
- *
- * This defines a raw port at 9600 baud, 8 data bits, no parity,
- * 1 stop bit.
- */
-
-static struct ktermios DgapDefaultTermios =
-{
-       .c_iflag =      (DEFAULT_IFLAGS),       /* iflags */
-       .c_oflag =      (DEFAULT_OFLAGS),       /* oflags */
-       .c_cflag =      (DEFAULT_CFLAGS),       /* cflags */
-       .c_lflag =      (DEFAULT_LFLAGS),       /* lflags */
-       .c_cc =         INIT_C_CC,
-       .c_line =       0,
-};
-
-/* Our function prototypes */
-static int dgap_tty_open(struct tty_struct *tty, struct file *file);
-static void dgap_tty_close(struct tty_struct *tty, struct file *file);
-static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch);
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
-static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
-static int dgap_tty_write_room(struct tty_struct* tty);
-static int dgap_tty_chars_in_buffer(struct tty_struct* tty);
-static void dgap_tty_start(struct tty_struct *tty);
-static void dgap_tty_stop(struct tty_struct *tty);
-static void dgap_tty_throttle(struct tty_struct *tty);
-static void dgap_tty_unthrottle(struct tty_struct *tty);
-static void dgap_tty_flush_chars(struct tty_struct *tty);
-static void dgap_tty_flush_buffer(struct tty_struct *tty);
-static void dgap_tty_hangup(struct tty_struct *tty);
-static int dgap_wait_for_drain(struct tty_struct *tty);
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value);
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info);
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo);
-static int dgap_tty_tiocmget(struct tty_struct *tty);
-static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-static int dgap_tty_send_break(struct tty_struct *tty, int msec);
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout);
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c);
-static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
-
-static const struct tty_operations dgap_tty_ops = {
-       .open = dgap_tty_open,
-       .close = dgap_tty_close,
-       .write = dgap_tty_write,
-       .write_room = dgap_tty_write_room,
-       .flush_buffer = dgap_tty_flush_buffer,
-       .chars_in_buffer = dgap_tty_chars_in_buffer,
-       .flush_chars = dgap_tty_flush_chars,
-       .ioctl = dgap_tty_ioctl,
-       .set_termios = dgap_tty_set_termios,
-       .stop = dgap_tty_stop,
-       .start = dgap_tty_start,
-       .throttle = dgap_tty_throttle,
-       .unthrottle = dgap_tty_unthrottle,
-       .hangup = dgap_tty_hangup,
-       .put_char = dgap_tty_put_char,
-       .tiocmget = dgap_tty_tiocmget,
-       .tiocmset = dgap_tty_tiocmset,
-       .break_ctl = dgap_tty_send_break,
-       .wait_until_sent = dgap_tty_wait_until_sent,
-       .send_xchar = dgap_tty_send_xchar
-};
-
-
-
-
-
-/************************************************************************
- *
- * TTY Initialization/Cleanup Functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_preinit()
- *
- * Initialize any global tty related data before we download any boards.
- */
-int dgap_tty_preinit(void)
-{
-       unsigned long flags;
-
-       DGAP_LOCK(dgap_global_lock, flags);
-
-       /*
-        * Allocate a buffer for doing the copy from user space to
-        * kernel space in dgap_input().  We only use one buffer and
-        * control access to it with a semaphore.  If we are paging, we
-        * are already in trouble so one buffer won't hurt much anyway.
-        */
-       dgap_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_ATOMIC);
-
-       if (!dgap_TmpWriteBuf) {
-               DGAP_UNLOCK(dgap_global_lock, flags);
-               DPR_INIT(("unable to allocate tmp write buf"));
-               return (-ENOMEM);
-       }
-
-        DGAP_UNLOCK(dgap_global_lock, flags);
-        return(0);
-}
-
-
-/*
- * dgap_tty_register()
- *
- * Init the tty subsystem for this board.
- */
-int dgap_tty_register(struct board_t *brd)
-{
-       int rc = 0;
-
-       DPR_INIT(("tty_register start"));
-
-       brd->SerialDriver = alloc_tty_driver(MAXPORTS);
-
-       snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgap_%d_", brd->boardnum);
-       brd->SerialDriver->name = brd->SerialName;
-       brd->SerialDriver->name_base = 0;
-       brd->SerialDriver->major = 0;
-       brd->SerialDriver->minor_start = 0;
-       brd->SerialDriver->type = TTY_DRIVER_TYPE_SERIAL;
-       brd->SerialDriver->subtype = SERIAL_TYPE_NORMAL;
-       brd->SerialDriver->init_termios = DgapDefaultTermios;
-       brd->SerialDriver->driver_name = DRVSTR;
-       brd->SerialDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
-
-       /* The kernel wants space to store pointers to tty_structs */
-       brd->SerialDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
-       if (!brd->SerialDriver->ttys)
-               return(-ENOMEM);
-
-       /*
-        * Entry points for driver.  Called by the kernel from
-        * tty_io.c and n_tty.c.
-        */
-       tty_set_operations(brd->SerialDriver, &dgap_tty_ops);
-
-       /*
-        * If we're doing transparent print, we have to do all of the above
-        * again, separately so we don't get the LD confused about what major
-        * we are when we get into the dgap_tty_open() routine.
-        */
-       brd->PrintDriver = alloc_tty_driver(MAXPORTS);
-
-       snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgap_%d_", brd->boardnum);
-       brd->PrintDriver->name = brd->PrintName;
-       brd->PrintDriver->name_base = 0;
-       brd->PrintDriver->major = 0;
-       brd->PrintDriver->minor_start = 0;
-       brd->PrintDriver->type = TTY_DRIVER_TYPE_SERIAL;
-       brd->PrintDriver->subtype = SERIAL_TYPE_NORMAL;
-       brd->PrintDriver->init_termios = DgapDefaultTermios;
-       brd->PrintDriver->driver_name = DRVSTR;
-       brd->PrintDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
-
-       /* The kernel wants space to store pointers to tty_structs */
-       brd->PrintDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
-       if (!brd->PrintDriver->ttys)
-               return(-ENOMEM);
-
-       /*
-        * Entry points for driver.  Called by the kernel from
-        * tty_io.c and n_tty.c.
-        */
-       tty_set_operations(brd->PrintDriver, &dgap_tty_ops);
-
-       if (!brd->dgap_Major_Serial_Registered) {
-               /* Register tty devices */
-               rc = tty_register_driver(brd->SerialDriver);
-               if (rc < 0) {
-                       APR(("Can't register tty device (%d)\n", rc));
-                       return(rc);
-               }
-               brd->dgap_Major_Serial_Registered = TRUE;
-               dgap_BoardsByMajor[brd->SerialDriver->major] = brd;
-               brd->dgap_Serial_Major = brd->SerialDriver->major;
-       }
-
-       if (!brd->dgap_Major_TransparentPrint_Registered) {
-               /* Register Transparent Print devices */
-               rc = tty_register_driver(brd->PrintDriver);
-               if (rc < 0) {
-                       APR(("Can't register Transparent Print device (%d)\n", rc));
-                       return(rc);
-               }
-               brd->dgap_Major_TransparentPrint_Registered = TRUE;
-               dgap_BoardsByMajor[brd->PrintDriver->major] = brd;
-               brd->dgap_TransparentPrint_Major = brd->PrintDriver->major;
-       }
-
-       DPR_INIT(("DGAP REGISTER TTY: MAJORS: %d %d\n", brd->SerialDriver->major,
-               brd->PrintDriver->major));
-
-       return (rc);
-}
-
-
-/*
- * dgap_tty_init()
- *
- * Init the tty subsystem.  Called once per board after board has been
- * downloaded and init'ed.
- */
-int dgap_tty_init(struct board_t *brd)
-{
-       int i;
-       int tlw;
-       uint true_count = 0;
-       uchar *vaddr;
-       uchar modem = 0;
-       struct channel_t *ch;
-       struct bs_t *bs;
-       struct cm_t *cm;
-
-       if (!brd)
-               return (-ENXIO);
-
-       DPR_INIT(("dgap_tty_init start\n"));
-
-       /*
-        * Initialize board structure elements.
-        */
-
-       vaddr = brd->re_map_membase;
-       true_count = readw((vaddr + NCHAN));
-
-       brd->nasync = dgap_config_get_number_of_ports(brd);
-
-       if (!brd->nasync) {
-               brd->nasync = brd->maxports;
-       }
-
-       if (brd->nasync > brd->maxports) {
-               brd->nasync = brd->maxports;
-       }
-
-       if (true_count != brd->nasync) {
-               if ((brd->type == PPCM) && (true_count == 64)) {
-                       APR(("***WARNING**** %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
-                               brd->name, brd->nasync, true_count));
-               }
-               else if ((brd->type == PPCM) && (true_count == 0)) {
-                       APR(("***WARNING**** %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
-                               brd->name, brd->nasync, true_count));
-               }
-               else {
-                       APR(("***WARNING**** %s configured for %d ports, has %d ports.\n",
-                               brd->name, brd->nasync, true_count));
-               }
-
-               brd->nasync = true_count;
-
-               /* If no ports, don't bother going any further */
-               if (!brd->nasync) {
-                       brd->state = BOARD_FAILED;
-                       brd->dpastatus = BD_NOFEP;
-                       return(-ENXIO);
-               }
-       }
-
-       /*
-        * Allocate channel memory that might not have been allocated
-        * when the driver was first loaded.
-        */
-       for (i = 0; i < brd->nasync; i++) {
-               if (!brd->channels[i]) {
-                       brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_ATOMIC);
-                       if (!brd->channels[i]) {
-                               DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
-                                   __FILE__, __LINE__));
-                       }
-               }
-       }
-
-       ch = brd->channels[0];
-       vaddr = brd->re_map_membase;
-
-       bs = (struct bs_t *) ((ulong) vaddr + CHANBUF);
-       cm = (struct cm_t *) ((ulong) vaddr + CMDBUF);
-
-       brd->bd_bs = bs;
-
-       /* Set up channel variables */
-       for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
-
-               if (!brd->channels[i])
-                       continue;
-
-               DGAP_SPINLOCK_INIT(ch->ch_lock);
-
-               /* Store all our magic numbers */
-               ch->magic = DGAP_CHANNEL_MAGIC;
-               ch->ch_tun.magic = DGAP_UNIT_MAGIC;
-               ch->ch_tun.un_type = DGAP_SERIAL;
-               ch->ch_tun.un_ch = ch;
-               ch->ch_tun.un_dev = i;
-
-               ch->ch_pun.magic = DGAP_UNIT_MAGIC;
-               ch->ch_pun.un_type = DGAP_PRINT;
-               ch->ch_pun.un_ch = ch;
-               ch->ch_pun.un_dev = i;
-
-               ch->ch_vaddr = vaddr;
-               ch->ch_bs = bs;
-               ch->ch_cm = cm;
-               ch->ch_bd = brd;
-               ch->ch_portnum = i;
-               ch->ch_digi = dgap_digi_init;
-
-               /*
-                * Set up digi dsr and dcd bits based on altpin flag.
-                */
-               if (dgap_config_get_altpin(brd)) {
-                       ch->ch_dsr      = DM_CD;
-                       ch->ch_cd       = DM_DSR;
-                       ch->ch_digi.digi_flags |= DIGI_ALTPIN;
-               }
-               else {
-                       ch->ch_cd       = DM_CD;
-                       ch->ch_dsr      = DM_DSR;
-               }
-
-               ch->ch_taddr = vaddr + ((ch->ch_bs->tx_seg) << 4);
-               ch->ch_raddr = vaddr + ((ch->ch_bs->rx_seg) << 4);
-               ch->ch_tx_win = 0;
-               ch->ch_rx_win = 0;
-               ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
-               ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
-               ch->ch_tstart = 0;
-               ch->ch_rstart = 0;
-
-               /* .25 second delay */
-               ch->ch_close_delay = 250;
-
-               /*
-                * Set queue water marks, interrupt mask,
-                * and general tty parameters.
-                */
-               ch->ch_tlw = tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : ch->ch_tsize / 2;
-
-               dgap_cmdw(ch, STLOW, tlw, 0);
-
-               dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
-
-               dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
-
-               ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
-
-               init_waitqueue_head(&ch->ch_flags_wait);
-               init_waitqueue_head(&ch->ch_tun.un_flags_wait);
-               init_waitqueue_head(&ch->ch_pun.un_flags_wait);
-               init_waitqueue_head(&ch->ch_sniff_wait);
-
-               /* Turn on all modem interrupts for now */
-               modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
-               writeb(modem, &(ch->ch_bs->m_int));
-
-               /*
-                * Set edelay to 0 if interrupts are turned on,
-                * otherwise set edelay to the usual 100.
-                */
-               if (brd->intr_used)
-                       writew(0, &(ch->ch_bs->edelay));
-               else
-                       writew(100, &(ch->ch_bs->edelay));
-
-               writeb(1, &(ch->ch_bs->idata));
-       }
-
-
-       DPR_INIT(("dgap_tty_init finish\n"));
-
-       return (0);
-}
-
-
-/*
- * dgap_tty_post_uninit()
- *
- * UnInitialize any global tty related data.
- */
-void dgap_tty_post_uninit(void)
-{
-       kfree(dgap_TmpWriteBuf);
-       dgap_TmpWriteBuf = NULL;
-}
-
-
-/*
- * dgap_tty_uninit()
- *
- * Uninitialize the TTY portion of this driver.  Free all memory and
- * resources.
- */
-void dgap_tty_uninit(struct board_t *brd)
-{
-       int i = 0;
-
-       if (brd->dgap_Major_Serial_Registered) {
-               dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
-               brd->dgap_Serial_Major = 0;
-               for (i = 0; i < brd->nasync; i++) {
-                       dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
-                       tty_unregister_device(brd->SerialDriver, i);
-               }
-               tty_unregister_driver(brd->SerialDriver);
-               kfree(brd->SerialDriver->ttys);
-               brd->SerialDriver->ttys = NULL;
-               put_tty_driver(brd->SerialDriver);
-               brd->dgap_Major_Serial_Registered = FALSE;
-       }
-
-       if (brd->dgap_Major_TransparentPrint_Registered) {
-               dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
-               brd->dgap_TransparentPrint_Major = 0;
-               for (i = 0; i < brd->nasync; i++) {
-                       dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
-                       tty_unregister_device(brd->PrintDriver, i);
-               }
-               tty_unregister_driver(brd->PrintDriver);
-               kfree(brd->PrintDriver->ttys);
-               brd->PrintDriver->ttys = NULL;
-               put_tty_driver(brd->PrintDriver);
-               brd->dgap_Major_TransparentPrint_Registered = FALSE;
-       }
-}
-
-
-#define TMPBUFLEN (1024)
-
-/*
- * dgap_sniff - Dump data out to the "sniff" buffer if the
- * proc sniff file is opened...
- */
-static void dgap_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len)
-{
-       struct timeval tv;
-       int n;
-       int r;
-       int nbuf;
-       int i;
-       int tmpbuflen;
-       char tmpbuf[TMPBUFLEN];
-       char *p = tmpbuf;
-       int too_much_data;
-
-       /* Leave if sniff not open */
-       if (!(ch->ch_sniff_flags & SNIFF_OPEN))
-               return;
-
-       do_gettimeofday(&tv);
-
-       /* Create our header for data dump */
-       p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
-       tmpbuflen = p - tmpbuf;
-
-       do {
-               too_much_data = 0;
-
-               for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
-                       p += sprintf(p, "%02x ", *buf);
-                       buf++;
-                       tmpbuflen = p - tmpbuf;
-               }
-
-               if (tmpbuflen < (TMPBUFLEN - 4)) {
-                       if (i > 0)
-                               p += sprintf(p - 1, "%s\n", ">");
-                       else
-                               p += sprintf(p, "%s\n", ">");
-               } else {
-                       too_much_data = 1;
-                       len -= i;
-               }
-
-               nbuf = strlen(tmpbuf);
-               p = tmpbuf;
-
-               /*
-                *  Loop while data remains.
-                */
-               while (nbuf > 0 && ch->ch_sniff_buf) {
-                       /*
-                        *  Determine the amount of available space left in the
-                        *  buffer.  If there's none, wait until some appears.
-                        */
-                       n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
-
-                       /*
-                        * If there is no space left to write to in our sniff buffer,
-                        * we have no choice but to drop the data.
-                        * We *cannot* sleep here waiting for space, because this
-                        * function was probably called by the interrupt/timer routines!
-                        */
-                       if (n == 0) {
-                               return;
-                       }
-
-                       /*
-                        * Copy as much data as will fit.
-                        */
-
-                       if (n > nbuf)
-                               n = nbuf;
-
-                       r = SNIFF_MAX - ch->ch_sniff_in;
-
-                       if (r <= n) {
-                               memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
-
-                               n -= r;
-                               ch->ch_sniff_in = 0;
-                               p += r;
-                               nbuf -= r;
-                       }
-
-                       memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
-
-                       ch->ch_sniff_in += n;
-                       p += n;
-                       nbuf -= n;
-
-                       /*
-                        *  Wakeup any thread waiting for data
-                        */
-                       if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
-                               ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
-                               wake_up_interruptible(&ch->ch_sniff_wait);
-                       }
-               }
-
-               /*
-                * If the user sent us too much data to push into our tmpbuf,
-                * we need to keep looping around on all the data.
-                */
-               if (too_much_data) {
-                       p = tmpbuf;
-                       tmpbuflen = 0;
-               }
-
-       } while (too_much_data);
-}
-
-
-/*=======================================================================
- *
- *      dgap_input - Process received data.
- *
- *              ch      - Pointer to channel structure.
- *
- *=======================================================================*/
-
-void dgap_input(struct channel_t *ch)
-{
-       struct board_t *bd;
-       struct bs_t     *bs;
-       struct tty_struct *tp;
-       struct tty_ldisc *ld;
-       uint    rmask;
-       uint    head;
-       uint    tail;
-       int     data_len;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-       int flip_len;
-       int len = 0;
-       int n = 0;
-       uchar *buf;
-       uchar tmpchar;
-       int s = 0;
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       tp = ch->ch_tun.un_tty;
-
-       bs  = ch->ch_bs;
-       if (!bs) {
-               return;
-       }
-
-       bd = ch->ch_bd;
-       if(!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_READ(("dgap_input start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       /*
-        *      Figure the number of characters in the buffer.
-        *      Exit immediately if none.
-        */
-
-       rmask = ch->ch_rsize - 1;
-
-       head = readw(&(bs->rx_head));
-       head &= rmask;
-       tail = readw(&(bs->rx_tail));
-       tail &= rmask;
-
-       data_len = (head - tail) & rmask;
-
-       if (data_len == 0) {
-               writeb(1, &(bs->idata));
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               DPR_READ(("No data on port %d\n", ch->ch_portnum));
-               return;
-       }
-
-       /*
-        * If the device is not open, or CREAD is off, flush
-        * input data and return immediately.
-        */
-       if ((bd->state != BOARD_READY) || !tp  || (tp->magic != TTY_MAGIC) ||
-            !(ch->ch_tun.un_flags & UN_ISOPEN) || !(tp->termios.c_cflag & CREAD) ||
-           (ch->ch_tun.un_flags & UN_CLOSING)) {
-
-               DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum));
-               DPR_READ(("input. tp: %p tp->magic: %x MAGIC:%x ch flags: %x\n",
-                       tp, tp ? tp->magic : 0, TTY_MAGIC, ch->ch_tun.un_flags));
-               writew(head, &(bs->rx_tail));
-               writeb(1, &(bs->idata));
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return;
-       }
-
-       /*
-        * If we are throttled, simply don't read any data.
-        */
-       if (ch->ch_flags & CH_RXBLOCK) {
-               writeb(1, &(bs->idata));
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               DPR_READ(("Port %d throttled, not reading any data. head: %x tail: %x\n",
-                       ch->ch_portnum, head, tail));
-               return;
-       }
-
-       /*
-        *      Ignore oruns.
-        */
-       tmpchar = readb(&(bs->orun));
-       if (tmpchar) {
-               ch->ch_err_overrun++;
-               writeb(0, &(bs->orun));
-       }
-
-       DPR_READ(("dgap_input start 2\n"));
-
-       /* Decide how much data we can send into the tty layer */
-       flip_len = TTY_FLIPBUF_SIZE;
-
-       /* Chop down the length, if needed */
-       len = min(data_len, flip_len);
-       len = min(len, (N_TTY_BUF_SIZE - 1));
-
-       ld = tty_ldisc_ref(tp);
-
-#ifdef TTY_DONT_FLIP
-       /*
-        * If the DONT_FLIP flag is on, don't flush our buffer, and act
-        * like the ld doesn't have any space to put the data right now.
-        */
-       if (test_bit(TTY_DONT_FLIP, &tp->flags))
-               len = 0;
-#endif
-
-       /*
-        * If we were unable to get a reference to the ld,
-        * don't flush our buffer, and act like the ld doesn't
-        * have any space to put the data right now.
-        */
-       if (!ld) {
-               len = 0;
-       } else {
-               /*
-                * If ld doesn't have a pointer to a receive_buf function,
-                * flush the data, then act like the ld doesn't have any
-                * space to put the data right now.
-                */
-               if (!ld->ops->receive_buf) {
-                       writew(head, &(bs->rx_tail));
-                       len = 0;
-               }
-       }
-
-       if (len <= 0) {
-               writeb(1, &(bs->idata));
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               DPR_READ(("dgap_input 1 - finish\n"));
-               if (ld)
-                       tty_ldisc_deref(ld);
-               return;
-       }
-
-       buf = ch->ch_bd->flipbuf;
-       n = len;
-
-       /*
-        * n now contains the most amount of data we can copy,
-        * bounded either by our buffer size or the amount
-        * of data the card actually has pending...
-        */
-       while (n) {
-
-               s = ((head >= tail) ? head : ch->ch_rsize) - tail;
-               s = min(s, n);
-
-               if (s <= 0)
-                       break;
-
-               memcpy_fromio(buf, (char *) ch->ch_raddr + tail, s);
-               dgap_sniff_nowait_nolock(ch, "USER READ", buf, s);
-
-               tail += s;
-               buf += s;
-
-               n -= s;
-               /* Flip queue if needed */
-               tail &= rmask;
-       }
-
-       writew(tail, &(bs->rx_tail));
-       writeb(1, &(bs->idata));
-       ch->ch_rxcount += len;
-
-       /*
-        * If we are completely raw, we don't need to go through a lot
-        * of the tty layers that exist.
-        * In this case, we take the shortest and fastest route we
-        * can to relay the data to the user.
-        *
-        * On the other hand, if we are not raw, we need to go through
-        * the tty layer, which has its API more well defined.
-        */
-       if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
-               dgap_parity_scan(ch, ch->ch_bd->flipbuf, ch->ch_bd->flipflagbuf, &len);
-
-               len = tty_buffer_request_room(tp->port, len);
-               tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
-                       ch->ch_bd->flipflagbuf, len);
-       }
-       else {
-               len = tty_buffer_request_room(tp->port, len);
-               tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
-       }
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       /* Tell the tty layer its okay to "eat" the data now */
-       tty_flip_buffer_push(tp->port);
-
-       if (ld)
-               tty_ldisc_deref(ld);
-
-       DPR_READ(("dgap_input - finish\n"));
-}
-
-
-/************************************************************************
- * Determines when CARRIER changes state and takes appropriate
- * action.
- ************************************************************************/
-void dgap_carrier(struct channel_t *ch)
-{
-       struct board_t *bd;
-
-        int virt_carrier = 0;
-        int phys_carrier = 0;
-
-       DPR_CARR(("dgap_carrier called...\n"));
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       bd = ch->ch_bd;
-
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       /* Make sure altpin is always set correctly */
-       if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
-               ch->ch_dsr      = DM_CD;
-               ch->ch_cd       = DM_DSR;
-       }
-       else {
-               ch->ch_dsr      = DM_DSR;
-               ch->ch_cd       = DM_CD;
-       }
-
-       if (ch->ch_mistat & D_CD(ch)) {
-               DPR_CARR(("mistat: %x  D_CD: %x\n", ch->ch_mistat, D_CD(ch)));
-               phys_carrier = 1;
-       }
-
-       if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) {
-               virt_carrier = 1;
-       }
-
-       if (ch->ch_c_cflag & CLOCAL) {
-               virt_carrier = 1;
-       }
-
-
-       DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier));
-
-       /*
-        * Test for a VIRTUAL carrier transition to HIGH.
-        */
-       if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
-
-               /*
-                * When carrier rises, wake any threads waiting
-                * for carrier in the open routine.
-                */
-
-               DPR_CARR(("carrier: virt DCD rose\n"));
-
-               if (waitqueue_active(&(ch->ch_flags_wait)))
-                       wake_up_interruptible(&ch->ch_flags_wait);
-       }
-
-       /*
-        * Test for a PHYSICAL carrier transition to HIGH.
-        */
-       if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
-
-               /*
-                * When carrier rises, wake any threads waiting
-                * for carrier in the open routine.
-                */
-
-               DPR_CARR(("carrier: physical DCD rose\n"));
-
-               if (waitqueue_active(&(ch->ch_flags_wait)))
-                       wake_up_interruptible(&ch->ch_flags_wait);
-       }
-
-       /*
-        *  Test for a PHYSICAL transition to low, so long as we aren't
-        *  currently ignoring physical transitions (which is what "virtual
-        *  carrier" indicates).
-        *
-        *  The transition of the virtual carrier to low really doesn't
-        *  matter... it really only means "ignore carrier state", not
-        *  "make pretend that carrier is there".
-        */
-       if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) &&
-           (phys_carrier == 0))
-       {
-
-               /*
-                *   When carrier drops:
-                *
-                *   Drop carrier on all open units.
-                *
-                *   Flush queues, waking up any task waiting in the
-                *   line discipline.
-                *
-                *   Send a hangup to the control terminal.
-                *
-                *   Enable all select calls.
-                */
-               if (waitqueue_active(&(ch->ch_flags_wait)))
-                       wake_up_interruptible(&ch->ch_flags_wait);
-
-               if (ch->ch_tun.un_open_count > 0) {
-                       DPR_CARR(("Sending tty hangup\n"));
-                       tty_hangup(ch->ch_tun.un_tty);
-               }
-
-               if (ch->ch_pun.un_open_count > 0) {
-                       DPR_CARR(("Sending pr hangup\n"));
-                       tty_hangup(ch->ch_pun.un_tty);
-               }
-       }
-
-       /*
-        *  Make sure that our cached values reflect the current reality.
-        */
-       if (virt_carrier == 1)
-               ch->ch_flags |= CH_FCAR;
-       else
-               ch->ch_flags &= ~CH_FCAR;
-
-       if (phys_carrier == 1)
-               ch->ch_flags |= CH_CD;
-       else
-               ch->ch_flags &= ~CH_CD;
-}
-
-
-/************************************************************************
- *
- * TTY Entry points and helper functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_open()
- *
- */
-static int dgap_tty_open(struct tty_struct *tty, struct file *file)
-{
-       struct board_t  *brd;
-       struct channel_t *ch;
-       struct un_t     *un;
-       struct bs_t     *bs;
-       uint            major = 0;
-       uint            minor = 0;
-       int             rc = 0;
-       ulong           lock_flags;
-       ulong           lock_flags2;
-       u16             head;
-
-       rc = 0;
-
-       major = MAJOR(tty_devnum(tty));
-       minor = MINOR(tty_devnum(tty));
-
-       if (major > 255) {
-               return -ENXIO;
-       }
-
-       /* Get board pointer from our array of majors we have allocated */
-       brd = dgap_BoardsByMajor[major];
-       if (!brd) {
-               return -ENXIO;
-       }
-
-       /*
-        * If board is not yet up to a state of READY, go to
-        * sleep waiting for it to happen or they cancel the open.
-        */
-       rc = wait_event_interruptible(brd->state_wait,
-               (brd->state & BOARD_READY));
-
-       if (rc) {
-               return rc;
-       }
-
-       DGAP_LOCK(brd->bd_lock, lock_flags);
-
-       /* The wait above should guarantee this cannot happen */
-       if (brd->state != BOARD_READY) {
-               DGAP_UNLOCK(brd->bd_lock, lock_flags);
-               return -ENXIO;
-       }
-
-       /* If opened device is greater than our number of ports, bail. */
-       if (MINOR(tty_devnum(tty)) > brd->nasync) {
-               DGAP_UNLOCK(brd->bd_lock, lock_flags);
-               return -ENXIO;
-       }
-
-       ch = brd->channels[minor];
-       if (!ch) {
-               DGAP_UNLOCK(brd->bd_lock, lock_flags);
-               return -ENXIO;
-       }
-
-       /* Grab channel lock */
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       /* Figure out our type */
-       if (major == brd->dgap_Serial_Major) {
-               un = &brd->channels[minor]->ch_tun;
-               un->un_type = DGAP_SERIAL;
-       }
-       else if (major == brd->dgap_TransparentPrint_Major) {
-               un = &brd->channels[minor]->ch_pun;
-               un->un_type = DGAP_PRINT;
-       }
-       else {
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(brd->bd_lock, lock_flags);
-               DPR_OPEN(("%d Unknown TYPE!\n", __LINE__));
-               return -ENXIO;
-       }
-
-       /* Store our unit into driver_data, so we always have it available. */
-       tty->driver_data = un;
-
-       DPR_OPEN(("Open called. MAJOR: %d MINOR:%d unit: %p NAME: %s\n",
-               MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), un, brd->name));
-
-       /*
-        * Error if channel info pointer is NULL.
-        */
-       bs = ch->ch_bs;
-       if (!bs) {
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(brd->bd_lock, lock_flags);
-               DPR_OPEN(("%d BS is 0!\n", __LINE__));
-               return -ENXIO;
-        }
-
-       DPR_OPEN(("%d: tflag=%x  pflag=%x\n", __LINE__, ch->ch_tun.un_flags, ch->ch_pun.un_flags));
-
-       /*
-        * Initialize tty's
-        */
-       if (!(un->un_flags & UN_ISOPEN)) {
-               /* Store important variables. */
-               un->un_tty     = tty;
-
-               /* Maybe do something here to the TTY struct as well? */
-       }
-
-       /*
-        * Initialize if neither terminal or printer is open.
-        */
-       if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
-
-               DPR_OPEN(("dgap_open: initializing channel in open...\n"));
-
-               ch->ch_mforce = 0;
-               ch->ch_mval = 0;
-
-               /*
-                * Flush input queue.
-                */
-               head = readw(&(bs->rx_head));
-               writew(head, &(bs->rx_tail));
-
-               ch->ch_flags = 0;
-               ch->pscan_state = 0;
-               ch->pscan_savechar = 0;
-
-               ch->ch_c_cflag   = tty->termios.c_cflag;
-               ch->ch_c_iflag   = tty->termios.c_iflag;
-               ch->ch_c_oflag   = tty->termios.c_oflag;
-               ch->ch_c_lflag   = tty->termios.c_lflag;
-               ch->ch_startc = tty->termios.c_cc[VSTART];
-               ch->ch_stopc  = tty->termios.c_cc[VSTOP];
-
-               /* TODO: flush our TTY struct here? */
-       }
-
-       dgap_carrier(ch);
-       /*
-        * Run param in case we changed anything
-        */
-       dgap_param(tty);
-
-       /*
-        * follow protocol for opening port
-        */
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(brd->bd_lock, lock_flags);
-
-       rc = dgap_block_til_ready(tty, file, ch);
-
-       if (!un->un_tty) {
-               return -ENODEV;
-       }
-
-       if (rc) {
-               DPR_OPEN(("dgap_tty_open returning after dgap_block_til_ready "
-                       "with %d\n", rc));
-       }
-
-       /* No going back now, increment our unit and channel counters */
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-       ch->ch_open_count++;
-       un->un_open_count++;
-       un->un_flags |= (UN_ISOPEN);
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       DPR_OPEN(("dgap_tty_open finished\n"));
-       return (rc);
-}
-
-
-/*
- * dgap_block_til_ready()
- *
- * Wait for DCD, if needed.
- */
-static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
-{
-       int retval = 0;
-       struct un_t *un = NULL;
-       ulong   lock_flags;
-       uint    old_flags = 0;
-       int sleep_on_un_flags = 0;
-
-       if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-               return (-ENXIO);
-       }
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC) {
-               return (-ENXIO);
-       }
-
-       DPR_OPEN(("dgap_block_til_ready - before block.\n"));
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-
-       ch->ch_wopen++;
-
-       /* Loop forever */
-       while (1) {
-
-               sleep_on_un_flags = 0;
-
-               /*
-                * If board has failed somehow during our sleep, bail with error.
-                */
-               if (ch->ch_bd->state == BOARD_FAILED) {
-                       retval = -ENXIO;
-                       break;
-               }
-
-               /* If tty was hung up, break out of loop and set error. */
-               if (tty_hung_up_p(file)) {
-                       retval = -EAGAIN;
-                       break;
-               }
-
-               /*
-                * If either unit is in the middle of the fragile part of close,
-                * we just cannot touch the channel safely.
-                * Go back to sleep, knowing that when the channel can be
-                * touched safely, the close routine will signal the
-                * ch_wait_flags to wake us back up.
-                */
-               if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
-
-                       /*
-                        * Our conditions to leave cleanly and happily:
-                        * 1) NONBLOCKING on the tty is set.
-                        * 2) CLOCAL is set.
-                        * 3) DCD (fake or real) is active.
-                        */
-
-                       if (file->f_flags & O_NONBLOCK) {
-                               break;
-                       }
-
-                       if (tty->flags & (1 << TTY_IO_ERROR)) {
-                               break;
-                       }
-
-                       if (ch->ch_flags & CH_CD) {
-                               DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
-                               break;
-                       }
-
-                       if (ch->ch_flags & CH_FCAR) {
-                               DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
-                               break;
-                       }
-               }
-               else {
-                       sleep_on_un_flags = 1;
-               }
-
-               /*
-                * If there is a signal pending, the user probably
-                * interrupted (ctrl-c) us.
-                * Leave loop with error set.
-                */
-               if (signal_pending(current)) {
-                       DPR_OPEN(("%d: signal pending...\n", __LINE__));
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-
-               DPR_OPEN(("dgap_block_til_ready - blocking.\n"));
-
-               /*
-                * Store the flags before we let go of channel lock
-                */
-               if (sleep_on_un_flags)
-                       old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
-               else
-                       old_flags = ch->ch_flags;
-
-               /*
-                * Let go of channel lock before calling schedule.
-                * Our poller will get any FEP events and wake us up when DCD
-                * eventually goes active.
-                */
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-               DPR_OPEN(("Going to sleep on %s flags...\n",
-                       (sleep_on_un_flags ? "un" : "ch")));
-
-               /*
-                * Wait for something in the flags to change from the current value.
-                */
-               if (sleep_on_un_flags) {
-                       retval = wait_event_interruptible(un->un_flags_wait,
-                               (old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
-               }
-               else {
-                       retval = wait_event_interruptible(ch->ch_flags_wait,
-                               (old_flags != ch->ch_flags));
-               }
-
-               DPR_OPEN(("After sleep... retval: %x\n", retval));
-
-               /*
-                * We got woken up for some reason.
-                * Before looping around, grab our channel lock.
-                */
-               DGAP_LOCK(ch->ch_lock, lock_flags);
-       }
-
-       ch->ch_wopen--;
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       DPR_OPEN(("dgap_block_til_ready - after blocking.\n"));
-
-       if (retval) {
-               DPR_OPEN(("dgap_block_til_ready - done. error. retval: %x\n", retval));
-               return(retval);
-       }
-
-       DPR_OPEN(("dgap_block_til_ready - done no error. jiffies: %lu\n", jiffies));
-
-       return(0);
-}
-
-
-/*
- * dgap_tty_hangup()
- *
- * Hangup the port.  Like a close, but don't wait for output to drain.
- */
-static void dgap_tty_hangup(struct tty_struct *tty)
-{
-       struct board_t  *bd;
-       struct channel_t *ch;
-       struct un_t     *un;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_CLOSE(("dgap_hangup called. ch->ch_open_count: %d un->un_open_count: %d\n",
-               ch->ch_open_count, un->un_open_count));
-
-       /* flush the transmit queues */
-       dgap_tty_flush_buffer(tty);
-
-       DPR_CLOSE(("dgap_hangup finished. ch->ch_open_count: %d un->un_open_count: %d\n",
-               ch->ch_open_count, un->un_open_count));
-}
-
-
-
-/*
- * dgap_tty_close()
- *
- */
-static void dgap_tty_close(struct tty_struct *tty, struct file *file)
-{
-       struct ktermios *ts;
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong lock_flags;
-       int rc = 0;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       ts = &tty->termios;
-
-       DPR_CLOSE(("Close called\n"));
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-
-       /*
-        * Determine if this is the last close or not - and if we agree about
-        * which type of close it is with the Line Discipline
-        */
-       if ((tty->count == 1) && (un->un_open_count != 1)) {
-               /*
-                * Uh, oh.  tty->count is 1, which means that the tty
-                * structure will be freed.  un_open_count should always
-                * be one in these conditions.  If it's greater than
-                * one, we've got real problems, since it means the
-                * serial port won't be shutdown.
-                */
-               APR(("tty->count is 1, un open count is %d\n", un->un_open_count));
-               un->un_open_count = 1;
-       }
-
-       if (--un->un_open_count < 0) {
-               APR(("bad serial port open count of %d\n", un->un_open_count));
-               un->un_open_count = 0;
-       }
-
-       ch->ch_open_count--;
-
-       if (ch->ch_open_count && un->un_open_count) {
-               DPR_CLOSE(("dgap_tty_close: not last close ch: %d un:%d\n",
-                       ch->ch_open_count, un->un_open_count));
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-                return;
-        }
-
-       /* OK, its the last close on the unit */
-       DPR_CLOSE(("dgap_tty_close - last close on unit procedures\n"));
-
-       un->un_flags |= UN_CLOSING;
-
-       tty->closing = 1;
-
-       /*
-        * Only officially close channel if count is 0 and
-         * DIGI_PRINTER bit is not set.
-        */
-       if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
-
-               ch->ch_flags &= ~(CH_RXBLOCK);
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-               /* wait for output to drain */
-               /* This will also return if we take an interrupt */
-
-               DPR_CLOSE(("Calling wait_for_drain\n"));
-               rc = dgap_wait_for_drain(tty);
-               DPR_CLOSE(("After calling wait_for_drain\n"));
-
-               if (rc) {
-                       DPR_BASIC(("dgap_tty_close - bad return: %d ", rc));
-               }
-
-               dgap_tty_flush_buffer(tty);
-               tty_ldisc_flush(tty);
-
-               DGAP_LOCK(ch->ch_lock, lock_flags);
-
-               tty->closing = 0;
-
-               /*
-                * If we have HUPCL set, lower DTR and RTS
-                */
-               if (ch->ch_c_cflag & HUPCL ) {
-                       DPR_CLOSE(("Close. HUPCL set, dropping DTR/RTS\n"));
-                       ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
-                       dgap_cmdb( ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0 );
-
-                       /*
-                        * Go to sleep to ensure RTS/DTR
-                        * have been dropped for modems to see it.
-                        */
-                       if (ch->ch_close_delay) {
-                               DPR_CLOSE(("Close. Sleeping for RTS/DTR drop\n"));
-
-                               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-                               dgap_ms_sleep(ch->ch_close_delay);
-                               DGAP_LOCK(ch->ch_lock, lock_flags);
-
-                               DPR_CLOSE(("Close. After sleeping for RTS/DTR drop\n"));
-                       }
-               }
-
-               ch->pscan_state = 0;
-               ch->pscan_savechar = 0;
-               ch->ch_baud_info = 0;
-
-       }
-
-       /*
-        * turn off print device when closing print device.
-        */
-       if ((un->un_type == DGAP_PRINT)  && (ch->ch_flags & CH_PRON) ) {
-               dgap_wmove(ch, ch->ch_digi.digi_offstr,
-                       (int) ch->ch_digi.digi_offlen);
-               ch->ch_flags &= ~CH_PRON;
-       }
-
-       un->un_tty = NULL;
-       un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
-       tty->driver_data = NULL;
-
-       DPR_CLOSE(("Close. Doing wakeups\n"));
-       wake_up_interruptible(&ch->ch_flags_wait);
-       wake_up_interruptible(&un->un_flags_wait);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-        DPR_BASIC(("dgap_tty_close - complete\n"));
-}
-
-
-/*
- * dgap_tty_chars_in_buffer()
- *
- * Return number of characters that have not been transmitted yet.
- *
- * This routine is used by the line discipline to determine if there
- * is data waiting to be transmitted/drained/flushed or not.
- */
-static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
-{
-       struct board_t *bd = NULL;
-       struct channel_t *ch = NULL;
-       struct un_t *un = NULL;
-       struct bs_t *bs = NULL;
-       uchar tbusy;
-       uint chars = 0;
-       u16 thead, ttail, tmask, chead, ctail;
-       ulong   lock_flags = 0;
-       ulong   lock_flags2 = 0;
-
-       if (tty == NULL)
-               return(0);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (0);
-
-        bs = ch->ch_bs;
-       if (!bs)
-               return (0);
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       tmask = (ch->ch_tsize - 1);
-
-       /* Get Transmit queue pointers */
-       thead = readw(&(bs->tx_head)) & tmask;
-       ttail = readw(&(bs->tx_tail)) & tmask;
-
-       /* Get tbusy flag */
-       tbusy = readb(&(bs->tbusy));
-
-       /* Get Command queue pointers */
-       chead = readw(&(ch->ch_cm->cm_head));
-       ctail = readw(&(ch->ch_cm->cm_tail));
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       /*
-        * The only way we know for sure if there is no pending
-        * data left to be transferred, is if:
-        * 1) Transmit head and tail are equal (empty).
-        * 2) Command queue head and tail are equal (empty).
-        * 3) The "TBUSY" flag is 0. (Transmitter not busy).
-        */
-
-       if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
-               chars = 0;
-       }
-       else {
-               if (thead >= ttail)
-                       chars = thead - ttail;
-               else
-                       chars = thead - ttail + ch->ch_tsize;
-               /*
-                * Fudge factor here.
-                * If chars is zero, we know that the command queue had
-                * something in it or tbusy was set.  Because we cannot
-                * be sure if there is still some data to be transmitted,
-                * lets lie, and tell ld we have 1 byte left.
-                */
-               if (chars == 0) {
-                       /*
-                        * If TBUSY is still set, and our tx buffers are empty,
-                        * force the firmware to send me another wakeup after
-                        * TBUSY has been cleared.
-                        */
-                       if (tbusy != 0) {
-                               DGAP_LOCK(ch->ch_lock, lock_flags);
-                               un->un_flags |= UN_EMPTY;
-                               writeb(1, &(bs->iempty));
-                               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-                       }
-                       chars = 1;
-               }
-       }
-
-       DPR_WRITE(("dgap_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d tsize: %d)\n",
-               ch->ch_portnum, chars, thead, ttail, ch->ch_tsize));
-        return(chars);
-}
-
-
-static int dgap_wait_for_drain(struct tty_struct *tty)
-{
-       struct channel_t *ch;
-       struct un_t *un;
-       struct bs_t *bs;
-       int ret = -EIO;
-       uint count = 1;
-       ulong   lock_flags = 0;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return ret;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return ret;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return ret;
-
-        bs = ch->ch_bs;
-       if (!bs)
-               return ret;
-
-       ret = 0;
-
-       DPR_DRAIN(("dgap_wait_for_drain start\n"));
-
-       /* Loop until data is drained */
-       while (count != 0) {
-
-               count = dgap_tty_chars_in_buffer(tty);
-
-               if (count == 0)
-                       break;
-
-               /* Set flag waiting for drain */
-               DGAP_LOCK(ch->ch_lock, lock_flags);
-               un->un_flags |= UN_EMPTY;
-               writeb(1, &(bs->iempty));
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-               /* Go to sleep till we get woken up */
-               ret = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
-               /* If ret is non-zero, user ctrl-c'ed us */
-               if (ret) {
-                       break;
-               }
-       }
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-       un->un_flags &= ~(UN_EMPTY);
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       DPR_DRAIN(("dgap_wait_for_drain finish\n"));
-       return (ret);
-}
-
-
-/*
- * dgap_maxcps_room
- *
- * Reduces bytes_available to the max number of characters
- * that can be sent currently given the maxcps value, and
- * returns the new bytes_available.  This only affects printer
- * output.
- */
-static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
-{
-       struct channel_t *ch = NULL;
-       struct un_t *un = NULL;
-
-       if (tty == NULL)
-               return (bytes_available);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (bytes_available);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (bytes_available);
-
-       /*
-        * If its not the Transparent print device, return
-        * the full data amount.
-        */
-       if (un->un_type != DGAP_PRINT)
-               return (bytes_available);
-
-       if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
-               int cps_limit = 0;
-               unsigned long current_time = jiffies;
-               unsigned long buffer_time = current_time +
-                       (HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
-
-               if (ch->ch_cpstime < current_time) {
-                       /* buffer is empty */
-                       ch->ch_cpstime = current_time;            /* reset ch_cpstime */
-                       cps_limit = ch->ch_digi.digi_bufsize;
-               }
-               else if (ch->ch_cpstime < buffer_time) {
-                       /* still room in the buffer */
-                       cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
-               }
-               else {
-                       /* no room in the buffer */
-                       cps_limit = 0;
-               }
-
-               bytes_available = min(cps_limit, bytes_available);
-       }
-
-       return (bytes_available);
-}
-
-
-static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
-{
-       struct channel_t *ch = NULL;
-       struct bs_t *bs = NULL;
-
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-        bs = ch->ch_bs;
-       if (!bs)
-               return;
-
-       if ((event & UN_LOW) != 0) {
-               if ((un->un_flags & UN_LOW) == 0) {
-                       un->un_flags |= UN_LOW;
-                       writeb(1, &(bs->ilow));
-               }
-       }
-       if ((event & UN_LOW) != 0) {
-               if ((un->un_flags & UN_EMPTY) == 0) {
-                       un->un_flags |= UN_EMPTY;
-                       writeb(1, &(bs->iempty));
-               }
-       }
-}
-
-
-/*
- * dgap_tty_write_room()
- *
- * Return space available in Tx buffer
- */
-static int dgap_tty_write_room(struct tty_struct *tty)
-{
-       struct channel_t *ch = NULL;
-       struct un_t *un = NULL;
-       struct bs_t *bs = NULL;
-       u16 head, tail, tmask;
-       int ret = 0;
-       ulong   lock_flags = 0;
-
-       if (tty == NULL || dgap_TmpWriteBuf == NULL)
-               return(0);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (0);
-
-        bs = ch->ch_bs;
-       if (!bs)
-               return (0);
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-
-       tmask = ch->ch_tsize - 1;
-       head = readw(&(bs->tx_head)) & tmask;
-       tail = readw(&(bs->tx_tail)) & tmask;
-
-        if ((ret = tail - head - 1) < 0)
-                ret += ch->ch_tsize;
-
-       /* Limit printer to maxcps */
-       ret = dgap_maxcps_room(tty, ret);
-
-       /*
-        * If we are printer device, leave space for
-        * possibly both the on and off strings.
-        */
-       if (un->un_type == DGAP_PRINT) {
-               if (!(ch->ch_flags & CH_PRON))
-                       ret -= ch->ch_digi.digi_onlen;
-               ret -= ch->ch_digi.digi_offlen;
-       }
-       else {
-               if (ch->ch_flags & CH_PRON)
-                       ret -= ch->ch_digi.digi_offlen;
-       }
-
-       if (ret < 0)
-               ret = 0;
-
-       /*
-        * Schedule FEP to wake us up if needed.
-        *
-        * TODO:  This might be overkill...
-        * Do we really need to schedule callbacks from the FEP
-        * in every case?  Can we get smarter based on ret?
-        */
-       dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       DPR_WRITE(("dgap_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
-
-        return(ret);
-}
-
-
-/*
- * dgap_tty_put_char()
- *
- * Put a character into ch->ch_buf
- *
- *      - used by the line discipline for OPOST processing
- */
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
-{
-       /*
-        * Simply call tty_write.
-        */
-       DPR_WRITE(("dgap_tty_put_char called\n"));
-       dgap_tty_write(tty, &c, 1);
-       return 1;
-}
-
-
-/*
- * dgap_tty_write()
- *
- * Take data from the user or kernel and send it out to the FEP.
- * In here exists all the Transparent Print magic as well.
- */
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-       struct channel_t *ch = NULL;
-       struct un_t *un = NULL;
-       struct bs_t *bs = NULL;
-       char *vaddr = NULL;
-       u16 head, tail, tmask, remain;
-       int bufcount = 0, n = 0;
-       int orig_count = 0;
-       ulong lock_flags;
-       int from_user = 0;
-
-       if (tty == NULL || dgap_TmpWriteBuf == NULL)
-               return(0);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (0);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return(0);
-
-        bs = ch->ch_bs;
-       if (!bs)
-               return(0);
-
-       if (!count)
-               return(0);
-
-       DPR_WRITE(("dgap_tty_write: Port: %x tty=%p user=%d len=%d\n",
-               ch->ch_portnum, tty, from_user, count));
-
-       /*
-        * Store original amount of characters passed in.
-        * This helps to figure out if we should ask the FEP
-        * to send us an event when it has more space available.
-        */
-       orig_count = count;
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-
-       /* Get our space available for the channel from the board */
-       tmask = ch->ch_tsize - 1;
-       head = readw(&(bs->tx_head)) & tmask;
-       tail = readw(&(bs->tx_tail)) & tmask;
-
-       if ((bufcount = tail - head - 1) < 0)
-               bufcount += ch->ch_tsize;
-
-       DPR_WRITE(("%d: bufcount: %x count: %x tail: %x head: %x tmask: %x\n",
-               __LINE__, bufcount, count, tail, head, tmask));
-
-       /*
-        * Limit printer output to maxcps overall, with bursts allowed
-        * up to bufsize characters.
-        */
-       bufcount = dgap_maxcps_room(tty, bufcount);
-
-       /*
-        * Take minimum of what the user wants to send, and the
-        * space available in the FEP buffer.
-        */
-       count = min(count, bufcount);
-
-       /*
-        * Bail if no space left.
-        */
-       if (count <= 0) {
-               dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-               return(0);
-       }
-
-       /*
-        * Output the printer ON string, if we are in terminal mode, but
-        * need to be in printer mode.
-        */
-       if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
-               dgap_wmove(ch, ch->ch_digi.digi_onstr,
-                   (int) ch->ch_digi.digi_onlen);
-               head = readw(&(bs->tx_head)) & tmask;
-               ch->ch_flags |= CH_PRON;
-       }
-
-       /*
-        * On the other hand, output the printer OFF string, if we are
-        * currently in printer mode, but need to output to the terminal.
-        */
-       if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
-               dgap_wmove(ch, ch->ch_digi.digi_offstr,
-                       (int) ch->ch_digi.digi_offlen);
-               head = readw(&(bs->tx_head)) & tmask;
-               ch->ch_flags &= ~CH_PRON;
-       }
-
-       /*
-        * If there is nothing left to copy, or I can't handle any more data, leave.
-        */
-       if (count <= 0) {
-               dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-               return(0);
-       }
-
-       if (from_user) {
-
-               count = min(count, WRITEBUFLEN);
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-               /*
-                * If data is coming from user space, copy it into a temporary
-                * buffer so we don't get swapped out while doing the copy to
-                * the board.
-                */
-               /* we're allowed to block if it's from_user */
-               if (down_interruptible(&dgap_TmpWriteSem)) {
-                       return (-EINTR);
-               }
-
-               if (copy_from_user(dgap_TmpWriteBuf, (const uchar __user *) buf, count)) {
-                       up(&dgap_TmpWriteSem);
-                       printk("Write: Copy from user failed!\n");
-                       return -EFAULT;
-               }
-
-               DGAP_LOCK(ch->ch_lock, lock_flags);
-
-               buf = dgap_TmpWriteBuf;
-       }
-
-       n = count;
-
-       /*
-        * If the write wraps over the top of the circular buffer,
-        * move the portion up to the wrap point, and reset the
-        * pointers to the bottom.
-        */
-       remain = ch->ch_tstart + ch->ch_tsize - head;
-
-       if (n >= remain) {
-               n -= remain;
-               vaddr = ch->ch_taddr + head;
-
-               memcpy_toio(vaddr, (uchar *) buf, remain);
-               dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
-
-               head = ch->ch_tstart;
-               buf += remain;
-       }
-
-       if (n > 0) {
-
-               /*
-                * Move rest of data.
-                */
-               vaddr = ch->ch_taddr + head;
-               remain = n;
-
-               memcpy_toio(vaddr, (uchar *) buf, remain);
-               dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
-
-               head += remain;
-
-       }
-
-       if (count) {
-               ch->ch_txcount += count;
-               head &= tmask;
-               writew(head, &(bs->tx_head));
-       }
-
-
-       dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-
-       /*
-        * If this is the print device, and the
-        * printer is still on, we need to turn it
-        * off before going idle.  If the buffer is
-        * non-empty, wait until it goes empty.
-        * Otherwise turn it off right now.
-        */
-       if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
-               tail = readw(&(bs->tx_tail)) & tmask;
-
-               if (tail != head) {
-                       un->un_flags |= UN_EMPTY;
-                       writeb(1, &(bs->iempty));
-               }
-               else {
-                       dgap_wmove(ch, ch->ch_digi.digi_offstr,
-                               (int) ch->ch_digi.digi_offlen);
-                       head = readw(&(bs->tx_head)) & tmask;
-                       ch->ch_flags &= ~CH_PRON;
-               }
-       }
-
-       /* Update printer buffer empty time. */
-       if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
-           && (ch->ch_digi.digi_bufsize > 0)) {
-                ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
-       }
-
-       if (from_user) {
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-               up(&dgap_TmpWriteSem);
-       }
-       else {
-               DGAP_UNLOCK(ch->ch_lock, lock_flags);
-       }
-
-       DPR_WRITE(("Write finished - Write %d bytes of %d.\n", count, orig_count));
-
-       return (count);
-}
-
-
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_tty_tiocmget(struct tty_struct *tty)
-{
-       struct channel_t *ch;
-       struct un_t *un;
-       int result = -EIO;
-       uchar mstat = 0;
-       ulong lock_flags;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return result;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return result;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return result;
-
-       DPR_IOCTL(("dgap_tty_tiocmget start\n"));
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-
-       mstat = readb(&(ch->ch_bs->m_stat));
-        /* Append any outbound signals that might be pending... */
-        mstat |= ch->ch_mostat;
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       result = 0;
-
-       if (mstat & D_DTR(ch))
-               result |= TIOCM_DTR;
-       if (mstat & D_RTS(ch))
-               result |= TIOCM_RTS;
-       if (mstat & D_CTS(ch))
-               result |= TIOCM_CTS;
-       if (mstat & D_DSR(ch))
-               result |= TIOCM_DSR;
-       if (mstat & D_RI(ch))
-               result |= TIOCM_RI;
-       if (mstat & D_CD(ch))
-               result |= TIOCM_CD;
-
-       DPR_IOCTL(("dgap_tty_tiocmget finish\n"));
-
-       return result;
-}
-
-
-/*
- * dgap_tty_tiocmset()
- *
- * Set modem signals, called by ld.
- */
-
-static int dgap_tty_tiocmset(struct tty_struct *tty,
-                unsigned int set, unsigned int clear)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       int ret = -EIO;
-       ulong lock_flags;
-       ulong lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return ret;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return ret;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return ret;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return ret;
-
-       DPR_IOCTL(("dgap_tty_tiocmset start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       if (set & TIOCM_RTS) {
-               ch->ch_mforce |= D_RTS(ch);
-               ch->ch_mval   |= D_RTS(ch);
-        }
-
-       if (set & TIOCM_DTR) {
-               ch->ch_mforce |= D_DTR(ch);
-               ch->ch_mval   |= D_DTR(ch);
-        }
-
-       if (clear & TIOCM_RTS) {
-               ch->ch_mforce |= D_RTS(ch);
-               ch->ch_mval   &= ~(D_RTS(ch));
-        }
-
-       if (clear & TIOCM_DTR) {
-               ch->ch_mforce |= D_DTR(ch);
-               ch->ch_mval   &= ~(D_DTR(ch));
-        }
-
-       dgap_param(tty);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_tiocmset finish\n"));
-
-       return (0);
-}
-
-
-
-/*
- * dgap_tty_send_break()
- *
- * Send a Break, called by ld.
- */
-static int dgap_tty_send_break(struct tty_struct *tty, int msec)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       int ret = -EIO;
-       ulong lock_flags;
-       ulong lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return ret;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return ret;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return ret;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return ret;
-
-       switch (msec) {
-       case -1:
-               msec = 0xFFFF;
-               break;
-       case 0:
-               msec = 1;
-               break;
-       default:
-               msec /= 10;
-               break;
-       }
-
-       DPR_IOCTL(("dgap_tty_send_break start 1.  %lx\n", jiffies));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-#if 0
-       dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-#endif
-       dgap_cmdw(ch, SBREAK, (u16) msec, 0);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_send_break finish\n"));
-
-       return (0);
-}
-
-
-
-
-/*
- * dgap_tty_wait_until_sent()
- *
- * wait until data has been transmitted, called by ld.
- */
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-       int rc;
-       rc = dgap_wait_for_drain(tty);
-       if (rc) {
-               DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-               return;
-       }
-       return;
-}
-
-
-
-/*
- * dgap_send_xchar()
- *
- * send a high priority character, called by ld.
- */
-static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong lock_flags;
-       ulong lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_send_xchar start 1.  %lx\n", jiffies));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       /*
-        * This is technically what we should do.
-        * However, the NIST tests specifically want
-        * to see each XON or XOFF character that it
-        * sends, so lets just send each character
-        * by hand...
-        */
-#if 0
-       if (c == STOP_CHAR(tty)) {
-               dgap_cmdw(ch, RPAUSE, 0, 0);
-       }
-       else if (c == START_CHAR(tty)) {
-               dgap_cmdw(ch, RRESUME, 0, 0);
-       }
-       else {
-               dgap_wmove(ch, &c, 1);
-       }
-#else
-       dgap_wmove(ch, &c, 1);
-#endif
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_send_xchar finish\n"));
-
-       return;
-}
-
-
-
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
-{
-       int result = 0;
-       uchar mstat = 0;
-       ulong lock_flags;
-       int rc = 0;
-
-       DPR_IOCTL(("dgap_get_modem_info start\n"));
-
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return(-ENXIO);
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-
-       mstat = readb(&(ch->ch_bs->m_stat));
-       /* Append any outbound signals that might be pending... */
-       mstat |= ch->ch_mostat;
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       result = 0;
-
-       if (mstat & D_DTR(ch))
-               result |= TIOCM_DTR;
-       if (mstat & D_RTS(ch))
-               result |= TIOCM_RTS;
-       if (mstat & D_CTS(ch))
-               result |= TIOCM_CTS;
-       if (mstat & D_DSR(ch))
-               result |= TIOCM_DSR;
-       if (mstat & D_RI(ch))
-               result |= TIOCM_RI;
-       if (mstat & D_CD(ch))
-               result |= TIOCM_CD;
-
-       rc = put_user(result, value);
-
-       DPR_IOCTL(("dgap_get_modem_info finish\n"));
-       return(rc);
-}
-
-
-/*
- * dgap_set_modem_info()
- *
- * Set modem signals, called by ld.
- */
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       int ret = -ENXIO;
-       unsigned int arg = 0;
-       ulong lock_flags;
-       ulong lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return ret;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return ret;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return ret;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return ret;
-
-       DPR_IOCTL(("dgap_set_modem_info() start\n"));
-
-       ret = get_user(arg, value);
-       if (ret) {
-               DPR_IOCTL(("dgap_set_modem_info %d ret: %x. finished.\n", __LINE__, ret));
-               return(ret);
-       }
-
-       DPR_IOCTL(("dgap_set_modem_info: command: %x arg: %x\n", command, arg));
-
-       switch (command) {
-       case TIOCMBIS:
-               if (arg & TIOCM_RTS) {
-                       ch->ch_mforce |= D_RTS(ch);
-                       ch->ch_mval   |= D_RTS(ch);
-               }
-
-               if (arg & TIOCM_DTR) {
-                       ch->ch_mforce |= D_DTR(ch);
-                       ch->ch_mval   |= D_DTR(ch);
-               }
-
-               break;
-
-       case TIOCMBIC:
-               if (arg & TIOCM_RTS) {
-                       ch->ch_mforce |= D_RTS(ch);
-                       ch->ch_mval   &= ~(D_RTS(ch));
-               }
-
-               if (arg & TIOCM_DTR) {
-                       ch->ch_mforce |= D_DTR(ch);
-                       ch->ch_mval   &= ~(D_DTR(ch));
-               }
-
-               break;
-
-        case TIOCMSET:
-               ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
-
-               if (arg & TIOCM_RTS) {
-                       ch->ch_mval |= D_RTS(ch);
-               }
-               else {
-                       ch->ch_mval &= ~(D_RTS(ch));
-               }
-
-               if (arg & TIOCM_DTR) {
-                       ch->ch_mval |= (D_DTR(ch));
-               }
-               else {
-                       ch->ch_mval &= ~(D_DTR(ch));
-               }
-
-               break;
-
-       default:
-               return(-EINVAL);
-       }
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       dgap_param(tty);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_set_modem_info finish\n"));
-
-       return (0);
-}
-
-
-/*
- * dgap_tty_digigeta()
- *
- * Ioctl to get the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
-{
-       struct channel_t *ch;
-       struct un_t *un;
-       struct digi_t tmp;
-       ulong lock_flags;
-
-       if (!retinfo)
-               return (-EFAULT);
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-EFAULT);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-EFAULT);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-EFAULT);
-
-       memset(&tmp, 0, sizeof(tmp));
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-       memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-               return (-EFAULT);
-
-       return (0);
-}
-
-
-/*
- * dgap_tty_digiseta()
- *
- * Ioctl to set the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       struct digi_t new_digi;
-       ulong   lock_flags = 0;
-       unsigned long lock_flags2;
-
-       DPR_IOCTL(("DIGI_SETA start\n"));
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-EFAULT);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-EFAULT);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-EFAULT);
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (-EFAULT);
-
-        if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
-               DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
-                return(-EFAULT);
-       }
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
-
-       if (ch->ch_digi.digi_maxcps < 1)
-               ch->ch_digi.digi_maxcps = 1;
-
-       if (ch->ch_digi.digi_maxcps > 10000)
-               ch->ch_digi.digi_maxcps = 10000;
-
-       if (ch->ch_digi.digi_bufsize < 10)
-               ch->ch_digi.digi_bufsize = 10;
-
-       if (ch->ch_digi.digi_maxchar < 1)
-               ch->ch_digi.digi_maxchar = 1;
-
-       if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
-               ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
-
-       if (ch->ch_digi.digi_onlen > DIGI_PLEN)
-               ch->ch_digi.digi_onlen = DIGI_PLEN;
-
-       if (ch->ch_digi.digi_offlen > DIGI_PLEN)
-               ch->ch_digi.digi_offlen = DIGI_PLEN;
-
-       dgap_param(tty);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("DIGI_SETA finish\n"));
-
-       return(0);
-}
-
-
-/*
- * dgap_tty_digigetedelay()
- *
- * Ioctl to get the current edelay setting.
- *
- *
- *
- */
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
-{
-       struct channel_t *ch;
-       struct un_t *un;
-       int tmp;
-       ulong lock_flags;
-
-       if (!retinfo)
-               return (-EFAULT);
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-EFAULT);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-EFAULT);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-EFAULT);
-
-       memset(&tmp, 0, sizeof(tmp));
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-       tmp = readw(&(ch->ch_bs->edelay));
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-               return (-EFAULT);
-
-       return (0);
-}
-
-
-/*
- * dgap_tty_digisetedelay()
- *
- * Ioctl to set the EDELAY setting
- *
- */
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       int new_digi;
-       ulong lock_flags;
-       ulong lock_flags2;
-
-       DPR_IOCTL(("DIGI_SETA start\n"));
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-EFAULT);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-EFAULT);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-EFAULT);
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (-EFAULT);
-
-        if (copy_from_user(&new_digi, new_info, sizeof(int))) {
-               DPR_IOCTL(("DIGI_SETEDELAY failed copy_from_user\n"));
-                return(-EFAULT);
-       }
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       writew((u16) new_digi, &(ch->ch_bs->edelay));
-
-       dgap_param(tty);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("DIGI_SETA finish\n"));
-
-       return(0);
-}
-
-
-/*
- * dgap_tty_digigetcustombaud()
- *
- * Ioctl to get the current custom baud rate setting.
- */
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo)
-{
-       struct channel_t *ch;
-       struct un_t *un;
-       int tmp;
-       ulong lock_flags;
-
-       if (!retinfo)
-               return (-EFAULT);
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-EFAULT);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-EFAULT);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-EFAULT);
-
-       memset(&tmp, 0, sizeof(tmp));
-
-       DGAP_LOCK(ch->ch_lock, lock_flags);
-       tmp = dgap_get_custom_baud(ch);
-       DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-       DPR_IOCTL(("DIGI_GETCUSTOMBAUD. Returning %d\n", tmp));
-
-       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-               return (-EFAULT);
-
-       return (0);
-}
-
-
-/*
- * dgap_tty_digisetcustombaud()
- *
- * Ioctl to set the custom baud rate setting
- */
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       uint new_rate;
-       ulong lock_flags;
-       ulong lock_flags2;
-
-       DPR_IOCTL(("DIGI_SETCUSTOMBAUD start\n"));
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-EFAULT);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-EFAULT);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-EFAULT);
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (-EFAULT);
-
-
-       if (copy_from_user(&new_rate, new_info, sizeof(unsigned int))) {
-               DPR_IOCTL(("DIGI_SETCUSTOMBAUD failed copy_from_user\n"));
-               return(-EFAULT);
-       }
-
-       if (bd->bd_flags & BD_FEP5PLUS) {
-
-               DPR_IOCTL(("DIGI_SETCUSTOMBAUD. Setting %d\n", new_rate));
-
-               DGAP_LOCK(bd->bd_lock, lock_flags);
-               DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-               ch->ch_custom_speed = new_rate;
-
-               dgap_param(tty);
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-       }
-
-       DPR_IOCTL(("DIGI_SETCUSTOMBAUD finish\n"));
-
-       return(0);
-}
-
-
-/*
- * dgap_set_termios()
- */
-static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       unsigned long lock_flags;
-       unsigned long lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       ch->ch_c_cflag   = tty->termios.c_cflag;
-       ch->ch_c_iflag   = tty->termios.c_iflag;
-       ch->ch_c_oflag   = tty->termios.c_oflag;
-       ch->ch_c_lflag   = tty->termios.c_lflag;
-       ch->ch_startc    = tty->termios.c_cc[VSTART];
-       ch->ch_stopc     = tty->termios.c_cc[VSTOP];
-
-       dgap_carrier(ch);
-       dgap_param(tty);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-}
-
-
-static void dgap_tty_throttle(struct tty_struct *tty)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_throttle start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       ch->ch_flags |= (CH_RXBLOCK);
-#if 1
-       dgap_cmdw(ch, RPAUSE, 0, 0);
-#endif
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_throttle finish\n"));
-}
-
-
-static void dgap_tty_unthrottle(struct tty_struct *tty)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_unthrottle start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       ch->ch_flags &= ~(CH_RXBLOCK);
-
-#if 1
-       dgap_cmdw(ch, RRESUME, 0, 0);
-#endif
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_unthrottle finish\n"));
-}
-
-
-static void dgap_tty_start(struct tty_struct *tty)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_start start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       dgap_cmdw(ch, RESUMETX, 0, 0);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_start finish\n"));
-}
-
-
-static void dgap_tty_stop(struct tty_struct *tty)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_stop start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       dgap_cmdw(ch, PAUSETX, 0, 0);
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_stop finish\n"));
-}
-
-
-/*
- * dgap_tty_flush_chars()
- *
- * Flush the cook buffer
- *
- * Note to self, and any other poor souls who venture here:
- *
- * flush in this case DOES NOT mean dispose of the data.
- * instead, it means "stop buffering and send it if you
- * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
- *
- * It is also always called in interrupt context - JAR 8-Sept-99
- */
-static void dgap_tty_flush_chars(struct tty_struct *tty)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_flush_chars start\n"));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       /* TODO: Do something here */
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-       DPR_IOCTL(("dgap_tty_flush_chars finish\n"));
-}
-
-
-
-/*
- * dgap_tty_flush_buffer()
- *
- * Flush Tx buffer (make in == out)
- */
-static void dgap_tty_flush_buffer(struct tty_struct *tty)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       ulong   lock_flags;
-       ulong   lock_flags2;
-       u16     head = 0;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return;
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return;
-
-       DPR_IOCTL(("dgap_tty_flush_buffer on port: %d start\n", ch->ch_portnum));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       ch->ch_flags &= ~CH_STOP;
-       head = readw(&(ch->ch_bs->tx_head));
-       dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
-       dgap_cmdw(ch, RESUMETX, 0, 0);
-       if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
-               ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
-               wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-       }
-       if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
-               ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
-               wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-       }
-
-       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-       if (waitqueue_active(&tty->write_wait))
-               wake_up_interruptible(&tty->write_wait);
-       tty_wakeup(tty);
-
-       DPR_IOCTL(("dgap_tty_flush_buffer finish\n"));
-}
-
-
-
-/*****************************************************************************
- *
- * The IOCTL function and all of its helpers
- *
- *****************************************************************************/
-
-/*
- * dgap_tty_ioctl()
- *
- * The usual assortment of ioctl's
- */
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
-               unsigned long arg)
-{
-       struct board_t *bd;
-       struct channel_t *ch;
-       struct un_t *un;
-       int rc;
-       u16     head = 0;
-       ulong   lock_flags = 0;
-       ulong   lock_flags2 = 0;
-       void __user *uarg = (void __user *) arg;
-
-       if (!tty || tty->magic != TTY_MAGIC)
-               return (-ENODEV);
-
-       un = tty->driver_data;
-       if (!un || un->magic != DGAP_UNIT_MAGIC)
-               return (-ENODEV);
-
-       ch = un->un_ch;
-       if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-               return (-ENODEV);
-
-       bd = ch->ch_bd;
-       if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-               return (-ENODEV);
-
-       DPR_IOCTL(("dgap_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
-               ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-       DGAP_LOCK(bd->bd_lock, lock_flags);
-       DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-       if (un->un_open_count <= 0) {
-               DPR_BASIC(("dgap_tty_ioctl - unit not open.\n"));
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(-EIO);
-       }
-
-       switch (cmd) {
-
-       /* Here are all the standard ioctl's that we MUST implement */
-
-       case TCSBRK:
-               /*
-                * TCSBRK is SVID version: non-zero arg --> no break
-                * this behaviour is exploited by tcdrain().
-                *
-                * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-                * between 0.25 and 0.5 seconds so we'll ask for something
-                * in the middle: 0.375 seconds.
-                */
-               rc = tty_check_change(tty);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               if (rc) {
-                       return(rc);
-               }
-
-               rc = dgap_wait_for_drain(tty);
-
-               if (rc) {
-                       DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-                       return(-EINTR);
-               }
-
-               DGAP_LOCK(bd->bd_lock, lock_flags);
-               DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-               if(((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) {
-                       dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-               }
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-                       ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-                return(0);
-
-
-       case TCSBRKP:
-               /* support for POSIX tcsendbreak()
-
-                * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-                * between 0.25 and 0.5 seconds so we'll ask for something
-                * in the middle: 0.375 seconds.
-                */
-               rc = tty_check_change(tty);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               if (rc) {
-                       return(rc);
-               }
-
-               rc = dgap_wait_for_drain(tty);
-               if (rc) {
-                       DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-                       return(-EINTR);
-               }
-
-               DGAP_LOCK(bd->bd_lock, lock_flags);
-               DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-               dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-                       ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-               return(0);
-
-        case TIOCSBRK:
-               /*
-                * FEP5 doesn't support turning on a break unconditionally.
-                * The FEP5 device will stop sending a break automatically
-                * after the specified time value that was sent when turning on
-                * the break.
-                */
-               rc = tty_check_change(tty);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               if (rc) {
-                       return(rc);
-               }
-
-               rc = dgap_wait_for_drain(tty);
-               if (rc) {
-                       DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-                       return(-EINTR);
-               }
-
-               DGAP_LOCK(bd->bd_lock, lock_flags);
-               DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-               dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-                       ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-               return 0;
-
-        case TIOCCBRK:
-               /*
-                * FEP5 doesn't support turning off a break unconditionally.
-                * The FEP5 device will stop sending a break automatically
-                * after the specified time value that was sent when turning on
-                * the break.
-                */
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return 0;
-
-       case TIOCGSOFTCAR:
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
-               return(rc);
-
-       case TIOCSSOFTCAR:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               rc = get_user(arg, (unsigned long __user *) arg);
-               if (rc)
-                       return(rc);
-
-               DGAP_LOCK(bd->bd_lock, lock_flags);
-               DGAP_LOCK(ch->ch_lock, lock_flags2);
-               tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
-               dgap_param(tty);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               return(0);
-
-       case TIOCMGET:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                return(dgap_get_modem_info(ch, uarg));
-
-       case TIOCMBIS:
-       case TIOCMBIC:
-       case TIOCMSET:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_set_modem_info(tty, cmd, uarg));
-
-               /*
-                * Here are any additional ioctl's that we want to implement
-                */
-
-       case TCFLSH:
-               /*
-                * The linux tty driver doesn't have a flush
-                * input routine for the driver, assuming all backed
-                * up data is in the line disc. buffers.  However,
-                * we all know that's not the case.  Here, we
-                * act on the ioctl, but then lie and say we didn't
-                * so the line discipline will process the flush
-                * also.
-                */
-               rc = tty_check_change(tty);
-               if (rc) {
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       return(rc);
-               }
-
-               if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
-                       if (!(un->un_type == DGAP_PRINT)) {
-                               head = readw(&(ch->ch_bs->rx_head));
-                               writew(head, &(ch->ch_bs->rx_tail));
-                               writeb(0, &(ch->ch_bs->orun));
-                       }
-               }
-
-               if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
-                       ch->ch_flags &= ~CH_STOP;
-                       head = readw(&(ch->ch_bs->tx_head));
-                       dgap_cmdw(ch, FLUSHTX, (u16) head, 0 );
-                       dgap_cmdw(ch, RESUMETX, 0, 0);
-                       if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
-                               ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
-                               wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-                       }
-                       if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
-                               ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
-                               wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-                       }
-                       if (waitqueue_active(&tty->write_wait))
-                               wake_up_interruptible(&tty->write_wait);
-
-                       /* Can't hold any locks when calling tty_wakeup! */
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       tty_wakeup(tty);
-                       DGAP_LOCK(bd->bd_lock, lock_flags);
-                       DGAP_LOCK(ch->ch_lock, lock_flags2);
-               }
-
-               /* pretend we didn't recognize this IOCTL */
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               DPR_IOCTL(("dgap_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n",
-                       __LINE__, ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-               return(-ENOIOCTLCMD);
-
-       case TCSETSF:
-       case TCSETSW:
-               /*
-                * The linux tty driver doesn't have a flush
-                * input routine for the driver, assuming all backed
-                * up data is in the line disc. buffers.  However,
-                * we all know that's not the case.  Here, we
-                * act on the ioctl, but then lie and say we didn't
-                * so the line discipline will process the flush
-                * also.
-                */
-               if (cmd == TCSETSF) {
-                       /* flush rx */
-                       ch->ch_flags &= ~CH_STOP;
-                       head = readw(&(ch->ch_bs->rx_head));
-                       writew(head, &(ch->ch_bs->rx_tail));
-               }
-
-               /* now wait for all the output to drain */
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               rc = dgap_wait_for_drain(tty);
-               if (rc) {
-                       DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-                       return(-EINTR);
-               }
-
-               DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-                       ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-               /* pretend we didn't recognize this */
-               return(-ENOIOCTLCMD);
-
-       case TCSETAW:
-
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               rc = dgap_wait_for_drain(tty);
-               if (rc) {
-                       DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-                       return(-EINTR);
-               }
-
-               /* pretend we didn't recognize this */
-               return(-ENOIOCTLCMD);
-
-       case TCXONC:
-               /*
-                * The Linux Line Discipline (LD) would do this for us if we
-                * let it, but we have the special firmware options to do this
-                * the "right way" regardless of hardware or software flow
-                * control so we'll do it outselves instead of letting the LD
-                * do it.
-                */
-               rc = tty_check_change(tty);
-               if (rc) {
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       return(rc);
-               }
-
-               DPR_IOCTL(("dgap_ioctl - in TCXONC - %d\n", cmd));
-               switch (arg) {
-
-               case TCOON:
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       dgap_tty_start(tty);
-                       return(0);
-               case TCOOFF:
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       dgap_tty_stop(tty);
-                       return(0);
-               case TCION:
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       /* Make the ld do it */
-                       return(-ENOIOCTLCMD);
-               case TCIOFF:
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       /* Make the ld do it */
-                       return(-ENOIOCTLCMD);
-               default:
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       return(-EINVAL);
-               }
-
-       case DIGI_GETA:
-               /* get information for ditty */
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_tty_digigeta(tty, uarg));
-
-       case DIGI_SETAW:
-       case DIGI_SETAF:
-
-               /* set information for ditty */
-               if (cmd == (DIGI_SETAW)) {
-
-                       DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-                       DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                       rc = dgap_wait_for_drain(tty);
-                       if (rc) {
-                               DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-                               return(-EINTR);
-                       }
-                       DGAP_LOCK(bd->bd_lock, lock_flags);
-                       DGAP_LOCK(ch->ch_lock, lock_flags2);
-               }
-               else {
-                       tty_ldisc_flush(tty);
-               }
-               /* fall thru */
-
-       case DIGI_SETA:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_tty_digiseta(tty, uarg));
-
-       case DIGI_GEDELAY:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_tty_digigetedelay(tty, uarg));
-
-       case DIGI_SEDELAY:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_tty_digisetedelay(tty, uarg));
-
-       case DIGI_GETCUSTOMBAUD:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_tty_digigetcustombaud(tty, uarg));
-
-       case DIGI_SETCUSTOMBAUD:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return(dgap_tty_digisetcustombaud(tty, uarg));
-
-       case DIGI_RESET_PORT:
-               dgap_firmware_reset_port(ch);
-               dgap_param(tty);
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-               return 0;
-
-       default:
-               DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-               DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-               DPR_IOCTL(("dgap_tty_ioctl - in default\n"));
-               DPR_IOCTL(("dgap_tty_ioctl end - cmd %s (%x), arg %lx\n",
-                       dgap_ioctl_name(cmd), cmd, arg));
-
-               return(-ENOIOCTLCMD);
-       }
-}
diff --git a/drivers/staging/dgap/dgap_tty.h b/drivers/staging/dgap/dgap_tty.h
deleted file mode 100644 (file)
index 464a460..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_TTY_H
-#define __DGAP_TTY_H
-
-#include "dgap_driver.h"
-
-int    dgap_tty_register(struct board_t *brd);
-
-int    dgap_tty_preinit(void);
-int     dgap_tty_init(struct board_t *);
-
-void   dgap_tty_post_uninit(void);
-void   dgap_tty_uninit(struct board_t *);
-
-void   dgap_carrier(struct channel_t *ch);
-void   dgap_input(struct channel_t *ch);
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_types.h b/drivers/staging/dgap/dgap_types.h
deleted file mode 100644 (file)
index eca38c7..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_TYPES_H
-#define __DGAP_TYPES_H
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-/* Required for our shared headers! */
-typedef unsigned char          uchar;
-
-#endif
diff --git a/drivers/staging/dgap/digi.h b/drivers/staging/dgap/digi.h
deleted file mode 100644 (file)
index fe87903..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- * $Id: digi.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DIGI_H
-#define __DIGI_H
-
-/************************************************************************
- ***   Definitions for Digi ditty(1) command.
- ************************************************************************/
-
-
-/*
- * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
- */
-
-/************************************************************************
- * This module provides application access to special Digi
- * serial line enhancements which are not standard UNIX(tm) features.
- ************************************************************************/
-
-#if !defined(TIOCMODG)
-
-#define        TIOCMODG        ('d'<<8) | 250          /* get modem ctrl state */
-#define        TIOCMODS        ('d'<<8) | 251          /* set modem ctrl state */
-
-#ifndef TIOCM_LE
-#define                TIOCM_LE        0x01            /* line enable          */
-#define                TIOCM_DTR       0x02            /* data terminal ready  */
-#define                TIOCM_RTS       0x04            /* request to send      */
-#define                TIOCM_ST        0x08            /* secondary transmit   */
-#define                TIOCM_SR        0x10            /* secondary receive    */
-#define                TIOCM_CTS       0x20            /* clear to send        */
-#define                TIOCM_CAR       0x40            /* carrier detect       */
-#define                TIOCM_RNG       0x80            /* ring indicator       */
-#define                TIOCM_DSR       0x100           /* data set ready       */
-#define                TIOCM_RI        TIOCM_RNG       /* ring (alternate)     */
-#define                TIOCM_CD        TIOCM_CAR       /* carrier detect (alt) */
-#endif
-
-#endif
-
-#if !defined(TIOCMSET)
-#define        TIOCMSET        ('d'<<8) | 252          /* set modem ctrl state */
-#define        TIOCMGET        ('d'<<8) | 253          /* set modem ctrl state */
-#endif
-
-#if !defined(TIOCMBIC)
-#define        TIOCMBIC        ('d'<<8) | 254          /* set modem ctrl state */
-#define        TIOCMBIS        ('d'<<8) | 255          /* set modem ctrl state */
-#endif
-
-
-#if !defined(TIOCSDTR)
-#define        TIOCSDTR        ('e'<<8) | 0            /* set DTR              */
-#define        TIOCCDTR        ('e'<<8) | 1            /* clear DTR            */
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA      ('e'<<8) | 94           /* Read params          */
-
-#define DIGI_SETA      ('e'<<8) | 95           /* Set params           */
-#define DIGI_SETAW     ('e'<<8) | 96           /* Drain & set params   */
-#define DIGI_SETAF     ('e'<<8) | 97           /* Drain, flush & set params */
-
-#define DIGI_KME       ('e'<<8) | 98           /* Read/Write Host      */
-                                               /* Adapter Memory       */
-
-#define        DIGI_GETFLOW    ('e'<<8) | 99           /* Get startc/stopc flow */
-                                               /* control characters    */
-#define        DIGI_SETFLOW    ('e'<<8) | 100          /* Set startc/stopc flow */
-                                               /* control characters    */
-#define        DIGI_GETAFLOW   ('e'<<8) | 101          /* Get Aux. startc/stopc */
-                                               /* flow control chars    */
-#define        DIGI_SETAFLOW   ('e'<<8) | 102          /* Set Aux. startc/stopc */
-                                               /* flow control chars    */
-
-#define DIGI_GEDELAY   ('d'<<8) | 246          /* Get edelay */
-#define DIGI_SEDELAY   ('d'<<8) | 247          /* Set edelay */
-
-struct digiflow_t {
-       unsigned char   startc;                         /* flow cntl start char */
-       unsigned char   stopc;                          /* flow cntl stop char  */
-};
-
-
-#ifdef FLOW_2200
-#define        F2200_GETA      ('e'<<8) | 104          /* Get 2x36 flow cntl flags */
-#define        F2200_SETAW     ('e'<<8) | 105          /* Set 2x36 flow cntl flags */
-#define                F2200_MASK      0x03            /* 2200 flow cntl bit mask  */
-#define                FCNTL_2200      0x01            /* 2x36 terminal flow cntl  */
-#define                PCNTL_2200      0x02            /* 2x36 printer flow cntl   */
-#define        F2200_XON       0xf8
-#define        P2200_XON       0xf9
-#define        F2200_XOFF      0xfa
-#define        P2200_XOFF      0xfb
-
-#define        FXOFF_MASK      0x03                    /* 2200 flow status mask    */
-#define        RCVD_FXOFF      0x01                    /* 2x36 Terminal XOFF rcvd  */
-#define        RCVD_PXOFF      0x02                    /* 2x36 Printer XOFF rcvd   */
-#endif
-
-/************************************************************************
- * Values for digi_flags
- ************************************************************************/
-#define DIGI_IXON      0x0001          /* Handle IXON in the FEP       */
-#define DIGI_FAST      0x0002          /* Fast baud rates              */
-#define RTSPACE                0x0004          /* RTS input flow control       */
-#define CTSPACE                0x0008          /* CTS output flow control      */
-#define DSRPACE                0x0010          /* DSR output flow control      */
-#define DCDPACE                0x0020          /* DCD output flow control      */
-#define DTRPACE                0x0040          /* DTR input flow control       */
-#define DIGI_COOK      0x0080          /* Cooked processing done in FEP */
-#define DIGI_FORCEDCD  0x0100          /* Force carrier                */
-#define        DIGI_ALTPIN     0x0200          /* Alternate RJ-45 pin config   */
-#define        DIGI_AIXON      0x0400          /* Aux flow control in fep      */
-#define        DIGI_PRINTER    0x0800          /* Hold port open for flow cntrl*/
-#define DIGI_PP_INPUT  0x1000          /* Change parallel port to input*/
-#define DIGI_DTR_TOGGLE 0x2000         /* Support DTR Toggle           */
-#define        DIGI_422        0x4000          /* for 422/232 selectable panel */
-#define DIGI_RTS_TOGGLE        0x8000          /* Support RTS Toggle           */
-
-/************************************************************************
- * These options are not supported on the comxi.
- ************************************************************************/
-#define        DIGI_COMXI      (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
-
-#define DIGI_PLEN      28              /* String length                */
-#define        DIGI_TSIZ       10              /* Terminal string len          */
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_t {
-       unsigned short  digi_flags;             /* Flags (see above)    */
-       unsigned short  digi_maxcps;            /* Max printer CPS      */
-       unsigned short  digi_maxchar;           /* Max chars in print queue */
-       unsigned short  digi_bufsize;           /* Buffer size          */
-       unsigned char   digi_onlen;             /* Length of ON string  */
-       unsigned char   digi_offlen;            /* Length of OFF string */
-       char            digi_onstr[DIGI_PLEN];  /* Printer on string    */
-       char            digi_offstr[DIGI_PLEN]; /* Printer off string   */
-       char            digi_term[DIGI_TSIZ];   /* terminal string      */
-};
-
-/************************************************************************
- * KME definitions and structures.
- ************************************************************************/
-#define        RW_IDLE         0       /* Operation complete                   */
-#define        RW_READ         1       /* Read Concentrator Memory             */
-#define        RW_WRITE        2       /* Write Concentrator Memory            */
-
-struct rw_t {
-       unsigned char   rw_req;         /* Request type                 */
-       unsigned char   rw_board;       /* Host Adapter board number    */
-       unsigned char   rw_conc;        /* Concentrator number          */
-       unsigned char   rw_reserved;    /* Reserved for expansion       */
-       unsigned long   rw_addr;        /* Address in concentrator      */
-       unsigned short  rw_size;        /* Read/write request length    */
-       unsigned char   rw_data[128];   /* Data to read/write           */
-};
-
-/***********************************************************************
- * Shrink Buffer and Board Information definitions and structures.
-
- ************************************************************************/
-                       /* Board type return codes */
-#define        PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
-#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
-#define        PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
-#define        MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
-#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
-
-                        /* Non-Zero Result codes. */
-#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
-#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
-#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
-#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
-#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
-
-struct shrink_buf_struct {
-       unsigned long   shrink_buf_vaddr;       /* Virtual address of board */
-       unsigned long   shrink_buf_phys;        /* Physical address of board */
-       unsigned long   shrink_buf_bseg;        /* Amount of board memory */
-       unsigned long   shrink_buf_hseg;        /* '186 Beginning of Dual-Port */
-
-       unsigned long   shrink_buf_lseg;        /* '186 Beginning of freed memory                                               */
-       unsigned long   shrink_buf_mseg;        /* Linear address from start of
-                                                  dual-port were freed memory
-                                                  begins, host viewpoint. */
-
-       unsigned long   shrink_buf_bdparam;     /* Parameter for xxmemon and
-                                                  xxmemoff */
-
-       unsigned long   shrink_buf_reserva;     /* Reserved */
-       unsigned long   shrink_buf_reservb;     /* Reserved */
-       unsigned long   shrink_buf_reservc;     /* Reserved */
-       unsigned long   shrink_buf_reservd;     /* Reserved */
-
-       unsigned char   shrink_buf_result;      /* Reason for call failing
-                                                  Zero is Good return */
-       unsigned char   shrink_buf_init;        /* Non-Zero if it caused an
-                                                  xxinit call. */
-
-       unsigned char   shrink_buf_anports;     /* Number of async ports  */
-       unsigned char   shrink_buf_snports;     /* Number of sync  ports */
-       unsigned char   shrink_buf_type;        /* Board type 1 = PC/Xi,
-                                                             2 = PC/Xm,
-                                                             3 = PC/Xe
-                                                             4 = MC/Xi
-                                                             5 = COMX/i */
-       unsigned char   shrink_buf_card;        /* Card number */
-
-};
-
-/************************************************************************
- * Structure to get driver status information
- ************************************************************************/
-struct digi_dinfo {
-       unsigned long   dinfo_nboards;          /* # boards configured  */
-       char            dinfo_reserved[12];     /* for future expansion */
-       char            dinfo_version[16];      /* driver version       */
-};
-
-#define        DIGI_GETDD      ('d'<<8) | 248          /* get driver info      */
-
-/************************************************************************
- * Structure used with ioctl commands for per-board information
- *
- * physsize and memsize differ when board has "windowed" memory
- ************************************************************************/
-struct digi_info {
-       unsigned long   info_bdnum;             /* Board number (0 based)  */
-       unsigned long   info_ioport;            /* io port address         */
-       unsigned long   info_physaddr;          /* memory address          */
-       unsigned long   info_physsize;          /* Size of host mem window */
-       unsigned long   info_memsize;           /* Amount of dual-port mem */
-                                               /* on board                */
-       unsigned short  info_bdtype;            /* Board type              */
-       unsigned short  info_nports;            /* number of ports         */
-       char            info_bdstate;           /* board state             */
-       char            info_reserved[7];       /* for future expansion    */
-};
-
-#define        DIGI_GETBD      ('d'<<8) | 249          /* get board info          */
-
-struct digi_stat {
-       unsigned int    info_chan;              /* Channel number (0 based)  */
-       unsigned int    info_brd;               /* Board number (0 based)  */
-       unsigned long   info_cflag;             /* cflag for channel       */
-       unsigned long   info_iflag;             /* iflag for channel       */
-       unsigned long   info_oflag;             /* oflag for channel       */
-       unsigned long   info_mstat;             /* mstat for channel       */
-       unsigned long   info_tx_data;           /* tx_data for channel       */
-       unsigned long   info_rx_data;           /* rx_data for channel       */
-       unsigned long   info_hflow;             /* hflow for channel       */
-       unsigned long   info_reserved[8];       /* for future expansion    */
-};
-
-#define        DIGI_GETSTAT    ('d'<<8) | 244          /* get board info          */
-/************************************************************************
- *
- * Structure used with ioctl commands for per-channel information
- *
- ************************************************************************/
-struct digi_ch {
-       unsigned long   info_bdnum;             /* Board number (0 based)  */
-       unsigned long   info_channel;           /* Channel index number    */
-       unsigned long   info_ch_cflag;          /* Channel cflag           */
-       unsigned long   info_ch_iflag;          /* Channel iflag           */
-       unsigned long   info_ch_oflag;          /* Channel oflag           */
-       unsigned long   info_chsize;            /* Channel structure size  */
-       unsigned long   info_sleep_stat;        /* sleep status            */
-       dev_t           info_dev;               /* device number           */
-       unsigned char   info_initstate;         /* Channel init state      */
-       unsigned char   info_running;           /* Channel running state   */
-       long            reserved[8];            /* reserved for future use */
-};
-
-/*
-* This structure is used with the DIGI_FEPCMD ioctl to
-* tell the driver which port to send the command for.
-*/
-struct digi_cmd {
-       int     cmd;
-       int     word;
-       int     ncmds;
-       int     chan; /* channel index (zero based) */
-       int     bdid; /* board index (zero based) */
-};
-
-/*
-*  info_sleep_stat defines
-*/
-#define INFO_RUNWAIT   0x0001
-#define INFO_WOPEN     0x0002
-#define INFO_TTIOW     0x0004
-#define INFO_CH_RWAIT  0x0008
-#define INFO_CH_WEMPTY 0x0010
-#define INFO_CH_WLOW   0x0020
-#define INFO_XXBUF_BUSY 0x0040
-
-#define        DIGI_GETCH      ('d'<<8) | 245          /* get board info          */
-
-/* Board type definitions */
-
-#define        SUBTYPE         0007
-#define        T_PCXI          0000
-#define T_PCXM         0001
-#define T_PCXE         0002
-#define T_PCXR         0003
-#define T_SP           0004
-#define T_SP_PLUS      0005
-#      define T_HERC   0000
-#      define T_HOU    0001
-#      define T_LON    0002
-#      define T_CHA    0003
-#define FAMILY         0070
-#define T_COMXI                0000
-#define T_PCXX         0010
-#define T_CX           0020
-#define T_EPC          0030
-#define        T_PCLITE        0040
-#define        T_SPXX          0050
-#define        T_AVXX          0060
-#define T_DXB          0070
-#define T_A2K_4_8      0070
-#define BUSTYPE                0700
-#define T_ISABUS       0000
-#define T_MCBUS                0100
-#define        T_EISABUS       0200
-#define        T_PCIBUS        0400
-
-/* Board State Definitions */
-
-#define        BD_RUNNING      0x0
-#define        BD_REASON       0x7f
-#define        BD_NOTFOUND     0x1
-#define        BD_NOIOPORT     0x2
-#define        BD_NOMEM        0x3
-#define        BD_NOBIOS       0x4
-#define        BD_NOFEP        0x5
-#define        BD_FAILED       0x6
-#define BD_ALLOCATED   0x7
-#define BD_TRIBOOT     0x8
-#define        BD_BADKME       0x80
-
-#define DIGI_LOOPBACK        ('d'<<8) | 252            /* Enable/disable UART internal loopback */
-#define DIGI_SPOLL            ('d'<<8) | 254           /* change poller rate   */
-
-#define DIGI_SETCUSTOMBAUD     _IOW('e', 106, int)     /* Set integer baud rate */
-#define DIGI_GETCUSTOMBAUD     _IOR('e', 107, int)     /* Get integer baud rate */
-#define DIGI_RESET_PORT                ('e'<<8) | 93           /* Reset port           */
-
-#endif /* DIGI_H */
diff --git a/drivers/staging/dgap/downld.c b/drivers/staging/dgap/downld.c
deleted file mode 100644 (file)
index 1f4aa2e..0000000
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
- *
- * $Id: downld.c,v 1.6 2009/01/14 14:10:54 markh Exp $
- */
-
-/*
-** downld.c
-**
-**  This is the daemon that sends the fep, bios, and concentrator images
-**  from user space to the driver.
-** BUGS:
-**  If the file changes in the middle of the download, you probably
-**     will get what you deserve.
-**
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-
-#include "dgap_types.h"
-#include "digi.h"
-#include "dgap_fep5.h"
-
-#include "dgap_downld.h"
-
-#include <string.h>
-#include <malloc.h>
-#include <stddef.h>
-#include <unistd.h>
-
-char           *pgm;
-void           myperror();
-
-/*
-**  This structure is used to keep track of the different images available
-**  to give to the driver.  It is arranged so that the things that are
-**  constants or that have defaults are first inthe strucutre to simplify
-**  the table of initializers.
-*/
-struct image_info {
-       short   type;           /* bios, fep, conc */
-       short   family;         /* boards this applies to */
-       short   subtype;        /* subtype */
-       int     len;            /* size of image */
-       char    *image;         /* ioctl struct + image */
-       char    *name;
-       char    *fname;         /* filename of binary (i.e. "asfep.bin") */
-       char    *pathname;      /* pathname to this binary ("/etc/dgap/xrfep.bin"); */
-       time_t  mtime;          /* Last modification time */
-};
-
-#define IBIOS  0
-#define        IFEP    1
-#define        ICONC   2
-#define ICONFIG        3
-#define        IBAD    4
-
-#define DEFAULT_LOC "/lib/firmware/dgap/"
-
-struct image_info      *image_list;
-int                    nimages, count;
-
-struct image_info images[] = {
-{IBIOS, T_EPC,      SUBTYPE, 0, NULL, "EPC/X", "fxbios.bin", DEFAULT_LOC "fxbios.bin", 0 },
-{IFEP,  T_EPC,      SUBTYPE, 0, NULL, "EPC/X", "fxfep.bin", DEFAULT_LOC "fxfep.bin", 0 },
-{ICONC, T_EPC,      SUBTYPE, 0, NULL, "EPC/X", "fxcon.bin", DEFAULT_LOC "fxcon.bin", 0 },
-
-{IBIOS, T_CX,       SUBTYPE, 0, NULL, "C/X",   "cxbios.bin", DEFAULT_LOC "cxbios.bin", 0 },
-{IFEP,  T_CX,       SUBTYPE, 0, NULL, "C/X",   "cxhost.bin", DEFAULT_LOC "cxhost.bin", 0 },
-
-{IBIOS, T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpbios.bin", DEFAULT_LOC "cxpbios.bin", 0 },
-{IFEP,  T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpfep.bin", DEFAULT_LOC "cxpfep.bin", 0 },
-
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",   "cxcon.bin", DEFAULT_LOC "cxcon.bin", 0 },
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",   "ibmcxcon.bin", DEFAULT_LOC "ibmcxcon.bin", 0 },
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",   "ibmencon.bin", DEFAULT_LOC "ibmencon.bin", 0 },
-
-{IBIOS, FAMILY,   T_PCXR, 0, NULL, "PCXR",     "xrbios.bin", DEFAULT_LOC "xrbios.bin", 0 },
-{IFEP,  FAMILY,   T_PCXR, 0,  NULL,  "PCXR",   "xrfep.bin", DEFAULT_LOC "xrfep.bin", 0  },
-
-{IBIOS, T_PCLITE,   SUBTYPE, 0, NULL, "X/em",  "sxbios.bin", DEFAULT_LOC "sxbios.bin", 0 },
-{IFEP,  T_PCLITE,   SUBTYPE, 0,  NULL,  "X/em",        "sxfep.bin", DEFAULT_LOC "sxfep.bin", 0  },
-
-{IBIOS, T_EPC,      T_PCIBUS, 0, NULL, "PCI",  "pcibios.bin", DEFAULT_LOC "pcibios.bin", 0 },
-{IFEP,  T_EPC,      T_PCIBUS, 0, NULL, "PCI",  "pcifep.bin", DEFAULT_LOC "pcifep.bin", 0 },
-{ICONFIG, 0,       0, 0, NULL,         NULL,   "dgap.conf",    "/etc/dgap.conf", 0 },
-
-/* IBAD/NULL entry indicating end-of-table */
-
-{IBAD,  0,     0, 0,  NULL,  NULL, NULL, NULL, 0 }
-
-} ;
-
-int    errorprint = 1;
-int    nodldprint = 1;
-int    debugflag;
-int    fd;
-
-struct downld_t *ip;   /* Image pointer in current image  */
-struct downld_t *dp;   /* conc. download */
-
-
-/*
- * The same for either the FEP or the BIOS.
- *  Append the downldio header, issue the ioctl, then free
- *  the buffer.  Not horribly CPU efficient, but quite RAM efficient.
- */
-
-void squirt(int req_type, int bdid, struct image_info *ii)
-{
-       struct downldio *dliop;
-       int size_buf;
-       int sfd;
-       struct stat sb;
-
-       /*
-        * If this binary comes from a file, stat it to see how
-        * large it is. Yes, we intentionally do this each
-        * time for the binary may change between loads.
-        */
-
-       if (ii->pathname) {
-               sfd = open(ii->pathname, O_RDONLY);
-
-               if (sfd < 0 ) {
-                       myperror(ii->pathname);
-                       goto squirt_end;
-               }
-
-               if (fstat(sfd, &sb) == -1 ) {
-                       myperror(ii->pathname);
-                       goto squirt_end;
-               }
-
-               ii->len = sb.st_size;
-       }
-
-       size_buf = ii->len + sizeof(struct downldio);
-
-       /*
-        * This buffer will be freed at the end of this function.  It is
-        * not resilient and should be around only long enough for the d/l
-        * to happen.
-        */
-       dliop = (struct downldio *) malloc(size_buf);
-
-       if (dliop == NULL) {
-               fprintf(stderr,"%s: can't get %d bytes of memory; aborting\n",
-                       pgm, size_buf);
-               exit (1);
-       }
-
-       /* Now, stick the image in fepimage.  This can come from either
-        *  the compiled-in image or from the filesystem.
-        */
-       if (ii->pathname)
-               read(sfd, dliop->image.fi.fepimage, ii->len);
-       else
-               memcpy(dliop ->image.fi.fepimage, ii->image, ii->len);
-
-       dliop->req_type = req_type;
-       dliop->bdid = bdid;
-
-       dliop->image.fi.len = ii->len;
-
-       if (debugflag)
-               printf("sending %d bytes of %s %s from %s\n",
-                       ii->len,
-                       (ii->type == IFEP) ? "FEP" : (ii->type == IBIOS) ? "BIOS" : "CONFIG",
-                       ii->name ? ii->name : "",
-                       (ii->pathname) ? ii->pathname : "internal image" );
-
-       if (ioctl(fd, DIGI_DLREQ_SET, (char *) dliop) == -1) {
-               if(errorprint) {
-                       fprintf(stderr,
-                               "%s: warning - download ioctl failed\n",pgm);
-                       errorprint = 0;
-               }
-               sleep(2);
-       }
-
-squirt_end:
-
-       if (ii->pathname) {
-               close(sfd);
-       }
-       free(dliop);
-}
-
-
-/*
- *  See if we need to reload the download image in core
- *
- */
-void consider_file_rescan(struct image_info *ii)
-{
-       int sfd;
-       int len;
-       struct stat     sb;
-
-       /* This operation only makes sense when we're working from a file */
-
-       if (ii->pathname) {
-
-               sfd = open (ii->pathname, O_RDONLY) ;
-               if (sfd < 0 ) {
-                       myperror(ii->pathname);
-                       exit(1) ;
-               }
-
-               if( fstat(sfd,&sb) == -1 ) {
-                       myperror(ii->pathname);
-                       exit(1);
-               }
-
-               /* If the file hasn't changed since we last did this,
-                * and we have not done a free() on the image, bail
-                */
-               if (ii->image && (sb.st_mtime == ii->mtime))
-                       goto end_rescan;
-
-               ii->len = len = sb.st_size;
-
-               /* Record the timestamp of the file */
-               ii->mtime = sb.st_mtime;
-
-               /* image should be NULL unless there is an image malloced
-                * in already.  Before we malloc again, make sure we don't
-                * have a memory leak.
-                */
-               if ( ii->image ) {
-                       free( ii->image );
-                       /* ii->image = NULL; */ /* not necessary */
-               }
-
-               /* This image will be kept only long enough for the
-                * download to happen.  After sending the last block,
-                * it will be freed
-                */
-               ii->image = malloc(len) ;
-
-               if (ii->image == NULL) {
-                       fprintf(stderr,
-                               "%s: can't get %d bytes of memory; aborting\n",
-                                pgm, len);
-                       exit (1);
-               }
-
-               if (read(sfd, ii->image, len) < len) {
-                       fprintf(stderr,"%s: read error on %s; aborting\n",
-                               pgm, ii->pathname);
-                       exit (1);
-               }
-
-end_rescan:
-               close(sfd);
-
-       }
-}
-
-/*
- * Scan for images to match the driver requests
- */
-
-struct image_info * find_conc_image()
-{
-       int x;
-       struct image_info *i = NULL;
-
-       for ( x = 0; x < nimages; x++ ) {
-               i=&image_list[x];
-
-               if(i->type != ICONC)
-                       continue;
-
-               consider_file_rescan(i) ;
-
-               ip = (struct downld_t *) image_list[x].image;
-               if (ip == NULL) continue;
-
-               /*
-                * When I removed Clusterport, I kept only the code that I
-                * was SURE wasn't ClusterPort.  We may not need the next two
-                * lines of code.
-                */
-               if ((dp->dl_type != 'P' ) && ( ip->dl_srev == dp->dl_srev ))
-                       return i;
-       }
-       return NULL;
-}
-
-
-int main(int argc, char **argv)
-{
-       struct downldio dlio;
-       int             offset, bsize;
-       int             x;
-       char            *down, *image, *fname;
-       struct image_info *ii;
-
-       pgm = argv[0];
-       dp = &dlio.image.dl;            /* conc. download */
-
-       while((argc > 2) && !strcmp(argv[1],"-d")) {
-               debugflag++ ;
-               argc-- ;
-               argv++ ;
-       }
-
-       if(argc < 2) {
-               fprintf(stderr,
-                       "usage: %s download-device [image-file] ...\n",
-                       pgm);
-               exit(1);
-       }
-
-
-
-       /*
-        * Daemonize, unless debugging is turned on.
-        */
-       if (debugflag == 0) {
-               switch (fork())
-               {
-               case 0:
-                       break;
-
-               case -1:
-                       return 1;
-
-               default:
-                       return 0;
-               }
-
-               setsid();
-
-               /*
-                * The child no longer needs "stdin", "stdout", or "stderr",
-                * and should not block processes waiting for them to close.
-                */
-               fclose(stdin);
-               fclose(stdout);
-               fclose(stderr);
-
-       }
-
-       while (1) {
-               if( (fd = open(argv[1], O_RDWR)) == -1 ) {
-                       sleep(1);
-               }
-               else
-                       break;
-       }
-
-       /*
-       ** create a list of images to search through when trying to match
-       ** requests from the driver.  Put images from the command line in
-       ** the list before built in images so that the command line images
-       ** can override the built in ones.
-       */
-
-       /* allocate space for the list */
-
-       nimages = argc - 2;
-
-       /* count the number of default list entries */
-
-       for (count = 0; images[count].type != IBAD; ++count) ;
-
-       nimages += count;
-
-       /* Really should just remove the variable "image_list".... robertl */
-       image_list = images;
-
-       /* get the images from the command line */
-       for(x = 2; x < argc; x++) {
-               int xx;
-
-               /*
-                * strip off any leading path information for
-                * determining file type
-                */
-               if( (fname = strrchr(argv[x],'/')) == NULL)
-                       fname = argv[x];
-               else
-                       fname++;        /* skip the slash */
-
-               for (xx = 0; xx < count; xx++) {
-                       if (strcmp(fname, images[xx].fname) == 0 ) {
-                               images[xx].pathname = argv[x];
-
-                               /* image should be NULL until */
-                               /* space is malloced */
-                               images[xx].image = NULL;
-                       }
-               }
-       }
-
-        sleep(3);
-
-       /*
-       ** Endless loop: get a request from the fep, and service that request.
-       */
-       for(;;) {
-               /* get the request */
-               if (debugflag)
-                       printf("b4 get ioctl...");
-
-               if (ioctl(fd,DIGI_DLREQ_GET, &dlio) == -1 ) {
-                       if (errorprint) {
-                               fprintf(stderr,
-                                       "%s: warning - download ioctl failed\n",
-                                       pgm);
-                               errorprint = 0;
-                       }
-                       sleep(2);
-               } else {
-                       if (debugflag)
-                               printf("dlio.req_type is %d bd %d\n",
-                                       dlio.req_type,dlio.bdid);
-
-                       switch(dlio.req_type) {
-                       case DLREQ_BIOS:
-                               /*
-                               ** find the bios image for this type
-                               */
-                               for ( x = 0; x < nimages; x++ ) {
-                                       if(image_list[x].type != IBIOS)
-                                               continue;
-
-                                       if ((dlio.image.fi.type & FAMILY) ==
-                                               image_list[x].family) {
-
-                                               if ( image_list[x].family == T_CX   ) {
-                                                       if ((dlio.image.fi.type & BUSTYPE)
-                                                               == T_PCIBUS ) {
-                                                               if ( image_list[x].subtype
-                                                                       == T_PCIBUS )
-                                                                       break;
-                                                       }
-                                                       else {
-                                                               break;
-                                                       }
-                                               }
-                                               else if ( image_list[x].family == T_EPC ) {
-                                               /* If subtype of image is T_PCIBUS, it is */
-                                               /* a PCI EPC image, so the board must */
-                                               /* have bus type T_PCIBUS to match */
-                                                       if ((dlio.image.fi.type & BUSTYPE)
-                                                               == T_PCIBUS ) {
-                                                               if ( image_list[x].subtype
-                                                                       == T_PCIBUS )
-                                                                       break;
-                                                       }
-                                                       else {
-                                                       /* NON PCI EPC doesn't use PCI image */
-                                                               if ( image_list[x].subtype
-                                                                       != T_PCIBUS )
-                                                                       break;
-                                                       }
-                                               }
-                                               else
-                                                       break;
-                                       }
-                                       else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
-                                               /* PCXR board will break out of the loop here */
-                                               if ( image_list[x].subtype == T_PCXR   ) {
-                                                                       break;
-                                               }
-                                       }
-                               }
-
-                               if ( x >= nimages) {
-                                       /*
-                                       ** no valid images exist
-                                       */
-                                       if(nodldprint) {
-                                               fprintf(stderr,
-                                               "%s: cannot find correct BIOS image\n",
-                                                       pgm);
-                                               nodldprint = 0;
-                                       }
-                                       dlio.image.fi.type = -1;
-                                       if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1) {
-                                               if (errorprint) {
-                                                       fprintf(stderr,
-                                                       "%s: warning - download ioctl failed\n",
-                                                       pgm);
-                                                       errorprint = 0;
-                                               }
-                                               sleep(2);
-                                       }
-                                       break;
-                               }
-                               squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-                               break ;
-
-                       case DLREQ_FEP:
-                               /*
-                               ** find the fep image for this type
-                               */
-                               for ( x = 0; x < nimages; x++ ) {
-                                       if(image_list[x].type != IFEP)
-                                               continue;
-                                       if( (dlio.image.fi.type & FAMILY) ==
-                                               image_list[x].family ) {
-                                               if ( image_list[x].family == T_CX   ) {
-                                                       /* C/X PCI board */
-                                                       if ((dlio.image.fi.type & BUSTYPE)
-                                                               == T_PCIBUS ) {
-                                                               if ( image_list[x].subtype
-                                                                       == T_PCIBUS )
-                                                                       break;
-                                                       }
-                                                       else {
-                                                       /* Regular CX */
-                                                               break;
-                                                       }
-                                               }
-                                               else if ( image_list[x].family == T_EPC   )  {
-                                               /* If subtype of image is T_PCIBUS, it is */
-                                               /* a PCI EPC image, so the board must */
-                                               /* have bus type T_PCIBUS to match */
-                                                       if ((dlio.image.fi.type & BUSTYPE)
-                                                               == T_PCIBUS ) {
-                                                               if ( image_list[x].subtype
-                                                                       == T_PCIBUS )
-                                                                       break;
-                                                       }
-                                                       else {
-                                                       /* NON PCI EPC doesn't use PCI image */
-                                                               if ( image_list[x].subtype
-                                                                       != T_PCIBUS )
-                                                                       break;
-                                                       }
-                                               }
-                                               else
-                                                       break;
-                                       }
-                                       else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
-                                               /* PCXR board will break out of the loop here */
-                                               if ( image_list[x].subtype == T_PCXR   ) {
-                                                                       break;
-                                               }
-                                       }
-                               }
-
-                               if ( x >= nimages) {
-                                       /*
-                                       ** no valid images exist
-                                       */
-                                       if(nodldprint) {
-                                               fprintf(stderr,
-                                               "%s: cannot find correct FEP image\n",
-                                                       pgm);
-                                               nodldprint = 0;
-                                       }
-                                       dlio.image.fi.type=-1;
-                                       if( ioctl(fd,DIGI_DLREQ_SET,&dlio) == -1 ) {
-                                               if(errorprint) {
-                                                       fprintf(stderr,
-                                               "%s: warning - download ioctl failed\n",
-                                                               pgm);
-                                                       errorprint=0;
-                                               }
-                                               sleep(2);
-                                       }
-                                       break;
-                               }
-                               squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-                               break;
-
-                       case DLREQ_DEVCREATE:
-                               {
-                                       char string[1024];
-#if 0
-                                       sprintf(string, "%s /proc/dgap/%d/mknod", DEFSHELL, dlio.bdid);
-#endif
-                                       sprintf(string, "%s /usr/sbin/dgap_updatedevs %d", DEFSHELL, dlio.bdid);
-                                       system(string);
-
-                                       if (debugflag)
-                                               printf("Created Devices.\n");
-                                       if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-                                               if(errorprint) {
-                                                       fprintf(stderr, "%s: warning - DEVCREATE ioctl failed\n",pgm);
-                                                       errorprint = 0;
-                                               }
-                                               sleep(2);
-                                       }
-                                       if (debugflag)
-                                               printf("After ioctl set - Created Device.\n");
-                               }
-
-                               break;
-
-                       case DLREQ_CONFIG:
-                               for ( x = 0; x < nimages; x++ ) {
-                                       if(image_list[x].type != ICONFIG)
-                                               continue;
-                                       else
-                                               break;
-                               }
-
-                               if ( x >= nimages) {
-                                       /*
-                                       ** no valid images exist
-                                       */
-                                       if(nodldprint) {
-                                               fprintf(stderr,
-                                               "%s: cannot find correct CONFIG image\n",
-                                                       pgm);
-                                               nodldprint = 0;
-                                       }
-                                       dlio.image.fi.type=-1;
-                                       if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-                                               if(errorprint) {
-                                                       fprintf(stderr,
-                                               "%s: warning - download ioctl failed\n",
-                                                               pgm);
-                                                       errorprint=0;
-                                               }
-                                               sleep(2);
-                                       }
-                                       break;
-                               }
-
-                               squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-                               break;
-
-                       case DLREQ_CONC:
-                               /*
-                               ** find the image needed for this download
-                               */
-                               if ( dp->dl_seq == 0 ) {
-                                       /*
-                                       ** find image for hardware rev range
-                                       */
-                                       for ( x = 0; x < nimages; x++ ) {
-                                               ii=&image_list[x];
-
-                                               if(image_list[x].type != ICONC)
-                                                       continue;
-
-                                               consider_file_rescan(ii) ;
-
-                                               ip = (struct downld_t *) image_list[x].image;
-                                               if (ip == NULL) continue;
-
-                                               /*
-                                                * When I removed Clusterport, I kept only the
-                                                * code that I was SURE wasn't ClusterPort.
-                                                * We may not need the next four lines of code.
-                                                */
-
-                                               if ((dp->dl_type != 'P' ) &&
-                                                (ip->dl_lrev <= dp->dl_lrev ) &&
-                                                ( dp->dl_lrev <= ip->dl_hrev))
-                                                       break;
-                                       }
-
-                                       if ( x >= nimages ) {
-                                               /*
-                                               ** No valid images exist
-                                               */
-                                               if(nodldprint) {
-                                                       fprintf(stderr,
-                                               "%s: cannot find correct download image %d\n",
-                                                               pgm, dp->dl_lrev);
-                                                       nodldprint=0;
-                                               }
-                                               continue;
-                                       }
-
-                               } else {
-                                       /*
-                                       ** find image version required
-                                       */
-                                       if ((ii = find_conc_image()) == NULL ) {
-                                               /*
-                                               ** No valid images exist
-                                               */
-                                               fprintf(stderr,
-                                               "%s: can't find rest of download image??\n",
-                                                       pgm);
-                                               continue;
-                                       }
-                               }
-
-                               /*
-                               ** download block of image
-                               */
-
-                               offset = 1024 * dp->dl_seq;
-
-                               /*
-                               ** test if block requested within image
-                               */
-                               if ( offset < ii->len ) {
-
-                                       /*
-                                       ** if it is, determine block size, set segment,
-                                       ** set size, set pointers, and copy block
-                                       */
-                                       if (( bsize = ii->len - offset ) > 1024 )
-                                               bsize = 1024;
-
-                                       /*
-                                       ** copy image version info to download area
-                                       */
-                                       dp->dl_srev = ip->dl_srev;
-                                       dp->dl_lrev = ip->dl_lrev;
-                                       dp->dl_hrev = ip->dl_hrev;
-
-                                       dp->dl_seg = (64 * dp->dl_seq) + ip->dl_seg;
-                                       dp->dl_size = bsize;
-
-                                       down = (char *)&dp->dl_data[0];
-                                       image = (char *)((char *)ip + offset);
-
-                                       memcpy(down, image, bsize);
-                               }
-                               else {
-                                       /*
-                                       ** Image has been downloaded, set segment and
-                                       ** size to indicate no more blocks
-                                       */
-                                       dp->dl_seg = ip->dl_seg;
-                                       dp->dl_size = 0;
-
-                                       /* Now, we can release the concentrator */
-                                       /* image from memory if we're running  */
-                                       /* from filesystem images */
-
-                                       if (ii->pathname)
-                                               if (ii->image) {
-                                                       free(ii->image);
-                                                       ii->image = NULL;
-                                               }
-                               }
-
-                               if (debugflag)
-                                               printf(
-                                               "sending conc dl section %d to %s from %s\n",
-                                                       dp->dl_seq, ii->name,
-                                               ii->pathname ? ii->pathname : "Internal Image");
-
-                               if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-                                       if (errorprint) {
-                                               fprintf(stderr,
-                                               "%s: warning - download ioctl failed\n",
-                                                       pgm);
-                                               errorprint=0;
-                                       }
-                                       sleep(2);
-                               }
-                               break;
-                       } /* switch */
-               }
-               if (debugflag > 1) {
-                       printf("pausing: "); fflush(stdout);
-                       fflush(stdin);
-                       while(getchar() != '\n');
-                               printf("continuing\n");
-               }
-       }
-}
-
-/*
-** myperror()
-**
-**  Same as normal perror(), but places the program name at the beginning
-**  of the message.
-*/
-void myperror(char *s)
-{
-       fprintf(stderr,"%s: %s: %s.\n",pgm, s, strerror(errno));
-}
diff --git a/drivers/staging/echo/TODO b/drivers/staging/echo/TODO
deleted file mode 100644 (file)
index 72a311a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
-       - send to lkml for review
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: Steve
-Underwood <steveu@coppice.org> and David Rowe <david@rowetel.com>
index ab3c0d4ba68ea333be160dc0ca8e578416358a8c..25bea0556c1e6a039c876c71b20fec1c38d112d1 100644 (file)
@@ -757,6 +757,7 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
        }
 
        /* if it is released, wait for the next touch via IRQ */
+       lradc->cur_plate = LRADC_TOUCH;
        mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
index 78319ad176cd2cecde6e0686e12cbc19f5c3ec52..c6e8ba7b3e4eaa26297c778101eb1063bebc60ce 100644 (file)
@@ -20,6 +20,7 @@ config DRM_IMX_FB_HELPER
 
 config DRM_IMX_PARALLEL_DISPLAY
        tristate "Support for parallel displays"
+       select DRM_PANEL
        depends on DRM_IMX
        select VIDEOMODE_HELPERS
 
index 4677585b5ad51287eba03f5b4238e545df31e880..129e3a3f59f100847231a90e2d8b7740ce4f4ce0 100644 (file)
@@ -1,12 +1,11 @@
 
-imxdrm-objs := imx-drm-core.o imx-fb.o
+imxdrm-objs := imx-drm-core.o
 
 obj-$(CONFIG_DRM_IMX) += imxdrm.o
 
 obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
 obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
-obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
 obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
 
 imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
index 236ed66f116a29fda3af7fc6764b506cacbef16a..6b91c8e67174c72bf1bb22d2929b4dfc9b37c41f 100644 (file)
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/component.h>
 #include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
-#include <linux/fb.h>
-#include <linux/module.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
 
 #define MAX_CRTC       4
 
-struct crtc_cookie {
-       void *cookie;
-       int id;
-       struct list_head list;
-};
+struct imx_drm_crtc;
 
 struct imx_drm_device {
        struct drm_device                       *drm;
-       struct device                           *dev;
-       struct list_head                        crtc_list;
-       struct list_head                        encoder_list;
-       struct list_head                        connector_list;
-       struct mutex                            mutex;
+       struct imx_drm_crtc                     *crtc[MAX_CRTC];
        int                                     pipes;
        struct drm_fbdev_cma                    *fbhelper;
 };
 
 struct imx_drm_crtc {
        struct drm_crtc                         *crtc;
-       struct list_head                        list;
-       struct imx_drm_device                   *imxdrm;
        int                                     pipe;
        struct imx_drm_crtc_helper_funcs        imx_drm_helper_funcs;
-       struct module                           *owner;
-       struct crtc_cookie                      cookie;
-};
-
-struct imx_drm_encoder {
-       struct drm_encoder                      *encoder;
-       struct list_head                        list;
-       struct module                           *owner;
-       struct list_head                        possible_crtcs;
+       void                                    *cookie;
+       int                                     id;
+       int                                     mux_id;
 };
 
-struct imx_drm_connector {
-       struct drm_connector                    *connector;
-       struct list_head                        list;
-       struct module                           *owner;
-};
+static int legacyfb_depth = 16;
+module_param(legacyfb_depth, int, 0444);
 
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
 {
@@ -76,69 +57,71 @@ EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
 
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
        struct imx_drm_device *imxdrm = drm->dev_private;
 
        if (imxdrm->fbhelper)
                drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
+#endif
 }
 
 static int imx_drm_driver_unload(struct drm_device *drm)
 {
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
        struct imx_drm_device *imxdrm = drm->dev_private;
+#endif
 
-       imx_drm_device_put();
+       drm_kms_helper_poll_fini(drm);
+
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+       if (imxdrm->fbhelper)
+               drm_fbdev_cma_fini(imxdrm->fbhelper);
+#endif
+
+       component_unbind_all(drm->dev, drm);
 
        drm_vblank_cleanup(drm);
-       drm_kms_helper_poll_fini(drm);
        drm_mode_config_cleanup(drm);
 
        return 0;
 }
 
-/*
- * We don't care at all for crtc numbers, but the core expects the
- * crtcs to be numbered
- */
-static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm,
-               int num)
+static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
 {
-       struct imx_drm_crtc *imx_drm_crtc;
+       struct imx_drm_device *imxdrm = crtc->dev->dev_private;
+       unsigned i;
+
+       for (i = 0; i < MAX_CRTC; i++)
+               if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
+                       return imxdrm->crtc[i];
 
-       list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list)
-               if (imx_drm_crtc->pipe == num)
-                       return imx_drm_crtc;
        return NULL;
 }
 
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
                u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
 {
-       struct imx_drm_device *imxdrm = crtc->dev->dev_private;
-       struct imx_drm_crtc *imx_crtc;
        struct imx_drm_crtc_helper_funcs *helper;
+       struct imx_drm_crtc *imx_crtc;
 
-       list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list)
-               if (imx_crtc->crtc == crtc)
-                       goto found;
+       imx_crtc = imx_drm_find_crtc(encoder->crtc);
+       if (!imx_crtc)
+               return -EINVAL;
 
-       return -EINVAL;
-found:
        helper = &imx_crtc->imx_drm_helper_funcs;
        if (helper->set_interface_pix_fmt)
-               return helper->set_interface_pix_fmt(crtc,
-                               encoder_type, interface_pix_fmt,
+               return helper->set_interface_pix_fmt(encoder->crtc,
+                               encoder->encoder_type, interface_pix_fmt,
                                hsync_pin, vsync_pin);
        return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
 
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
-               u32 interface_pix_fmt)
+int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
 {
-       return imx_drm_crtc_panel_format_pins(crtc, encoder_type,
-                                             interface_pix_fmt, 2, 3);
+       return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format);
 
 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
 {
@@ -161,10 +144,9 @@ EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
 static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
 {
        struct imx_drm_device *imxdrm = drm->dev_private;
-       struct imx_drm_crtc *imx_drm_crtc;
+       struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
        int ret;
 
-       imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
        if (!imx_drm_crtc)
                return -EINVAL;
 
@@ -180,9 +162,8 @@ static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
 static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
 {
        struct imx_drm_device *imxdrm = drm->dev_private;
-       struct imx_drm_crtc *imx_drm_crtc;
+       struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
 
-       imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
        if (!imx_drm_crtc)
                return;
 
@@ -215,172 +196,54 @@ static const struct file_operations imx_drm_driver_fops = {
        .llseek = noop_llseek,
 };
 
-static struct imx_drm_device *imx_drm_device;
-
-static struct imx_drm_device *__imx_drm_device(void)
+int imx_drm_connector_mode_valid(struct drm_connector *connector,
+       struct drm_display_mode *mode)
 {
-       return imx_drm_device;
+       return MODE_OK;
 }
+EXPORT_SYMBOL(imx_drm_connector_mode_valid);
 
-struct drm_device *imx_drm_device_get(void)
+void imx_drm_connector_destroy(struct drm_connector *connector)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct imx_drm_encoder *enc;
-       struct imx_drm_connector *con;
-       struct imx_drm_crtc *crtc;
-
-       list_for_each_entry(enc, &imxdrm->encoder_list, list) {
-               if (!try_module_get(enc->owner)) {
-                       dev_err(imxdrm->dev, "could not get module %s\n",
-                                       module_name(enc->owner));
-                       goto unwind_enc;
-               }
-       }
-
-       list_for_each_entry(con, &imxdrm->connector_list, list) {
-               if (!try_module_get(con->owner)) {
-                       dev_err(imxdrm->dev, "could not get module %s\n",
-                                       module_name(con->owner));
-                       goto unwind_con;
-               }
-       }
-
-       list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
-               if (!try_module_get(crtc->owner)) {
-                       dev_err(imxdrm->dev, "could not get module %s\n",
-                                       module_name(crtc->owner));
-                       goto unwind_crtc;
-               }
-       }
-
-       return imxdrm->drm;
-
-unwind_crtc:
-       list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
-               module_put(crtc->owner);
-unwind_con:
-       list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
-               module_put(con->owner);
-unwind_enc:
-       list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
-               module_put(enc->owner);
-
-       mutex_unlock(&imxdrm->mutex);
-
-       return NULL;
-
-}
-EXPORT_SYMBOL_GPL(imx_drm_device_get);
-
-void imx_drm_device_put(void)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct imx_drm_encoder *enc;
-       struct imx_drm_connector *con;
-       struct imx_drm_crtc *crtc;
-
-       mutex_lock(&imxdrm->mutex);
-
-       list_for_each_entry(crtc, &imxdrm->crtc_list, list)
-               module_put(crtc->owner);
-
-       list_for_each_entry(con, &imxdrm->connector_list, list)
-               module_put(con->owner);
-
-       list_for_each_entry(enc, &imxdrm->encoder_list, list)
-               module_put(enc->owner);
-
-       mutex_unlock(&imxdrm->mutex);
-}
-EXPORT_SYMBOL_GPL(imx_drm_device_put);
-
-static int drm_mode_group_reinit(struct drm_device *dev)
-{
-       struct drm_mode_group *group = &dev->primary->mode_group;
-       uint32_t *id_list = group->id_list;
-       int ret;
-
-       ret = drm_mode_group_init_legacy_group(dev, group);
-       if (ret < 0)
-               return ret;
-
-       kfree(id_list);
-       return 0;
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
 }
+EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
 
-/*
- * register an encoder to the drm core
- */
-static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
+void imx_drm_encoder_destroy(struct drm_encoder *encoder)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-
-       INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs);
-
-       drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
-                       imx_drm_encoder->encoder->funcs,
-                       imx_drm_encoder->encoder->encoder_type);
-
-       drm_mode_group_reinit(imxdrm->drm);
-
-       return 0;
+       drm_encoder_cleanup(encoder);
 }
+EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
 
-/*
- * unregister an encoder from the drm core
- */
-static void imx_drm_encoder_unregister(struct imx_drm_encoder
-               *imx_drm_encoder)
+static void imx_drm_output_poll_changed(struct drm_device *drm)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-
-       drm_encoder_cleanup(imx_drm_encoder->encoder);
-
-       drm_mode_group_reinit(imxdrm->drm);
-}
-
-/*
- * register a connector to the drm core
- */
-static int imx_drm_connector_register(
-               struct imx_drm_connector *imx_drm_connector)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-
-       drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
-                       imx_drm_connector->connector->funcs,
-                       imx_drm_connector->connector->connector_type);
-       drm_mode_group_reinit(imxdrm->drm);
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+       struct imx_drm_device *imxdrm = drm->dev_private;
 
-       return drm_sysfs_connector_add(imx_drm_connector->connector);
+       drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
+#endif
 }
 
-/*
- * unregister a connector from the drm core
- */
-static void imx_drm_connector_unregister(
-               struct imx_drm_connector *imx_drm_connector)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-
-       drm_sysfs_connector_remove(imx_drm_connector->connector);
-       drm_connector_cleanup(imx_drm_connector->connector);
-
-       drm_mode_group_reinit(imxdrm->drm);
-}
+static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
+       .fb_create = drm_fb_cma_create,
+       .output_poll_changed = imx_drm_output_poll_changed,
+};
 
 /*
- * Called by the CRTC driver when all CRTCs are registered. This
- * puts all the pieces together and initializes the driver.
- * Once this is called no more CRTCs can be registered since
- * the drm core has hardcoded the number of crtcs in several
- * places.
+ * Main DRM initialisation. This binds, initialises and registers
+ * with DRM the subcomponents of the driver.
  */
 static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
+       struct imx_drm_device *imxdrm;
+       struct drm_connector *connector;
        int ret;
 
+       imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL);
+       if (!imxdrm)
+               return -ENOMEM;
+
        imxdrm->drm = drm;
 
        drm->dev_private = imxdrm;
@@ -396,120 +259,123 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
         */
        drm->irq_enabled = true;
 
-       drm_mode_config_init(drm);
-       imx_drm_mode_config_init(drm);
-
-       mutex_lock(&imxdrm->mutex);
-
-       drm_kms_helper_poll_init(drm);
+       /*
+        * set max width and height as default value(4096x4096).
+        * this value would be used to check framebuffer size limitation
+        * at drm_mode_addfb().
+        */
+       drm->mode_config.min_width = 64;
+       drm->mode_config.min_height = 64;
+       drm->mode_config.max_width = 4096;
+       drm->mode_config.max_height = 4096;
+       drm->mode_config.funcs = &imx_drm_mode_config_funcs;
 
-       /* setup the grouping for the legacy output */
-       ret = drm_mode_group_init_legacy_group(drm,
-                       &drm->primary->mode_group);
-       if (ret)
-               goto err_kms;
+       drm_mode_config_init(drm);
 
        ret = drm_vblank_init(drm, MAX_CRTC);
        if (ret)
                goto err_kms;
 
        /*
-        * with vblank_disable_allowed = true, vblank interrupt will be disabled
-        * by drm timer once a current process gives up ownership of
-        * vblank event.(after drm_vblank_put function is called)
+        * with vblank_disable_allowed = true, vblank interrupt will be
+        * disabled by drm timer once a current process gives up ownership
+        * of vblank event. (after drm_vblank_put function is called)
         */
        drm->vblank_disable_allowed = true;
 
-       if (!imx_drm_device_get()) {
-               ret = -EINVAL;
+       platform_set_drvdata(drm->platformdev, drm);
+
+       /* Now try and bind all our sub-components */
+       ret = component_bind_all(drm->dev, drm);
+       if (ret)
                goto err_vblank;
+
+       /*
+        * All components are now added, we can publish the connector sysfs
+        * entries to userspace.  This will generate hotplug events and so
+        * userspace will expect to be able to access DRM at this point.
+        */
+       list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+               ret = drm_sysfs_connector_add(connector);
+               if (ret) {
+                       dev_err(drm->dev,
+                               "[CONNECTOR:%d:%s] drm_sysfs_connector_add failed: %d\n",
+                               connector->base.id,
+                               drm_get_connector_name(connector), ret);
+                       goto err_unbind;
+               }
        }
 
-       platform_set_drvdata(drm->platformdev, drm);
-       mutex_unlock(&imxdrm->mutex);
+       /*
+        * All components are now initialised, so setup the fb helper.
+        * The fb helper takes copies of key hardware information, so the
+        * crtcs/connectors/encoders must not change after this point.
+        */
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+       if (legacyfb_depth != 16 && legacyfb_depth != 32) {
+               dev_warn(drm->dev, "Invalid legacyfb_depth.  Defaulting to 16bpp\n");
+               legacyfb_depth = 16;
+       }
+       imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
+                               drm->mode_config.num_crtc, MAX_CRTC);
+       if (IS_ERR(imxdrm->fbhelper)) {
+               ret = PTR_ERR(imxdrm->fbhelper);
+               imxdrm->fbhelper = NULL;
+               goto err_unbind;
+       }
+#endif
+
+       drm_kms_helper_poll_init(drm);
+
        return 0;
 
+err_unbind:
+       component_unbind_all(drm->dev, drm);
 err_vblank:
        drm_vblank_cleanup(drm);
 err_kms:
-       drm_kms_helper_poll_fini(drm);
        drm_mode_config_cleanup(drm);
-       mutex_unlock(&imxdrm->mutex);
 
        return ret;
 }
 
-static void imx_drm_update_possible_crtcs(void)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct imx_drm_crtc *imx_drm_crtc;
-       struct imx_drm_encoder *enc;
-       struct crtc_cookie *cookie;
-
-       list_for_each_entry(enc, &imxdrm->encoder_list, list) {
-               u32 possible_crtcs = 0;
-
-               list_for_each_entry(cookie, &enc->possible_crtcs, list) {
-                       list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) {
-                               if (imx_drm_crtc->cookie.cookie == cookie->cookie &&
-                                               imx_drm_crtc->cookie.id == cookie->id) {
-                                       possible_crtcs |= 1 << imx_drm_crtc->pipe;
-                               }
-                       }
-               }
-               enc->encoder->possible_crtcs = possible_crtcs;
-               enc->encoder->possible_clones = possible_crtcs;
-       }
-}
-
 /*
  * imx_drm_add_crtc - add a new crtc
  *
  * The return value if !NULL is a cookie for the caller to pass to
  * imx_drm_remove_crtc later.
  */
-int imx_drm_add_crtc(struct drm_crtc *crtc,
+int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
                struct imx_drm_crtc **new_crtc,
                const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
-               struct module *owner, void *cookie, int id)
+               void *cookie, int id)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
+       struct imx_drm_device *imxdrm = drm->dev_private;
        struct imx_drm_crtc *imx_drm_crtc;
        int ret;
 
-       mutex_lock(&imxdrm->mutex);
-
        /*
         * The vblank arrays are dimensioned by MAX_CRTC - we can't
         * pass IDs greater than this to those functions.
         */
-       if (imxdrm->pipes >= MAX_CRTC) {
-               ret = -EINVAL;
-               goto err_busy;
-       }
+       if (imxdrm->pipes >= MAX_CRTC)
+               return -EINVAL;
 
-       if (imxdrm->drm->open_count) {
-               ret = -EBUSY;
-               goto err_busy;
-       }
+       if (imxdrm->drm->open_count)
+               return -EBUSY;
 
        imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
-       if (!imx_drm_crtc) {
-               ret = -ENOMEM;
-               goto err_alloc;
-       }
+       if (!imx_drm_crtc)
+               return -ENOMEM;
 
        imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
        imx_drm_crtc->pipe = imxdrm->pipes++;
-       imx_drm_crtc->cookie.cookie = cookie;
-       imx_drm_crtc->cookie.id = id;
-
+       imx_drm_crtc->cookie = cookie;
+       imx_drm_crtc->id = id;
+       imx_drm_crtc->mux_id = imx_drm_crtc->pipe;
        imx_drm_crtc->crtc = crtc;
-       imx_drm_crtc->imxdrm = imxdrm;
 
-       imx_drm_crtc->owner = owner;
-
-       list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list);
+       imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
 
        *new_crtc = imx_drm_crtc;
 
@@ -520,23 +386,14 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
        drm_crtc_helper_add(crtc,
                        imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
-       drm_crtc_init(imxdrm->drm, crtc,
+       drm_crtc_init(drm, crtc,
                        imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
 
-       drm_mode_group_reinit(imxdrm->drm);
-
-       imx_drm_update_possible_crtcs();
-
-       mutex_unlock(&imxdrm->mutex);
-
        return 0;
 
 err_register:
-       list_del(&imx_drm_crtc->list);
+       imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
        kfree(imx_drm_crtc);
-err_alloc:
-err_busy:
-       mutex_unlock(&imxdrm->mutex);
        return ret;
 }
 EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
@@ -546,17 +403,11 @@ EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
  */
 int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
 {
-       struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
-
-       mutex_lock(&imxdrm->mutex);
+       struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private;
 
        drm_crtc_cleanup(imx_drm_crtc->crtc);
 
-       list_del(&imx_drm_crtc->list);
-
-       drm_mode_group_reinit(imxdrm->drm);
-
-       mutex_unlock(&imxdrm->mutex);
+       imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
 
        kfree(imx_drm_crtc);
 
@@ -565,220 +416,78 @@ int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
 
 /*
- * imx_drm_add_encoder - add a new encoder
+ * Find the DRM CRTC possible mask for the device node cookie/id.
+ *
+ * The encoder possible masks are defined by their position in the
+ * mode_config crtc_list.  This means that CRTCs must not be added
+ * or removed once the DRM device has been fully initialised.
  */
-int imx_drm_add_encoder(struct drm_encoder *encoder,
-               struct imx_drm_encoder **newenc, struct module *owner)
+static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm,
+       void *cookie, int id)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct imx_drm_encoder *imx_drm_encoder;
-       int ret;
-
-       mutex_lock(&imxdrm->mutex);
-
-       if (imxdrm->drm->open_count) {
-               ret = -EBUSY;
-               goto err_busy;
-       }
+       unsigned i;
 
-       imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL);
-       if (!imx_drm_encoder) {
-               ret = -ENOMEM;
-               goto err_alloc;
+       for (i = 0; i < MAX_CRTC; i++) {
+               struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i];
+               if (imx_drm_crtc && imx_drm_crtc->id == id &&
+                   imx_drm_crtc->cookie == cookie)
+                       return drm_crtc_mask(imx_drm_crtc->crtc);
        }
 
-       imx_drm_encoder->encoder = encoder;
-       imx_drm_encoder->owner = owner;
-
-       ret = imx_drm_encoder_register(imx_drm_encoder);
-       if (ret) {
-               ret = -ENOMEM;
-               goto err_register;
-       }
-
-       list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
-
-       *newenc = imx_drm_encoder;
-
-       mutex_unlock(&imxdrm->mutex);
-
        return 0;
-
-err_register:
-       kfree(imx_drm_encoder);
-err_alloc:
-err_busy:
-       mutex_unlock(&imxdrm->mutex);
-
-       return ret;
 }
-EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
 
-int imx_drm_encoder_add_possible_crtcs(
-               struct imx_drm_encoder *imx_drm_encoder,
-               struct device_node *np)
+int imx_drm_encoder_parse_of(struct drm_device *drm,
+       struct drm_encoder *encoder, struct device_node *np)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct of_phandle_args args;
-       struct crtc_cookie *c;
-       int ret = 0;
-       int i;
-
-       if (!list_empty(&imx_drm_encoder->possible_crtcs))
-               return -EBUSY;
+       struct imx_drm_device *imxdrm = drm->dev_private;
+       uint32_t crtc_mask = 0;
+       int i, ret = 0;
 
        for (i = 0; !ret; i++) {
-               ret = of_parse_phandle_with_args(np, "crtcs",
-                               "#crtc-cells", i, &args);
-               if (ret < 0)
-                       break;
+               struct of_phandle_args args;
+               uint32_t mask;
+               int id;
 
-               c = kzalloc(sizeof(*c), GFP_KERNEL);
-               if (!c) {
-                       of_node_put(args.np);
-                       return -ENOMEM;
-               }
-
-               c->cookie = args.np;
-               c->id = args.args_count > 0 ? args.args[0] : 0;
+               ret = of_parse_phandle_with_args(np, "crtcs", "#crtc-cells", i,
+                                                &args);
+               if (ret == -ENOENT)
+                       break;
+               if (ret < 0)
+                       return ret;
 
+               id = args.args_count > 0 ? args.args[0] : 0;
+               mask = imx_drm_find_crtc_mask(imxdrm, args.np, id);
                of_node_put(args.np);
 
-               mutex_lock(&imxdrm->mutex);
+               /*
+                * If we failed to find the CRTC(s) which this encoder is
+                * supposed to be connected to, it's because the CRTC has
+                * not been registered yet.  Defer probing, and hope that
+                * the required CRTC is added later.
+                */
+               if (mask == 0)
+                       return -EPROBE_DEFER;
 
-               list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs);
-
-               mutex_unlock(&imxdrm->mutex);
+               crtc_mask |= mask;
        }
 
-       imx_drm_update_possible_crtcs();
+       encoder->possible_crtcs = crtc_mask;
 
-       return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs);
-
-int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder,
-               struct drm_crtc *crtc)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct imx_drm_crtc *imx_crtc;
-       int i = 0;
-
-       list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) {
-               if (imx_crtc->crtc == crtc)
-                       goto found;
-               i++;
-       }
-
-       return -EINVAL;
-found:
-       return i;
-}
-EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
-
-/*
- * imx_drm_remove_encoder - remove an encoder
- */
-int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct crtc_cookie *c, *tmp;
-
-       mutex_lock(&imxdrm->mutex);
-
-       imx_drm_encoder_unregister(imx_drm_encoder);
-
-       list_del(&imx_drm_encoder->list);
-
-       list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs,
-                       list)
-               kfree(c);
-
-       mutex_unlock(&imxdrm->mutex);
-
-       kfree(imx_drm_encoder);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
-
-/*
- * imx_drm_add_connector - add a connector
- */
-int imx_drm_add_connector(struct drm_connector *connector,
-               struct imx_drm_connector **new_con,
-               struct module *owner)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       struct imx_drm_connector *imx_drm_connector;
-       int ret;
-
-       mutex_lock(&imxdrm->mutex);
-
-       if (imxdrm->drm->open_count) {
-               ret = -EBUSY;
-               goto err_busy;
-       }
-
-       imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL);
-       if (!imx_drm_connector) {
-               ret = -ENOMEM;
-               goto err_alloc;
-       }
-
-       imx_drm_connector->connector = connector;
-       imx_drm_connector->owner = owner;
-
-       ret = imx_drm_connector_register(imx_drm_connector);
-       if (ret)
-               goto err_register;
-
-       list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
-
-       *new_con = imx_drm_connector;
-
-       mutex_unlock(&imxdrm->mutex);
+       /* FIXME: this is the mask of outputs which can clone this output. */
+       encoder->possible_clones = ~0;
 
        return 0;
-
-err_register:
-       kfree(imx_drm_connector);
-err_alloc:
-err_busy:
-       mutex_unlock(&imxdrm->mutex);
-
-       return ret;
 }
-EXPORT_SYMBOL_GPL(imx_drm_add_connector);
+EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
 
-void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper)
+int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder)
 {
-       struct imx_drm_device *imxdrm = __imx_drm_device();
+       struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc);
 
-       imxdrm->fbhelper = fbdev_helper;
+       return imx_crtc ? imx_crtc->mux_id : -EINVAL;
 }
-EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set);
-
-/*
- * imx_drm_remove_connector - remove a connector
- */
-int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-
-       mutex_lock(&imxdrm->mutex);
-
-       imx_drm_connector_unregister(imx_drm_connector);
-
-       list_del(&imx_drm_connector->list);
-
-       mutex_unlock(&imxdrm->mutex);
-
-       kfree(imx_drm_connector);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
+EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
 
 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
        /* none so far */
@@ -819,80 +528,103 @@ static struct drm_driver imx_drm_driver = {
        .patchlevel             = 0,
 };
 
-static int imx_drm_platform_probe(struct platform_device *pdev)
+static int compare_parent_of(struct device *dev, void *data)
 {
-       int ret;
-
-       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-       if (ret)
-               return ret;
-
-       imx_drm_device->dev = &pdev->dev;
-
-       return drm_platform_init(&imx_drm_driver, pdev);
+       struct of_phandle_args *args = data;
+       return dev->parent && dev->parent->of_node == args->np;
 }
 
-static int imx_drm_platform_remove(struct platform_device *pdev)
+static int compare_of(struct device *dev, void *data)
 {
-       drm_put_dev(platform_get_drvdata(pdev));
-
-       return 0;
+       return dev->of_node == data;
 }
 
-static struct platform_driver imx_drm_pdrv = {
-       .probe          = imx_drm_platform_probe,
-       .remove         = imx_drm_platform_remove,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "imx-drm",
-       },
-};
-
-static struct platform_device *imx_drm_pdev;
-
-static int __init imx_drm_init(void)
+static int imx_drm_add_components(struct device *master, struct master *m)
 {
+       struct device_node *np = master->of_node;
+       unsigned i;
        int ret;
 
-       imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
-       if (!imx_drm_device)
-               return -ENOMEM;
+       for (i = 0; ; i++) {
+               struct of_phandle_args args;
+
+               ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
+                                                      i, &args);
+               if (ret)
+                       break;
 
-       mutex_init(&imx_drm_device->mutex);
-       INIT_LIST_HEAD(&imx_drm_device->crtc_list);
-       INIT_LIST_HEAD(&imx_drm_device->connector_list);
-       INIT_LIST_HEAD(&imx_drm_device->encoder_list);
+               ret = component_master_add_child(m, compare_parent_of, &args);
+               of_node_put(args.np);
 
-       imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
-       if (IS_ERR(imx_drm_pdev)) {
-               ret = PTR_ERR(imx_drm_pdev);
-               goto err_pdev;
+               if (ret)
+                       return ret;
        }
 
-       ret = platform_driver_register(&imx_drm_pdrv);
-       if (ret)
-               goto err_pdrv;
+       for (i = 0; ; i++) {
+               struct device_node *node;
+
+               node = of_parse_phandle(np, "connectors", i);
+               if (!node)
+                       break;
+
+               ret = component_master_add_child(m, compare_of, node);
+               of_node_put(node);
 
+               if (ret)
+                       return ret;
+       }
        return 0;
+}
 
-err_pdrv:
-       platform_device_unregister(imx_drm_pdev);
-err_pdev:
-       kfree(imx_drm_device);
+static int imx_drm_bind(struct device *dev)
+{
+       return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
+}
 
-       return ret;
+static void imx_drm_unbind(struct device *dev)
+{
+       drm_put_dev(dev_get_drvdata(dev));
 }
 
-static void __exit imx_drm_exit(void)
+static const struct component_master_ops imx_drm_ops = {
+       .add_components = imx_drm_add_components,
+       .bind = imx_drm_bind,
+       .unbind = imx_drm_unbind,
+};
+
+static int imx_drm_platform_probe(struct platform_device *pdev)
 {
-       platform_device_unregister(imx_drm_pdev);
-       platform_driver_unregister(&imx_drm_pdrv);
+       int ret;
+
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
-       kfree(imx_drm_device);
+       return component_master_add(&pdev->dev, &imx_drm_ops);
 }
 
-module_init(imx_drm_init);
-module_exit(imx_drm_exit);
+static int imx_drm_platform_remove(struct platform_device *pdev)
+{
+       component_master_del(&pdev->dev, &imx_drm_ops);
+       return 0;
+}
+
+static const struct of_device_id imx_drm_dt_ids[] = {
+       { .compatible = "fsl,imx-drm", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
+
+static struct platform_driver imx_drm_pdrv = {
+       .probe          = imx_drm_platform_probe,
+       .remove         = imx_drm_platform_remove,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "imx-drm",
+               .of_match_table = imx_drm_dt_ids,
+       },
+};
+module_platform_driver(imx_drm_pdrv);
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX drm driver core");
index ae90c9c15312c2ca57fb1884b622a8bf0469cf0e..035ab6258ad08aa82b79dc5438ccfdcab45d7a36 100644 (file)
@@ -1,17 +1,15 @@
 #ifndef _IMX_DRM_H_
 #define _IMX_DRM_H_
 
-#include <linux/videodev2.h>
-
-#define IPU_PIX_FMT_GBR24      v4l2_fourcc('G', 'B', 'R', '3')
-
+struct device_node;
 struct drm_crtc;
 struct drm_connector;
 struct drm_device;
+struct drm_display_mode;
 struct drm_encoder;
-struct imx_drm_crtc;
 struct drm_fbdev_cma;
 struct drm_framebuffer;
+struct imx_drm_crtc;
 struct platform_device;
 
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
@@ -25,10 +23,10 @@ struct imx_drm_crtc_helper_funcs {
        const struct drm_crtc_funcs *crtc_funcs;
 };
 
-int imx_drm_add_crtc(struct drm_crtc *crtc,
+int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
                struct imx_drm_crtc **new_crtc,
                const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
-               struct module *owner, void *cookie, int id);
+               void *cookie, int id);
 int imx_drm_remove_crtc(struct imx_drm_crtc *);
 int imx_drm_init_drm(struct platform_device *pdev,
                int preferred_bpp);
@@ -38,35 +36,22 @@ int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc);
 void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc);
 void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc);
 
-struct imx_drm_encoder;
-int imx_drm_add_encoder(struct drm_encoder *encoder,
-               struct imx_drm_encoder **new_enc,
-               struct module *owner);
-int imx_drm_remove_encoder(struct imx_drm_encoder *);
-
-struct imx_drm_connector;
-int imx_drm_add_connector(struct drm_connector *connector,
-               struct imx_drm_connector **new_con,
-               struct module *owner);
-int imx_drm_remove_connector(struct imx_drm_connector *);
-
 void imx_drm_mode_config_init(struct drm_device *drm);
 
 struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
 
-struct drm_device *imx_drm_device_get(void);
-void imx_drm_device_put(void);
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
                u32 interface_pix_fmt, int hsync_pin, int vsync_pin);
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format(struct drm_encoder *encoder,
                u32 interface_pix_fmt);
-void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper);
 
-struct device_node;
+int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder);
+int imx_drm_encoder_parse_of(struct drm_device *drm,
+       struct drm_encoder *encoder, struct device_node *np);
 
-int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder,
-               struct drm_crtc *crtc);
-int imx_drm_encoder_add_possible_crtcs(struct imx_drm_encoder *imx_drm_encoder,
-               struct device_node *np);
+int imx_drm_connector_mode_valid(struct drm_connector *connector,
+       struct drm_display_mode *mode);
+void imx_drm_connector_destroy(struct drm_connector *connector);
+void imx_drm_encoder_destroy(struct drm_encoder *encoder);
 
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/staging/imx-drm/imx-fb.c b/drivers/staging/imx-drm/imx-fb.c
deleted file mode 100644 (file)
index 03a7b4e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * i.MX drm driver
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * 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.
- *
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "imx-drm.h"
-
-static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
-       .fb_create = drm_fb_cma_create,
-};
-
-void imx_drm_mode_config_init(struct drm_device *dev)
-{
-       dev->mode_config.min_width = 64;
-       dev->mode_config.min_height = 64;
-
-       /*
-        * set max width and height as default value(4096x4096).
-        * this value would be used to check framebuffer size limitation
-        * at drm_mode_addfb().
-        */
-       dev->mode_config.max_width = 4096;
-       dev->mode_config.max_height = 4096;
-
-       dev->mode_config.funcs = &imx_drm_mode_config_funcs;
-}
diff --git a/drivers/staging/imx-drm/imx-fbdev.c b/drivers/staging/imx-drm/imx-fbdev.c
deleted file mode 100644 (file)
index 8331739..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * i.MX drm driver
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * 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.
- *
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "imx-drm.h"
-
-#define MAX_CONNECTOR          4
-#define PREFERRED_BPP          16
-
-static struct drm_fbdev_cma *fbdev_cma;
-
-static int legacyfb_depth = 16;
-
-module_param(legacyfb_depth, int, 0444);
-
-static int __init imx_fb_helper_init(void)
-{
-       struct drm_device *drm = imx_drm_device_get();
-
-       if (!drm)
-               return -EINVAL;
-
-       if (legacyfb_depth != 16 && legacyfb_depth != 32) {
-               pr_warn("i.MX legacyfb: invalid legacyfb_depth setting. defaulting to 16bpp\n");
-               legacyfb_depth = 16;
-       }
-
-       fbdev_cma = drm_fbdev_cma_init(drm, legacyfb_depth,
-                       drm->mode_config.num_crtc, MAX_CONNECTOR);
-
-       if (IS_ERR(fbdev_cma)) {
-               imx_drm_device_put();
-               return PTR_ERR(fbdev_cma);
-       }
-
-       imx_drm_fb_helper_set(fbdev_cma);
-
-       return 0;
-}
-
-static void __exit imx_fb_helper_exit(void)
-{
-       imx_drm_fb_helper_set(NULL);
-       drm_fbdev_cma_fini(fbdev_cma);
-       imx_drm_device_put();
-}
-
-late_initcall(imx_fb_helper_init);
-module_exit(imx_fb_helper_exit);
-
-MODULE_DESCRIPTION("Freescale i.MX legacy fb driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
index f1aa48cb500f0e6b9ce517ab0e0952f6f1bde645..8384ceab932ae61109946bfccc7cf8c5a9eab3a9 100644 (file)
@@ -12,6 +12,7 @@
  * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  */
 
+#include <linux/component.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -112,15 +113,15 @@ struct hdmi_data_info {
 
 struct imx_hdmi {
        struct drm_connector connector;
-       struct imx_drm_connector *imx_drm_connector;
        struct drm_encoder encoder;
-       struct imx_drm_encoder *imx_drm_encoder;
 
        enum imx_hdmi_devtype dev_type;
        struct device *dev;
        struct clk *isfr_clk;
        struct clk *iahb_clk;
 
+       enum drm_connector_status connector_status;
+
        struct hdmi_data_info hdmi_data;
        int vic;
 
@@ -134,7 +135,6 @@ struct imx_hdmi {
        struct i2c_adapter *ddc;
        void __iomem *regs;
 
-       unsigned long pixel_clk_rate;
        unsigned int sample_rate;
        int ratio;
 };
@@ -156,37 +156,34 @@ static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset)
        return readb(hdmi->regs + offset);
 }
 
+static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+{
+       u8 val = hdmi_readb(hdmi, reg) & ~mask;
+       val |= data & mask;
+       hdmi_writeb(hdmi, val, reg);
+}
+
 static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
                      u8 shift, u8 mask)
 {
-       u8 value = hdmi_readb(hdmi, reg) & ~mask;
-       value |= (data << shift) & mask;
-       hdmi_writeb(hdmi, value, reg);
+       hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
 static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
                                         unsigned int value)
 {
-       u8 val;
-
        hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
        hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
        hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
 
        /* nshift factor = 0 */
-       val = hdmi_readb(hdmi, HDMI_AUD_CTS3);
-       val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK;
-       hdmi_writeb(hdmi, val, HDMI_AUD_CTS3);
+       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
 }
 
 static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
 {
-       u8 val;
-
        /* Must be set/cleared first */
-       val = hdmi_readb(hdmi, HDMI_AUD_CTS3);
-       val &= ~HDMI_AUD_CTS3_CTS_MANUAL;
-       hdmi_writeb(hdmi, val, HDMI_AUD_CTS3);
+       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
        hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
        hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
@@ -331,34 +328,25 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
                return (cts * ratio) / 100;
 }
 
-static void hdmi_get_pixel_clk(struct imx_hdmi *hdmi)
-{
-       unsigned long rate;
-
-       rate = 65000000; /* FIXME */
-
-       if (rate)
-               hdmi->pixel_clk_rate = rate;
-}
-
-static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi)
+static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
+       unsigned long pixel_clk)
 {
        unsigned int clk_n, clk_cts;
 
-       clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate,
+       clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
                               hdmi->ratio);
-       clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate,
+       clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
                                   hdmi->ratio);
 
        if (!clk_cts) {
                dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-                        __func__, hdmi->pixel_clk_rate);
+                        __func__, pixel_clk);
                return;
        }
 
        dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
                __func__, hdmi->sample_rate, hdmi->ratio,
-               hdmi->pixel_clk_rate, clk_n, clk_cts);
+               pixel_clk, clk_n, clk_cts);
 
        hdmi_set_clock_regenerator_n(hdmi, clk_n);
        hdmi_regenerate_cts(hdmi, clk_cts);
@@ -366,32 +354,12 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi)
 
 static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
 {
-       unsigned int clk_n, clk_cts;
-
-       clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate,
-                              hdmi->ratio);
-       clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate,
-                                  hdmi->ratio);
-
-       if (!clk_cts) {
-               dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-                        __func__, hdmi->pixel_clk_rate);
-               return;
-       }
-
-       dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
-               __func__, hdmi->sample_rate, hdmi->ratio,
-               hdmi->pixel_clk_rate, clk_n, clk_cts);
-
-       hdmi_set_clock_regenerator_n(hdmi, clk_n);
-       hdmi_regenerate_cts(hdmi, clk_cts);
+       hdmi_set_clk_regenerator(hdmi, 74250000);
 }
 
 static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi)
 {
-       /* Get pixel clock from ipu */
-       hdmi_get_pixel_clk(hdmi);
-       hdmi_set_clk_regenerator(hdmi);
+       hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
 }
 
 /*
@@ -485,8 +453,8 @@ static int is_color_space_interpolation(struct imx_hdmi *hdmi)
 static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
 {
        const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
+       unsigned i;
        u32 csc_scale = 1;
-       u8 val;
 
        if (is_color_space_conversion(hdmi)) {
                if (hdmi->hdmi_data.enc_out_format == RGB) {
@@ -503,37 +471,22 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
                }
        }
 
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][0] & 0xff), HDMI_CSC_COEF_A1_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][0] >> 8), HDMI_CSC_COEF_A1_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][1] & 0xff), HDMI_CSC_COEF_A2_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][1] >> 8), HDMI_CSC_COEF_A2_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][2] & 0xff), HDMI_CSC_COEF_A3_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][2] >> 8), HDMI_CSC_COEF_A3_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][3] & 0xff), HDMI_CSC_COEF_A4_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[0][3] >> 8), HDMI_CSC_COEF_A4_MSB);
-
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][0] & 0xff), HDMI_CSC_COEF_B1_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][0] >> 8), HDMI_CSC_COEF_B1_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][1] & 0xff), HDMI_CSC_COEF_B2_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][1] >> 8), HDMI_CSC_COEF_B2_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][2] & 0xff), HDMI_CSC_COEF_B3_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][2] >> 8), HDMI_CSC_COEF_B3_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][3] & 0xff), HDMI_CSC_COEF_B4_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[1][3] >> 8), HDMI_CSC_COEF_B4_MSB);
-
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][0] & 0xff), HDMI_CSC_COEF_C1_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][0] >> 8), HDMI_CSC_COEF_C1_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][1] & 0xff), HDMI_CSC_COEF_C2_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][1] >> 8), HDMI_CSC_COEF_C2_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][2] & 0xff), HDMI_CSC_COEF_C3_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][2] >> 8), HDMI_CSC_COEF_C3_MSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][3] & 0xff), HDMI_CSC_COEF_C4_LSB);
-       hdmi_writeb(hdmi, ((*csc_coeff)[2][3] >> 8), HDMI_CSC_COEF_C4_MSB);
-
-       val = hdmi_readb(hdmi, HDMI_CSC_SCALE);
-       val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK;
-       val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK;
-       hdmi_writeb(hdmi, val, HDMI_CSC_SCALE);
+       /* The CSC registers are sequential, alternating MSB then LSB */
+       for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
+               u16 coeff_a = (*csc_coeff)[0][i];
+               u16 coeff_b = (*csc_coeff)[1][i];
+               u16 coeff_c = (*csc_coeff)[2][i];
+
+               hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
+               hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
+               hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
+               hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
+               hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
+               hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
+       }
+
+       hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+                 HDMI_CSC_SCALE);
 }
 
 static void hdmi_video_csc(struct imx_hdmi *hdmi)
@@ -541,7 +494,6 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
        int color_depth = 0;
        int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
        int decimation = 0;
-       u8 val;
 
        /* YCC422 interpolation to 444 mode */
        if (is_color_space_interpolation(hdmi))
@@ -562,10 +514,8 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
 
        /* Configure the CSC registers */
        hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
-       val = hdmi_readb(hdmi, HDMI_CSC_SCALE);
-       val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK;
-       val |= color_depth;
-       hdmi_writeb(hdmi, val, HDMI_CSC_SCALE);
+       hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
+                 HDMI_CSC_SCALE);
 
        imx_hdmi_update_csc_coeffs(hdmi);
 }
@@ -581,7 +531,7 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
        unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
        unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
        struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
-       u8 val;
+       u8 val, vp_conf;
 
        if (hdmi_data->enc_out_format == RGB
                || hdmi_data->enc_out_format == YCBCR444) {
@@ -620,107 +570,75 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
                HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
        hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
 
-       val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-       val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
-       val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
-       hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+       hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
+                 HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
 
        /* Data from pixel repeater block */
        if (hdmi_data->pix_repet_factor > 1) {
-               val = hdmi_readb(hdmi, HDMI_VP_CONF);
-               val &= ~(HDMI_VP_CONF_PR_EN_MASK |
-                       HDMI_VP_CONF_BYPASS_SELECT_MASK);
-               val |= HDMI_VP_CONF_PR_EN_ENABLE |
-                       HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
-               hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+               vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
+                         HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
        } else { /* data from packetizer block */
-               val = hdmi_readb(hdmi, HDMI_VP_CONF);
-               val &= ~(HDMI_VP_CONF_PR_EN_MASK |
-                       HDMI_VP_CONF_BYPASS_SELECT_MASK);
-               val |= HDMI_VP_CONF_PR_EN_DISABLE |
-                       HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
-               hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+               vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+                         HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
        }
 
-       val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-       val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
-       val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
-       hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+       hdmi_modb(hdmi, vp_conf,
+                 HDMI_VP_CONF_PR_EN_MASK |
+                 HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
+
+       hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
+                 HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
 
        hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
 
        if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
-               val = hdmi_readb(hdmi, HDMI_VP_CONF);
-               val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-                       HDMI_VP_CONF_PP_EN_ENMASK |
-                       HDMI_VP_CONF_YCC422_EN_MASK);
-               val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
-                       HDMI_VP_CONF_PP_EN_ENABLE |
-                       HDMI_VP_CONF_YCC422_EN_DISABLE;
-               hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+               vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+                         HDMI_VP_CONF_PP_EN_ENABLE |
+                         HDMI_VP_CONF_YCC422_EN_DISABLE;
        } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
-               val = hdmi_readb(hdmi, HDMI_VP_CONF);
-               val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-                       HDMI_VP_CONF_PP_EN_ENMASK |
-                       HDMI_VP_CONF_YCC422_EN_MASK);
-               val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
-                       HDMI_VP_CONF_PP_EN_DISABLE |
-                       HDMI_VP_CONF_YCC422_EN_ENABLE;
-               hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+               vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+                         HDMI_VP_CONF_PP_EN_DISABLE |
+                         HDMI_VP_CONF_YCC422_EN_ENABLE;
        } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
-               val = hdmi_readb(hdmi, HDMI_VP_CONF);
-               val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-                       HDMI_VP_CONF_PP_EN_ENMASK |
-                       HDMI_VP_CONF_YCC422_EN_MASK);
-               val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
-                       HDMI_VP_CONF_PP_EN_DISABLE |
-                       HDMI_VP_CONF_YCC422_EN_DISABLE;
-               hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+               vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+                         HDMI_VP_CONF_PP_EN_DISABLE |
+                         HDMI_VP_CONF_YCC422_EN_DISABLE;
        } else {
                return;
        }
 
-       val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-       val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
-               HDMI_VP_STUFF_YCC422_STUFFING_MASK);
-       val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
-               HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
-       hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+       hdmi_modb(hdmi, vp_conf,
+                 HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
+                 HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
+
+       hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+                       HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
+                 HDMI_VP_STUFF_PP_STUFFING_MASK |
+                 HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
 
-       val = hdmi_readb(hdmi, HDMI_VP_CONF);
-       val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
-       val |= output_select;
-       hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+       hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+                 HDMI_VP_CONF);
 }
 
 static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
                                                unsigned char bit)
 {
-       u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-       val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
-       val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
-               HDMI_PHY_TST0_TSTCLR_MASK;
-       hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
+                 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
                                                unsigned char bit)
 {
-       u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-       val &= ~HDMI_PHY_TST0_TSTEN_MASK;
-       val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) &
-               HDMI_PHY_TST0_TSTEN_MASK;
-       hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
+                 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
                                                unsigned char bit)
 {
-       u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-       val &= ~HDMI_PHY_TST0_TSTCLK_MASK;
-       val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) &
-               HDMI_PHY_TST0_TSTCLK_MASK;
-       hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
+                 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
@@ -811,19 +729,94 @@ static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable)
                         HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+enum {
+       RES_8,
+       RES_10,
+       RES_12,
+       RES_MAX,
+};
+
+struct mpll_config {
+       unsigned long mpixelclock;
+       struct {
+               u16 cpce;
+               u16 gmp;
+       } res[RES_MAX];
+};
+
+static const struct mpll_config mpll_config[] = {
+       {
+               45250000, {
+                       { 0x01e0, 0x0000 },
+                       { 0x21e1, 0x0000 },
+                       { 0x41e2, 0x0000 }
+               },
+       }, {
+               92500000, {
+                       { 0x0140, 0x0005 },
+                       { 0x2141, 0x0005 },
+                       { 0x4142, 0x0005 },
+               },
+       }, {
+               148500000, {
+                       { 0x00a0, 0x000a },
+                       { 0x20a1, 0x000a },
+                       { 0x40a2, 0x000a },
+               },
+       }, {
+               ~0UL, {
+                       { 0x00a0, 0x000a },
+                       { 0x2001, 0x000f },
+                       { 0x4002, 0x000f },
+               },
+       }
+};
+
+struct curr_ctrl {
+       unsigned long mpixelclock;
+       u16 curr[RES_MAX];
+};
+
+static const struct curr_ctrl curr_ctrl[] = {
+       /*      pixelclk     bpp8    bpp10   bpp12 */
+       {
+                54000000, { 0x091c, 0x091c, 0x06dc },
+       }, {
+                58400000, { 0x091c, 0x06dc, 0x06dc },
+       }, {
+                72000000, { 0x06dc, 0x06dc, 0x091c },
+       }, {
+                74250000, { 0x06dc, 0x0b5c, 0x091c },
+       }, {
+               118800000, { 0x091c, 0x091c, 0x06dc },
+       }, {
+               216000000, { 0x06dc, 0x0b5c, 0x091c },
+       }
+};
+
 static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
                              unsigned char res, int cscon)
 {
+       unsigned res_idx, i;
        u8 val, msec;
 
-       /* color resolution 0 is 8 bit colour depth */
-       if (!res)
-               res = 8;
-
        if (prep)
                return -EINVAL;
-       else if (res != 8 && res != 12)
+
+       switch (res) {
+       case 0: /* color resolution 0 is 8 bit colour depth */
+       case 8:
+               res_idx = RES_8;
+               break;
+       case 10:
+               res_idx = RES_10;
+               break;
+       case 12:
+               res_idx = RES_12;
+               break;
+       default:
                return -EINVAL;
+       }
 
        /* Enable csc path */
        if (cscon)
@@ -850,165 +843,30 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
                        HDMI_PHY_I2CM_SLAVE_ADDR);
        hdmi_phy_test_clear(hdmi, 0);
 
-       if (hdmi->hdmi_data.video_mode.mpixelclock <= 45250000) {
-               switch (res) {
-               case 8:
-                       /* PLL/MPLL Cfg */
-                       hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);  /* GMPCTRL */
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x21e1, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x41e2, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 92500000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x2141, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x4142, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 148500000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
+       /* PLL/MPLL Cfg - always match on final entry */
+       for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
+               if (hdmi->hdmi_data.video_mode.mpixelclock <=
+                   mpll_config[i].mpixelclock)
                        break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x20a1, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x40a2, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-               default:
-                       return -EINVAL;
-               }
-       } else {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x2001, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x4002, 0x06);
-                       hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
-               default:
-                       return -EINVAL;
-               }
-       }
 
-       if (hdmi->hdmi_data.video_mode.mpixelclock <= 54000000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);  /* CURRCTRL */
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 58400000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 72000000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 74250000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 118800000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 216000000) {
-               switch (res) {
-               case 8:
-                       hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-                       break;
-               case 10:
-                       hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
-                       break;
-               case 12:
-                       hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+       hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
+       hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+
+       for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
+               if (hdmi->hdmi_data.video_mode.mpixelclock <=
+                   curr_ctrl[i].mpixelclock)
                        break;
-               default:
-                       return -EINVAL;
-               }
-       } else {
+
+       if (i >= ARRAY_SIZE(curr_ctrl)) {
                dev_err(hdmi->dev,
                                "Pixel clock %d - unsupported by HDMI\n",
                                hdmi->hdmi_data.video_mode.mpixelclock);
                return -EINVAL;
        }
 
+       /* CURRCTRL */
+       hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+
        hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
        hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
        /* RESISTANCE TERM 133Ohm Cfg */
@@ -1077,7 +935,7 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
 
 static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
 {
-       u8 de, val;
+       u8 de;
 
        if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
                de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
@@ -1085,20 +943,13 @@ static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
                de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
 
        /* disable rx detect */
-       val = hdmi_readb(hdmi, HDMI_A_HDCPCFG0);
-       val &= HDMI_A_HDCPCFG0_RXDETECT_MASK;
-       val |= HDMI_A_HDCPCFG0_RXDETECT_DISABLE;
-       hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG0);
+       hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
+                 HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
 
-       val = hdmi_readb(hdmi, HDMI_A_VIDPOLCFG);
-       val &= HDMI_A_VIDPOLCFG_DATAENPOL_MASK;
-       val |= de;
-       hdmi_writeb(hdmi, val, HDMI_A_VIDPOLCFG);
+       hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
 
-       val = hdmi_readb(hdmi, HDMI_A_HDCPCFG1);
-       val &= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK;
-       val |= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE;
-       hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG1);
+       hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
+                 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
 }
 
 static void hdmi_config_AVI(struct imx_hdmi *hdmi)
@@ -1322,11 +1173,7 @@ static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
 
 static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
 {
-       u8 clkdis;
-
-       clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS);
-       clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
-       hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+       hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
 }
 
 /* Workaround to clear the overflow condition */
@@ -1461,9 +1308,6 @@ static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi)
        /* Clear Hotplug interrupts */
        hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
 
-       /* Unmute interrupts */
-       hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
-
        return 0;
 }
 
@@ -1532,12 +1376,9 @@ static void imx_hdmi_poweroff(struct imx_hdmi *hdmi)
 static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
                                                        *connector, bool force)
 {
-       /* FIXME */
-       return connector_status_connected;
-}
-
-static void imx_hdmi_connector_destroy(struct drm_connector *connector)
-{
+       struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+                                            connector);
+       return hdmi->connector_status;
 }
 
 static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1565,13 +1406,6 @@ static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
        return 0;
 }
 
-static int imx_hdmi_connector_mode_valid(struct drm_connector *connector,
-                         struct drm_display_mode *mode)
-{
-
-       return MODE_OK;
-}
-
 static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
                                                           *connector)
 {
@@ -1619,28 +1453,21 @@ static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder)
        struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
 
        imx_hdmi_poweroff(hdmi);
-       imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE,
-                                 V4L2_PIX_FMT_RGB24);
+       imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24);
 }
 
 static void imx_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
        struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
-       int mux = imx_drm_encoder_get_mux_id(hdmi->imx_drm_encoder,
-                                            encoder->crtc);
+       int mux = imx_drm_encoder_get_mux_id(encoder);
 
        imx_hdmi_set_ipu_di_mux(hdmi, mux);
 
        imx_hdmi_poweron(hdmi);
 }
 
-static void imx_hdmi_encoder_destroy(struct drm_encoder *encoder)
-{
-       return;
-}
-
 static struct drm_encoder_funcs imx_hdmi_encoder_funcs = {
-       .destroy = imx_hdmi_encoder_destroy,
+       .destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = {
@@ -1656,21 +1483,32 @@ static struct drm_connector_funcs imx_hdmi_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = imx_hdmi_connector_detect,
-       .destroy = imx_hdmi_connector_destroy,
+       .destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
        .get_modes = imx_hdmi_connector_get_modes,
-       .mode_valid = imx_hdmi_connector_mode_valid,
+       .mode_valid = imx_drm_connector_mode_valid,
        .best_encoder = imx_hdmi_connector_best_encoder,
 };
 
+static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id)
+{
+       struct imx_hdmi *hdmi = dev_id;
+       u8 intr_stat;
+
+       intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
+       if (intr_stat)
+               hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+       return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
+}
+
 static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
 {
        struct imx_hdmi *hdmi = dev_id;
        u8 intr_stat;
        u8 phy_int_pol;
-       u8 val;
 
        intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
 
@@ -1680,55 +1518,46 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
                if (phy_int_pol & HDMI_PHY_HPD) {
                        dev_dbg(hdmi->dev, "EVENT=plugin\n");
 
-                       val = hdmi_readb(hdmi, HDMI_PHY_POL0);
-                       val &= ~HDMI_PHY_HPD;
-                       hdmi_writeb(hdmi, val, HDMI_PHY_POL0);
+                       hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
 
+                       hdmi->connector_status = connector_status_connected;
                        imx_hdmi_poweron(hdmi);
                } else {
                        dev_dbg(hdmi->dev, "EVENT=plugout\n");
 
-                       val = hdmi_readb(hdmi, HDMI_PHY_POL0);
-                       val |= HDMI_PHY_HPD;
-                       hdmi_writeb(hdmi, val, HDMI_PHY_POL0);
+                       hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, HDMI_PHY_POL0);
 
+                       hdmi->connector_status = connector_status_disconnected;
                        imx_hdmi_poweroff(hdmi);
                }
+               drm_helper_hpd_irq_event(hdmi->connector.dev);
        }
 
        hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
+       hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
        return IRQ_HANDLED;
 }
 
-static int imx_hdmi_register(struct imx_hdmi *hdmi)
+static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi)
 {
        int ret;
 
-       hdmi->connector.funcs = &imx_hdmi_connector_funcs;
-       hdmi->encoder.funcs = &imx_hdmi_encoder_funcs;
+       ret = imx_drm_encoder_parse_of(drm, &hdmi->encoder,
+                                      hdmi->dev->of_node);
+       if (ret)
+               return ret;
 
-       hdmi->encoder.encoder_type = DRM_MODE_ENCODER_TMDS;
-       hdmi->connector.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+       hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
        drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
-       ret = imx_drm_add_encoder(&hdmi->encoder, &hdmi->imx_drm_encoder,
-                       THIS_MODULE);
-       if (ret) {
-               dev_err(hdmi->dev, "adding encoder failed: %d\n", ret);
-               return ret;
-       }
+       drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
+                        DRM_MODE_ENCODER_TMDS);
 
        drm_connector_helper_add(&hdmi->connector,
                        &imx_hdmi_connector_helper_funcs);
-
-       ret = imx_drm_add_connector(&hdmi->connector,
-                       &hdmi->imx_drm_connector, THIS_MODULE);
-       if (ret) {
-               imx_drm_remove_encoder(hdmi->imx_drm_encoder);
-               dev_err(hdmi->dev, "adding connector failed: %d\n", ret);
-               return ret;
-       }
+       drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
+                          DRM_MODE_CONNECTOR_HDMIA);
 
        hdmi->connector.encoder = &hdmi->encoder;
 
@@ -1755,21 +1584,26 @@ static const struct of_device_id imx_hdmi_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
 
-static int imx_hdmi_platform_probe(struct platform_device *pdev)
+static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        const struct of_device_id *of_id =
-                               of_match_device(imx_hdmi_dt_ids, &pdev->dev);
-       struct device_node *np = pdev->dev.of_node;
+                               of_match_device(imx_hdmi_dt_ids, dev);
+       struct drm_device *drm = data;
+       struct device_node *np = dev->of_node;
        struct device_node *ddc_node;
        struct imx_hdmi *hdmi;
        struct resource *iores;
        int ret, irq;
 
-       hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+       hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
        if (!hdmi)
                return -ENOMEM;
 
-       hdmi->dev = &pdev->dev;
+       hdmi->dev = dev;
+       hdmi->connector_status = connector_status_disconnected;
+       hdmi->sample_rate = 48000;
+       hdmi->ratio = 100;
 
        if (of_id) {
                const struct platform_device_id *device_id = of_id->data;
@@ -1791,13 +1625,14 @@ static int imx_hdmi_platform_probe(struct platform_device *pdev)
        if (irq < 0)
                return -EINVAL;
 
-       ret = devm_request_irq(&pdev->dev, irq, imx_hdmi_irq, 0,
-                              dev_name(&pdev->dev), hdmi);
+       ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq,
+                                       imx_hdmi_irq, IRQF_SHARED,
+                                       dev_name(dev), hdmi);
        if (ret)
                return ret;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hdmi->regs = devm_ioremap_resource(&pdev->dev, iores);
+       hdmi->regs = devm_ioremap_resource(dev, iores);
        if (IS_ERR(hdmi->regs))
                return PTR_ERR(hdmi->regs);
 
@@ -1836,7 +1671,7 @@ static int imx_hdmi_platform_probe(struct platform_device *pdev)
        }
 
        /* Product and revision IDs */
-       dev_info(&pdev->dev,
+       dev_info(dev,
                "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
                hdmi_readb(hdmi, HDMI_DESIGN_ID),
                hdmi_readb(hdmi, HDMI_REVISION_ID),
@@ -1864,13 +1699,14 @@ static int imx_hdmi_platform_probe(struct platform_device *pdev)
        if (ret)
                goto err_iahb;
 
-       ret = imx_hdmi_register(hdmi);
+       ret = imx_hdmi_register(drm, hdmi);
        if (ret)
                goto err_iahb;
 
-       imx_drm_encoder_add_possible_crtcs(hdmi->imx_drm_encoder, np);
+       /* Unmute interrupts */
+       hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
-       platform_set_drvdata(pdev, hdmi);
+       dev_set_drvdata(dev, hdmi);
 
        return 0;
 
@@ -1882,20 +1718,35 @@ err_isfr:
        return ret;
 }
 
-static int imx_hdmi_platform_remove(struct platform_device *pdev)
+static void imx_hdmi_unbind(struct device *dev, struct device *master,
+       void *data)
 {
-       struct imx_hdmi *hdmi = platform_get_drvdata(pdev);
-       struct drm_connector *connector = &hdmi->connector;
-       struct drm_encoder *encoder = &hdmi->encoder;
+       struct imx_hdmi *hdmi = dev_get_drvdata(dev);
 
-       drm_mode_connector_detach_encoder(connector, encoder);
-       imx_drm_remove_connector(hdmi->imx_drm_connector);
-       imx_drm_remove_encoder(hdmi->imx_drm_encoder);
+       /* Disable all interrupts */
+       hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+       hdmi->connector.funcs->destroy(&hdmi->connector);
+       hdmi->encoder.funcs->destroy(&hdmi->encoder);
 
        clk_disable_unprepare(hdmi->iahb_clk);
        clk_disable_unprepare(hdmi->isfr_clk);
        i2c_put_adapter(hdmi->ddc);
+}
+
+static const struct component_ops hdmi_ops = {
+       .bind   = imx_hdmi_bind,
+       .unbind = imx_hdmi_unbind,
+};
+
+static int imx_hdmi_platform_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &hdmi_ops);
+}
 
+static int imx_hdmi_platform_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &hdmi_ops);
        return 0;
 }
 
index 7e593296ac47287f4929b91270ff79d34752fd56..daa54df4527f274cdee17262827ad1a1b4c5b41b 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/module.h>
 #include <linux/clk.h>
+#include <linux/component.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -58,9 +59,8 @@ struct imx_ldb;
 struct imx_ldb_channel {
        struct imx_ldb *ldb;
        struct drm_connector connector;
-       struct imx_drm_connector *imx_drm_connector;
        struct drm_encoder encoder;
-       struct imx_drm_encoder *imx_drm_encoder;
+       struct device_node *child;
        int chno;
        void *edid;
        int edid_len;
@@ -91,11 +91,6 @@ static enum drm_connector_status imx_ldb_connector_detect(
        return connector_status_connected;
 }
 
-static void imx_ldb_connector_destroy(struct drm_connector *connector)
-{
-       /* do not free here */
-}
-
 static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 {
        struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
@@ -111,6 +106,8 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
                struct drm_display_mode *mode;
 
                mode = drm_mode_create(connector->dev);
+               if (!mode)
+                       return -EINVAL;
                drm_mode_copy(mode, &imx_ldb_ch->mode);
                mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
                drm_mode_probed_add(connector, mode);
@@ -120,12 +117,6 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
        return num_modes;
 }
 
-static int imx_ldb_connector_mode_valid(struct drm_connector *connector,
-                         struct drm_display_mode *mode)
-{
-       return 0;
-}
-
 static struct drm_encoder *imx_ldb_connector_best_encoder(
                struct drm_connector *connector)
 {
@@ -179,8 +170,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
        u32 pixel_fmt;
        unsigned long serial_clk;
        unsigned long di_clk = mode->clock * 1000;
-       int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->imx_drm_encoder,
-                                            encoder->crtc);
+       int mux = imx_drm_encoder_get_mux_id(encoder);
 
        if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
                /* dual channel LVDS mode */
@@ -207,8 +197,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
                pixel_fmt = V4L2_PIX_FMT_RGB24;
        }
 
-       imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_LVDS,
-                       pixel_fmt);
+       imx_drm_panel_format(encoder, pixel_fmt);
 }
 
 static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
@@ -216,8 +205,7 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
        struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
        struct imx_ldb *ldb = imx_ldb_ch->ldb;
        int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
-       int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->imx_drm_encoder,
-                                            encoder->crtc);
+       int mux = imx_drm_encoder_get_mux_id(encoder);
 
        if (dual) {
                clk_prepare_enable(ldb->clk[0]);
@@ -316,26 +304,21 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
        }
 }
 
-static void imx_ldb_encoder_destroy(struct drm_encoder *encoder)
-{
-       /* do not free here */
-}
-
 static struct drm_connector_funcs imx_ldb_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = imx_ldb_connector_detect,
-       .destroy = imx_ldb_connector_destroy,
+       .destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
        .get_modes = imx_ldb_connector_get_modes,
        .best_encoder = imx_ldb_connector_best_encoder,
-       .mode_valid = imx_ldb_connector_mode_valid,
+       .mode_valid = imx_drm_connector_mode_valid,
 };
 
 static struct drm_encoder_funcs imx_ldb_encoder_funcs = {
-       .destroy = imx_ldb_encoder_destroy,
+       .destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
@@ -351,56 +334,47 @@ static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno)
 {
        char clkname[16];
 
-       sprintf(clkname, "di%d", chno);
+       snprintf(clkname, sizeof(clkname), "di%d", chno);
        ldb->clk[chno] = devm_clk_get(ldb->dev, clkname);
        if (IS_ERR(ldb->clk[chno]))
                return PTR_ERR(ldb->clk[chno]);
 
-       sprintf(clkname, "di%d_pll", chno);
+       snprintf(clkname, sizeof(clkname), "di%d_pll", chno);
        ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
 
        return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
 }
 
-static int imx_ldb_register(struct imx_ldb_channel *imx_ldb_ch)
+static int imx_ldb_register(struct drm_device *drm,
+       struct imx_ldb_channel *imx_ldb_ch)
 {
-       int ret;
        struct imx_ldb *ldb = imx_ldb_ch->ldb;
+       int ret;
+
+       ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder,
+                                      imx_ldb_ch->child);
+       if (ret)
+               return ret;
 
        ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno);
        if (ret)
                return ret;
+
        if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
-               ret |= imx_ldb_get_clk(ldb, 1);
+               ret = imx_ldb_get_clk(ldb, 1);
                if (ret)
                        return ret;
        }
 
-       imx_ldb_ch->connector.funcs = &imx_ldb_connector_funcs;
-       imx_ldb_ch->encoder.funcs = &imx_ldb_encoder_funcs;
-
-       imx_ldb_ch->encoder.encoder_type = DRM_MODE_ENCODER_LVDS;
-       imx_ldb_ch->connector.connector_type = DRM_MODE_CONNECTOR_LVDS;
-
        drm_encoder_helper_add(&imx_ldb_ch->encoder,
                        &imx_ldb_encoder_helper_funcs);
-       ret = imx_drm_add_encoder(&imx_ldb_ch->encoder,
-                       &imx_ldb_ch->imx_drm_encoder, THIS_MODULE);
-       if (ret) {
-               dev_err(ldb->dev, "adding encoder failed with %d\n", ret);
-               return ret;
-       }
+       drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
+                        DRM_MODE_ENCODER_LVDS);
 
        drm_connector_helper_add(&imx_ldb_ch->connector,
                        &imx_ldb_connector_helper_funcs);
-
-       ret = imx_drm_add_connector(&imx_ldb_ch->connector,
-                       &imx_ldb_ch->imx_drm_connector, THIS_MODULE);
-       if (ret) {
-               imx_drm_remove_encoder(imx_ldb_ch->imx_drm_encoder);
-               dev_err(ldb->dev, "adding connector failed with %d\n", ret);
-               return ret;
-       }
+       drm_connector_init(drm, &imx_ldb_ch->connector,
+                          &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
 
        drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
                        &imx_ldb_ch->encoder);
@@ -459,11 +433,12 @@ static const struct of_device_id imx_ldb_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
 
-static int imx_ldb_probe(struct platform_device *pdev)
+static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 {
-       struct device_node *np = pdev->dev.of_node;
+       struct drm_device *drm = data;
+       struct device_node *np = dev->of_node;
        const struct of_device_id *of_id =
-                       of_match_device(imx_ldb_dt_ids, &pdev->dev);
+                       of_match_device(imx_ldb_dt_ids, dev);
        struct device_node *child;
        const u8 *edidp;
        struct imx_ldb *imx_ldb;
@@ -473,17 +448,17 @@ static int imx_ldb_probe(struct platform_device *pdev)
        int ret;
        int i;
 
-       imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL);
+       imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
        if (!imx_ldb)
                return -ENOMEM;
 
        imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
        if (IS_ERR(imx_ldb->regmap)) {
-               dev_err(&pdev->dev, "failed to get parent regmap\n");
+               dev_err(dev, "failed to get parent regmap\n");
                return PTR_ERR(imx_ldb->regmap);
        }
 
-       imx_ldb->dev = &pdev->dev;
+       imx_ldb->dev = dev;
 
        if (of_id)
                imx_ldb->lvds_mux = of_id->data;
@@ -521,7 +496,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
                        return -EINVAL;
 
                if (dual && i > 0) {
-                       dev_warn(&pdev->dev, "dual-channel mode, ignoring second output\n");
+                       dev_warn(dev, "dual-channel mode, ignoring second output\n");
                        continue;
                }
 
@@ -531,6 +506,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
                channel = &imx_ldb->channel[i];
                channel->ldb = imx_ldb;
                channel->chno = i;
+               channel->child = child;
 
                edidp = of_get_property(child, "edid", &channel->edid_len);
                if (edidp) {
@@ -560,7 +536,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
                        break;
                case LVDS_BIT_MAP_JEIDA:
                        if (datawidth == 18) {
-                               dev_err(&pdev->dev, "JEIDA standard only supported in 24 bit\n");
+                               dev_err(dev, "JEIDA standard only supported in 24 bit\n");
                                return -EINVAL;
                        }
                        if (i == 0 || dual)
@@ -569,38 +545,47 @@ static int imx_ldb_probe(struct platform_device *pdev)
                                imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA;
                        break;
                default:
-                       dev_err(&pdev->dev, "data mapping not specified or invalid\n");
+                       dev_err(dev, "data mapping not specified or invalid\n");
                        return -EINVAL;
                }
 
-               ret = imx_ldb_register(channel);
+               ret = imx_ldb_register(drm, channel);
                if (ret)
                        return ret;
-
-               imx_drm_encoder_add_possible_crtcs(channel->imx_drm_encoder, child);
        }
 
-       platform_set_drvdata(pdev, imx_ldb);
+       dev_set_drvdata(dev, imx_ldb);
 
        return 0;
 }
 
-static int imx_ldb_remove(struct platform_device *pdev)
+static void imx_ldb_unbind(struct device *dev, struct device *master,
+       void *data)
 {
-       struct imx_ldb *imx_ldb = platform_get_drvdata(pdev);
+       struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
        int i;
 
        for (i = 0; i < 2; i++) {
                struct imx_ldb_channel *channel = &imx_ldb->channel[i];
-               struct drm_connector *connector = &channel->connector;
-               struct drm_encoder *encoder = &channel->encoder;
-
-               drm_mode_connector_detach_encoder(connector, encoder);
 
-               imx_drm_remove_connector(channel->imx_drm_connector);
-               imx_drm_remove_encoder(channel->imx_drm_encoder);
+               channel->connector.funcs->destroy(&channel->connector);
+               channel->encoder.funcs->destroy(&channel->encoder);
        }
+}
+
+static const struct component_ops imx_ldb_ops = {
+       .bind   = imx_ldb_bind,
+       .unbind = imx_ldb_unbind,
+};
 
+static int imx_ldb_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &imx_ldb_ops);
+}
+
+static int imx_ldb_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &imx_ldb_ops);
        return 0;
 }
 
index 9abc7ca8b6cf78ad8dba66329352c341a7c369d7..50b25f1a85d5280cfcacdcfbdc51f52ec38e01ac 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/component.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
@@ -30,6 +31,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
+#include "ipu-v3/imx-ipu-v3.h"
 #include "imx-drm.h"
 
 #define TVE_COM_CONF_REG       0x00
@@ -110,9 +112,7 @@ enum {
 
 struct imx_tve {
        struct drm_connector connector;
-       struct imx_drm_connector *imx_drm_connector;
        struct drm_encoder encoder;
-       struct imx_drm_encoder *imx_drm_encoder;
        struct device *dev;
        spinlock_t lock;        /* register lock */
        bool enabled;
@@ -225,11 +225,6 @@ static enum drm_connector_status imx_tve_connector_detect(
        return connector_status_connected;
 }
 
-static void imx_tve_connector_destroy(struct drm_connector *connector)
-{
-       /* do not free here */
-}
-
 static int imx_tve_connector_get_modes(struct drm_connector *connector)
 {
        struct imx_tve *tve = con_to_tve(connector);
@@ -254,6 +249,11 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
 {
        struct imx_tve *tve = con_to_tve(connector);
        unsigned long rate;
+       int ret;
+
+       ret = imx_drm_connector_mode_valid(connector, mode);
+       if (ret != MODE_OK)
+               return ret;
 
        /* pixel clock with 2x oversampling */
        rate = clk_round_rate(tve->clk, 2000UL * mode->clock) / 2000;
@@ -305,13 +305,11 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
 
        switch (tve->mode) {
        case TVE_MODE_VGA:
-               imx_drm_crtc_panel_format_pins(encoder->crtc,
-                               DRM_MODE_ENCODER_DAC, IPU_PIX_FMT_GBR24,
+               imx_drm_panel_format_pins(encoder, IPU_PIX_FMT_GBR24,
                                tve->hsync_pin, tve->vsync_pin);
                break;
        case TVE_MODE_TVOUT:
-               imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_TVDAC,
-                                         V4L2_PIX_FMT_YUV444);
+               imx_drm_panel_format(encoder, V4L2_PIX_FMT_YUV444);
                break;
        }
 }
@@ -364,16 +362,11 @@ static void imx_tve_encoder_disable(struct drm_encoder *encoder)
        tve_disable(tve);
 }
 
-static void imx_tve_encoder_destroy(struct drm_encoder *encoder)
-{
-       /* do not free here */
-}
-
 static struct drm_connector_funcs imx_tve_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = imx_tve_connector_detect,
-       .destroy = imx_tve_connector_destroy,
+       .destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
@@ -383,7 +376,7 @@ static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
 };
 
 static struct drm_encoder_funcs imx_tve_encoder_funcs = {
-       .destroy = imx_tve_encoder_destroy,
+       .destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = {
@@ -503,34 +496,27 @@ static int tve_clk_init(struct imx_tve *tve, void __iomem *base)
        return 0;
 }
 
-static int imx_tve_register(struct imx_tve *tve)
+static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
 {
+       int encoder_type;
        int ret;
 
-       tve->connector.funcs = &imx_tve_connector_funcs;
-       tve->encoder.funcs = &imx_tve_encoder_funcs;
+       encoder_type = tve->mode == TVE_MODE_VGA ?
+                               DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
 
-       tve->encoder.encoder_type = DRM_MODE_ENCODER_NONE;
-       tve->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+       ret = imx_drm_encoder_parse_of(drm, &tve->encoder,
+                                      tve->dev->of_node);
+       if (ret)
+               return ret;
 
        drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs);
-       ret = imx_drm_add_encoder(&tve->encoder, &tve->imx_drm_encoder,
-                       THIS_MODULE);
-       if (ret) {
-               dev_err(tve->dev, "adding encoder failed with %d\n", ret);
-               return ret;
-       }
+       drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
+                        encoder_type);
 
        drm_connector_helper_add(&tve->connector,
                        &imx_tve_connector_helper_funcs);
-
-       ret = imx_drm_add_connector(&tve->connector,
-                       &tve->imx_drm_connector, THIS_MODULE);
-       if (ret) {
-               imx_drm_remove_encoder(tve->imx_drm_encoder);
-               dev_err(tve->dev, "adding connector failed with %d\n", ret);
-               return ret;
-       }
+       drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
+                          DRM_MODE_CONNECTOR_VGA);
 
        drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
 
@@ -576,9 +562,11 @@ static const int of_get_tve_mode(struct device_node *np)
        return -EINVAL;
 }
 
-static int imx_tve_probe(struct platform_device *pdev)
+static int imx_tve_bind(struct device *dev, struct device *master, void *data)
 {
-       struct device_node *np = pdev->dev.of_node;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct drm_device *drm = data;
+       struct device_node *np = dev->of_node;
        struct device_node *ddc_node;
        struct imx_tve *tve;
        struct resource *res;
@@ -587,11 +575,11 @@ static int imx_tve_probe(struct platform_device *pdev)
        int irq;
        int ret;
 
-       tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
+       tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
        if (!tve)
                return -ENOMEM;
 
-       tve->dev = &pdev->dev;
+       tve->dev = dev;
        spin_lock_init(&tve->lock);
 
        ddc_node = of_parse_phandle(np, "ddc", 0);
@@ -602,7 +590,7 @@ static int imx_tve_probe(struct platform_device *pdev)
 
        tve->mode = of_get_tve_mode(np);
        if (tve->mode != TVE_MODE_VGA) {
-               dev_err(&pdev->dev, "only VGA mode supported, currently\n");
+               dev_err(dev, "only VGA mode supported, currently\n");
                return -EINVAL;
        }
 
@@ -611,7 +599,7 @@ static int imx_tve_probe(struct platform_device *pdev)
                                           &tve->hsync_pin);
 
                if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to get vsync pin\n");
+                       dev_err(dev, "failed to get vsync pin\n");
                        return ret;
                }
 
@@ -619,40 +607,40 @@ static int imx_tve_probe(struct platform_device *pdev)
                                            &tve->vsync_pin);
 
                if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to get vsync pin\n");
+                       dev_err(dev, "failed to get vsync pin\n");
                        return ret;
                }
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base = devm_ioremap_resource(&pdev->dev, res);
+       base = devm_ioremap_resource(dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
 
        tve_regmap_config.lock_arg = tve;
-       tve->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "tve", base,
+       tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base,
                                                &tve_regmap_config);
        if (IS_ERR(tve->regmap)) {
-               dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+               dev_err(dev, "failed to init regmap: %ld\n",
                        PTR_ERR(tve->regmap));
                return PTR_ERR(tve->regmap);
        }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get irq\n");
+               dev_err(dev, "failed to get irq\n");
                return irq;
        }
 
-       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+       ret = devm_request_threaded_irq(dev, irq, NULL,
                                        imx_tve_irq_handler, IRQF_ONESHOT,
                                        "imx-tve", tve);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+               dev_err(dev, "failed to request irq: %d\n", ret);
                return ret;
        }
 
-       tve->dac_reg = devm_regulator_get(&pdev->dev, "dac");
+       tve->dac_reg = devm_regulator_get(dev, "dac");
        if (!IS_ERR(tve->dac_reg)) {
                regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
                ret = regulator_enable(tve->dac_reg);
@@ -660,17 +648,17 @@ static int imx_tve_probe(struct platform_device *pdev)
                        return ret;
        }
 
-       tve->clk = devm_clk_get(&pdev->dev, "tve");
+       tve->clk = devm_clk_get(dev, "tve");
        if (IS_ERR(tve->clk)) {
-               dev_err(&pdev->dev, "failed to get high speed tve clock: %ld\n",
+               dev_err(dev, "failed to get high speed tve clock: %ld\n",
                        PTR_ERR(tve->clk));
                return PTR_ERR(tve->clk);
        }
 
        /* this is the IPU DI clock input selector, can be parented to tve_di */
-       tve->di_sel_clk = devm_clk_get(&pdev->dev, "di_sel");
+       tve->di_sel_clk = devm_clk_get(dev, "di_sel");
        if (IS_ERR(tve->di_sel_clk)) {
-               dev_err(&pdev->dev, "failed to get ipu di mux clock: %ld\n",
+               dev_err(dev, "failed to get ipu di mux clock: %ld\n",
                        PTR_ERR(tve->di_sel_clk));
                return PTR_ERR(tve->di_sel_clk);
        }
@@ -681,42 +669,51 @@ static int imx_tve_probe(struct platform_device *pdev)
 
        ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to read configuration register: %d\n", ret);
+               dev_err(dev, "failed to read configuration register: %d\n", ret);
                return ret;
        }
        if (val != 0x00100000) {
-               dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n");
+               dev_err(dev, "configuration register default value indicates this is not a TVEv2\n");
                return -ENODEV;
        }
 
        /* disable cable detection for VGA mode */
        ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0);
 
-       ret = imx_tve_register(tve);
+       ret = imx_tve_register(drm, tve);
        if (ret)
                return ret;
 
-       ret = imx_drm_encoder_add_possible_crtcs(tve->imx_drm_encoder, np);
-
-       platform_set_drvdata(pdev, tve);
+       dev_set_drvdata(dev, tve);
 
        return 0;
 }
 
-static int imx_tve_remove(struct platform_device *pdev)
+static void imx_tve_unbind(struct device *dev, struct device *master,
+       void *data)
 {
-       struct imx_tve *tve = platform_get_drvdata(pdev);
-       struct drm_connector *connector = &tve->connector;
-       struct drm_encoder *encoder = &tve->encoder;
+       struct imx_tve *tve = dev_get_drvdata(dev);
 
-       drm_mode_connector_detach_encoder(connector, encoder);
-
-       imx_drm_remove_connector(tve->imx_drm_connector);
-       imx_drm_remove_encoder(tve->imx_drm_encoder);
+       tve->connector.funcs->destroy(&tve->connector);
+       tve->encoder.funcs->destroy(&tve->encoder);
 
        if (!IS_ERR(tve->dac_reg))
                regulator_disable(tve->dac_reg);
+}
+
+static const struct component_ops imx_tve_ops = {
+       .bind   = imx_tve_bind,
+       .unbind = imx_tve_unbind,
+};
 
+static int imx_tve_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &imx_tve_ops);
+}
+
+static int imx_tve_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &imx_tve_ops);
        return 0;
 }
 
index 4826b5c0249d1b202cd69b8474d35a2729962c18..c4d14ead5837ce85b0b6fb5064cdca13e9023ab7 100644 (file)
@@ -25,6 +25,8 @@ enum ipuv3_type {
        IPUV3H,
 };
 
+#define IPU_PIX_FMT_GBR24      v4l2_fourcc('G', 'B', 'R', '3')
+
 /*
  * Bitfield of Display Interface signal polarities.
  */
index d0e3bc3c53e708dbf761e4e9a5760935f55c26b8..d5de8bb5c803f87b84dbfea1a2aaac5843f3661a 100644 (file)
@@ -262,7 +262,7 @@ void ipu_dc_disable_channel(struct ipu_dc *dc)
 
        /* Wait for DC triple buffer to empty */
        while ((readl(priv->dc_reg + DC_STAT) & val) != val) {
-               msleep(2);
+               usleep_range(2000, 20000);
                timeout -= 2;
                if (timeout <= 0)
                        break;
index 948a49b289ef171036d3f39e8ac0eb6392e59b3e..82a9ebad697c76b13181d809fa5c53c6d5200f62 100644 (file)
@@ -19,9 +19,6 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 
 #include "imx-ipu-v3.h"
 #include "ipu-prv.h"
@@ -33,10 +30,7 @@ struct ipu_di {
        struct clk *clk_di;     /* display input clock */
        struct clk *clk_ipu;    /* IPU bus clock */
        struct clk *clk_di_pixel; /* resulting pixel clock */
-       struct clk_hw clk_hw_out;
-       char *clk_name;
        bool inuse;
-       unsigned long clkflags;
        struct ipu_soc *ipu;
 };
 
@@ -141,130 +135,6 @@ static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
        writel(value, di->base + offset);
 }
 
-static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate)
-{
-       u64 tmp = inrate;
-       int div;
-
-       tmp *= 16;
-
-       do_div(tmp, outrate);
-
-       div = tmp;
-
-       if (div < 0x10)
-               div = 0x10;
-
-#ifdef WTF_IS_THIS
-       /*
-        * Freescale has this in their Kernel. It is neither clear what
-        * it does nor why it does it
-        */
-       if (div & 0x10)
-               div &= ~0x7;
-       else {
-               /* Round up divider if it gets us closer to desired pix clk */
-               if ((div & 0xC) == 0xC) {
-                       div += 0x10;
-                       div &= ~0xF;
-               }
-       }
-#endif
-       return div;
-}
-
-static unsigned long clk_di_recalc_rate(struct clk_hw *hw,
-               unsigned long parent_rate)
-{
-       struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-       unsigned long outrate;
-       u32 div = ipu_di_read(di, DI_BS_CLKGEN0);
-
-       if (div < 0x10)
-               div = 0x10;
-
-       outrate = (parent_rate / div) * 16;
-
-       return outrate;
-}
-
-static long clk_di_round_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long *prate)
-{
-       struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-       unsigned long outrate;
-       int div;
-       u32 val;
-
-       div = ipu_di_clk_calc_div(*prate, rate);
-
-       outrate = (*prate / div) * 16;
-
-       val = ipu_di_read(di, DI_GENERAL);
-
-       if (!(val & DI_GEN_DI_CLK_EXT) && outrate > *prate / 2)
-               outrate = *prate / 2;
-
-       dev_dbg(di->ipu->dev,
-               "%s: inrate: %ld div: 0x%08x outrate: %ld wanted: %ld\n",
-                       __func__, *prate, div, outrate, rate);
-
-       return outrate;
-}
-
-static int clk_di_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-       int div;
-       u32 clkgen0;
-
-       clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff;
-
-       div = ipu_di_clk_calc_div(parent_rate, rate);
-
-       ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0);
-
-       dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n",
-                       __func__, parent_rate, rate, div);
-       return 0;
-}
-
-static u8 clk_di_get_parent(struct clk_hw *hw)
-{
-       struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-       u32 val;
-
-       val = ipu_di_read(di, DI_GENERAL);
-
-       return val & DI_GEN_DI_CLK_EXT ? 1 : 0;
-}
-
-static int clk_di_set_parent(struct clk_hw *hw, u8 index)
-{
-       struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-       u32 val;
-
-       val = ipu_di_read(di, DI_GENERAL);
-
-       if (index)
-               val |= DI_GEN_DI_CLK_EXT;
-       else
-               val &= ~DI_GEN_DI_CLK_EXT;
-
-       ipu_di_write(di, val, DI_GENERAL);
-
-       return 0;
-}
-
-static struct clk_ops clk_di_ops = {
-       .round_rate = clk_di_round_rate,
-       .set_rate = clk_di_set_rate,
-       .recalc_rate = clk_di_recalc_rate,
-       .set_parent = clk_di_set_parent,
-       .get_parent = clk_di_get_parent,
-};
-
 static void ipu_di_data_wave_config(struct ipu_di *di,
                                     int wave_gen,
                                     int access_size, int component_size)
@@ -528,15 +398,125 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
                ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
 }
 
+static void ipu_di_config_clock(struct ipu_di *di,
+       const struct ipu_di_signal_cfg *sig)
+{
+       struct clk *clk;
+       unsigned clkgen0;
+       uint32_t val;
+
+       if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
+               /*
+                * CLKMODE_EXT means we must use the DI clock: this is
+                * needed for things like LVDS which needs to feed the
+                * DI and LDB with the same pixel clock.
+                */
+               clk = di->clk_di;
+
+               if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
+                       /*
+                        * CLKMODE_SYNC means that we want the DI to be
+                        * clocked at the same rate as the parent clock.
+                        * This is needed (eg) for LDB which needs to be
+                        * fed with the same pixel clock.  We assume that
+                        * the LDB clock has already been set correctly.
+                        */
+                       clkgen0 = 1 << 4;
+               } else {
+                       /*
+                        * We can use the divider.  We should really have
+                        * a flag here indicating whether the bridge can
+                        * cope with a fractional divider or not.  For the
+                        * time being, let's go for simplicitly and
+                        * reliability.
+                        */
+                       unsigned long in_rate;
+                       unsigned div;
+
+                       clk_set_rate(clk, sig->pixelclock);
+
+                       in_rate = clk_get_rate(clk);
+                       div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+                       if (div == 0)
+                               div = 1;
+
+                       clkgen0 = div << 4;
+               }
+       } else {
+               /*
+                * For other interfaces, we can arbitarily select between
+                * the DI specific clock and the internal IPU clock.  See
+                * DI_GENERAL bit 20.  We select the IPU clock if it can
+                * give us a clock rate within 1% of the requested frequency,
+                * otherwise we use the DI clock.
+                */
+               unsigned long rate, clkrate;
+               unsigned div, error;
+
+               clkrate = clk_get_rate(di->clk_ipu);
+               div = (clkrate + sig->pixelclock / 2) / sig->pixelclock;
+               rate = clkrate / div;
+
+               error = rate / (sig->pixelclock / 1000);
+
+               dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
+                       rate, div, (signed)(error - 1000) / 10, error % 10);
+
+               /* Allow a 1% error */
+               if (error < 1010 && error >= 990) {
+                       clk = di->clk_ipu;
+
+                       clkgen0 = div << 4;
+               } else {
+                       unsigned long in_rate;
+                       unsigned div;
+
+                       clk = di->clk_di;
+
+                       clk_set_rate(clk, sig->pixelclock);
+
+                       in_rate = clk_get_rate(clk);
+                       div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+                       if (div == 0)
+                               div = 1;
+
+                       clkgen0 = div << 4;
+               }
+       }
+
+       di->clk_di_pixel = clk;
+
+       /* Set the divider */
+       ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
+
+       /*
+        * Set the high/low periods.  Bits 24:16 give us the falling edge,
+        * and bits 8:0 give the rising edge.  LSB is fraction, and is
+        * based on the divider above.  We want a 50% duty cycle, so set
+        * the falling edge to be half the divider.
+        */
+       ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
+
+       /* Finally select the input clock */
+       val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
+       if (clk == di->clk_di)
+               val |= DI_GEN_DI_CLK_EXT;
+       ipu_di_write(di, val, DI_GENERAL);
+
+       dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
+               sig->pixelclock,
+               clk_get_rate(di->clk_ipu),
+               clk_get_rate(di->clk_di),
+               clk == di->clk_di ? "DI" : "IPU",
+               clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
+}
+
 int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 {
        u32 reg;
        u32 di_gen, vsync_cnt;
        u32 div;
        u32 h_total, v_total;
-       int ret;
-       unsigned long round;
-       struct clk *parent;
 
        dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
                di->id, sig->width, sig->height);
@@ -544,33 +524,20 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
        if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
                return -EINVAL;
 
-       if (sig->clkflags & IPU_DI_CLKMODE_EXT)
-               parent = di->clk_di;
-       else
-               parent = di->clk_ipu;
-
-       ret = clk_set_parent(di->clk_di_pixel, parent);
-       if (ret) {
-               dev_err(di->ipu->dev,
-                       "setting pixel clock to parent %s failed with %d\n",
-                               __clk_get_name(parent), ret);
-               return ret;
-       }
-
-       if (sig->clkflags & IPU_DI_CLKMODE_SYNC)
-               round = clk_get_rate(parent);
-       else
-               round = clk_round_rate(di->clk_di_pixel, sig->pixelclock);
-
-       ret = clk_set_rate(di->clk_di_pixel, round);
-
        h_total = sig->width + sig->h_sync_width + sig->h_start_width +
                sig->h_end_width;
        v_total = sig->height + sig->v_sync_width + sig->v_start_width +
                sig->v_end_width;
 
+       dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
+               clk_get_rate(di->clk_ipu),
+               clk_get_rate(di->clk_di),
+               sig->pixelclock);
+
        mutex_lock(&di_mutex);
 
+       ipu_di_config_clock(di, sig);
+
        div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
        div = div / 16;         /* Now divider is integer portion */
 
@@ -654,7 +621,11 @@ EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
 
 int ipu_di_enable(struct ipu_di *di)
 {
-       int ret = clk_prepare_enable(di->clk_di_pixel);
+       int ret;
+
+       WARN_ON(IS_ERR(di->clk_di_pixel));
+
+       ret = clk_prepare_enable(di->clk_di_pixel);
        if (ret)
                return ret;
 
@@ -666,6 +637,8 @@ EXPORT_SYMBOL_GPL(ipu_di_enable);
 
 int ipu_di_disable(struct ipu_di *di)
 {
+       WARN_ON(IS_ERR(di->clk_di_pixel));
+
        ipu_module_disable(di->ipu, di->module);
 
        clk_disable_unprepare(di->clk_di_pixel);
@@ -721,13 +694,6 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
                u32 module, struct clk *clk_ipu)
 {
        struct ipu_di *di;
-       int ret;
-       const char *di_parent[2];
-       struct clk_init_data init = {
-               .ops = &clk_di_ops,
-               .num_parents = 2,
-               .flags = 0,
-       };
 
        if (id > 1)
                return -ENODEV;
@@ -749,45 +715,16 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
        if (!di->base)
                return -ENOMEM;
 
-       di_parent[0] = __clk_get_name(di->clk_ipu);
-       di_parent[1] = __clk_get_name(di->clk_di);
-
        ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
 
-       init.parent_names = (const char **)&di_parent;
-       di->clk_name = kasprintf(GFP_KERNEL, "%s_di%d_pixel",
-                       dev_name(dev), id);
-       if (!di->clk_name)
-               return -ENOMEM;
-
-       init.name = di->clk_name;
-
-       di->clk_hw_out.init = &init;
-       di->clk_di_pixel = clk_register(dev, &di->clk_hw_out);
-
-       if (IS_ERR(di->clk_di_pixel)) {
-               ret = PTR_ERR(di->clk_di_pixel);
-               goto failed_clk_register;
-       }
-
        dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
                        id, base, di->base);
        di->inuse = false;
        di->ipu = ipu;
 
        return 0;
-
-failed_clk_register:
-
-       kfree(di->clk_name);
-
-       return ret;
 }
 
 void ipu_di_exit(struct ipu_soc *ipu, int id)
 {
-       struct ipu_di *di = ipu->di_priv[id];
-
-       clk_unregister(di->clk_di_pixel);
-       kfree(di->clk_name);
 }
index 98070dd8c92057c85b6a9aea1b9236fbb504b89f..45213017fa4b3557e680843f05fad4adf4b19227 100644 (file)
@@ -161,9 +161,6 @@ static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
                        "dmfc: using %d slots starting from segment %d for IPU channel %d\n",
                        slots, segment, dmfc->data->ipu_channel);
 
-       if (!dmfc)
-               return -EINVAL;
-
        switch (slots) {
        case 1:
                field = DMFC_FIFO_SIZE_64;
index 22be104fbda97526980481011ad5250121b52948..e646017c32ac573aa3d96bd5de949c2e9677cfc7 100644 (file)
@@ -17,6 +17,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  */
+#include <linux/component.h>
 #include <linux/module.h>
 #include <linux/export.h>
 #include <linux/device.h>
@@ -284,6 +285,7 @@ static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
                ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
                        IPU_DI_CLKMODE_EXT;
                break;
+       case DRM_MODE_ENCODER_TMDS:
        case DRM_MODE_ENCODER_NONE:
                ipu_crtc->di_clkflags = 0;
                break;
@@ -334,7 +336,7 @@ err_out:
 }
 
 static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
-               struct ipu_client_platformdata *pdata)
+       struct ipu_client_platformdata *pdata, struct drm_device *drm)
 {
        struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
        int dp = -EINVAL;
@@ -348,9 +350,9 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                return ret;
        }
 
-       ret = imx_drm_add_crtc(&ipu_crtc->base,
+       ret = imx_drm_add_crtc(drm, &ipu_crtc->base,
                        &ipu_crtc->imx_crtc,
-                       &ipu_crtc_helper_funcs, THIS_MODULE,
+                       &ipu_crtc_helper_funcs,
                        ipu_crtc->dev->parent->of_node, pdata->di);
        if (ret) {
                dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
@@ -399,43 +401,61 @@ err_put_resources:
        return ret;
 }
 
-static int ipu_drm_probe(struct platform_device *pdev)
+static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 {
-       struct ipu_client_platformdata *pdata = pdev->dev.platform_data;
+       struct ipu_client_platformdata *pdata = dev->platform_data;
+       struct drm_device *drm = data;
        struct ipu_crtc *ipu_crtc;
        int ret;
 
-       if (!pdata)
-               return -EINVAL;
-
-       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-       if (ret)
-               return ret;
-
-       ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL);
+       ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
        if (!ipu_crtc)
                return -ENOMEM;
 
-       ipu_crtc->dev = &pdev->dev;
+       ipu_crtc->dev = dev;
 
-       ret = ipu_crtc_init(ipu_crtc, pdata);
+       ret = ipu_crtc_init(ipu_crtc, pdata, drm);
        if (ret)
                return ret;
 
-       platform_set_drvdata(pdev, ipu_crtc);
+       dev_set_drvdata(dev, ipu_crtc);
 
        return 0;
 }
 
-static int ipu_drm_remove(struct platform_device *pdev)
+static void ipu_drm_unbind(struct device *dev, struct device *master,
+       void *data)
 {
-       struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev);
+       struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
 
        imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 
        ipu_plane_put_resources(ipu_crtc->plane[0]);
        ipu_put_resources(ipu_crtc);
+}
+
+static const struct component_ops ipu_crtc_ops = {
+       .bind = ipu_drm_bind,
+       .unbind = ipu_drm_unbind,
+};
+
+static int ipu_drm_probe(struct platform_device *pdev)
+{
+       int ret;
 
+       if (!pdev->dev.platform_data)
+               return -EINVAL;
+
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
+       return component_add(&pdev->dev, &ipu_crtc_ops);
+}
+
+static int ipu_drm_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &ipu_crtc_ops);
        return 0;
 }
 
index 34b642a12f8bb2cb6163b1fa05eeca184aef135b..b0c9b6ce48540471760a824126c4e9e709e8af8e 100644 (file)
@@ -72,8 +72,8 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
                return -EFAULT;
        }
 
-       dev_dbg(ipu_plane->base.dev->dev, "phys = 0x%x, x = %d, y = %d",
-               cma_obj->paddr, x, y);
+       dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
+               &cma_obj->paddr, x, y);
 
        cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
        ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
index 351d61dede0024003f39c7ace312e552081c79ad..c60b6c645f42000df73f7ee4ba198cca6c65d27f 100644 (file)
  * MA 02110-1301, USA.
  */
 
+#include <linux/component.h>
 #include <linux/module.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
 #include <linux/videodev2.h>
 #include <video/of_display_timing.h>
 
 
 struct imx_parallel_display {
        struct drm_connector connector;
-       struct imx_drm_connector *imx_drm_connector;
        struct drm_encoder encoder;
-       struct imx_drm_encoder *imx_drm_encoder;
        struct device *dev;
        void *edid;
        int edid_len;
        u32 interface_pix_fmt;
        int mode_valid;
        struct drm_display_mode mode;
+       struct drm_panel *panel;
 };
 
 static enum drm_connector_status imx_pd_connector_detect(
@@ -49,17 +50,19 @@ static enum drm_connector_status imx_pd_connector_detect(
        return connector_status_connected;
 }
 
-static void imx_pd_connector_destroy(struct drm_connector *connector)
-{
-       /* do not free here */
-}
-
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
 {
        struct imx_parallel_display *imxpd = con_to_imxpd(connector);
        struct device_node *np = imxpd->dev->of_node;
        int num_modes = 0;
 
+       if (imxpd->panel && imxpd->panel->funcs &&
+           imxpd->panel->funcs->get_modes) {
+               num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
+               if (num_modes > 0)
+                       return num_modes;
+       }
+
        if (imxpd->edid) {
                drm_mode_connector_update_edid_property(connector, imxpd->edid);
                num_modes = drm_add_edid_modes(connector, imxpd->edid);
@@ -67,6 +70,8 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
 
        if (imxpd->mode_valid) {
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
+               if (!mode)
+                       return -EINVAL;
                drm_mode_copy(mode, &imxpd->mode);
                mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
                drm_mode_probed_add(connector, mode);
@@ -75,6 +80,8 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
 
        if (np) {
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
+               if (!mode)
+                       return -EINVAL;
                of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE);
                drm_mode_copy(mode, &imxpd->mode);
                mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
@@ -85,12 +92,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
        return num_modes;
 }
 
-static int imx_pd_connector_mode_valid(struct drm_connector *connector,
-                         struct drm_display_mode *mode)
-{
-       return 0;
-}
-
 static struct drm_encoder *imx_pd_connector_best_encoder(
                struct drm_connector *connector)
 {
@@ -101,6 +102,12 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
 
 static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
+       struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
+
+       if (mode != DRM_MODE_DPMS_ON)
+               drm_panel_disable(imxpd->panel);
+       else
+               drm_panel_enable(imxpd->panel);
 }
 
 static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -114,8 +121,7 @@ static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
 {
        struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
 
-       imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE,
-                       imxpd->interface_pix_fmt);
+       imx_drm_panel_format(encoder, imxpd->interface_pix_fmt);
 }
 
 static void imx_pd_encoder_commit(struct drm_encoder *encoder)
@@ -132,26 +138,21 @@ static void imx_pd_encoder_disable(struct drm_encoder *encoder)
 {
 }
 
-static void imx_pd_encoder_destroy(struct drm_encoder *encoder)
-{
-       /* do not free here */
-}
-
 static struct drm_connector_funcs imx_pd_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = imx_pd_connector_detect,
-       .destroy = imx_pd_connector_destroy,
+       .destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
        .get_modes = imx_pd_connector_get_modes,
        .best_encoder = imx_pd_connector_best_encoder,
-       .mode_valid = imx_pd_connector_mode_valid,
+       .mode_valid = imx_drm_connector_mode_valid,
 };
 
 static struct drm_encoder_funcs imx_pd_encoder_funcs = {
-       .destroy = imx_pd_encoder_destroy,
+       .destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
@@ -163,51 +164,46 @@ static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
        .disable = imx_pd_encoder_disable,
 };
 
-static int imx_pd_register(struct imx_parallel_display *imxpd)
+static int imx_pd_register(struct drm_device *drm,
+       struct imx_parallel_display *imxpd)
 {
        int ret;
 
-       drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
-
-       imxpd->connector.funcs = &imx_pd_connector_funcs;
-       imxpd->encoder.funcs = &imx_pd_encoder_funcs;
-
-       imxpd->encoder.encoder_type = DRM_MODE_ENCODER_NONE;
-       imxpd->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+       ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder,
+                                      imxpd->dev->of_node);
+       if (ret)
+               return ret;
 
        drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
-       ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder,
-                       THIS_MODULE);
-       if (ret) {
-               dev_err(imxpd->dev, "adding encoder failed with %d\n", ret);
-               return ret;
-       }
+       drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs,
+                        DRM_MODE_ENCODER_NONE);
 
        drm_connector_helper_add(&imxpd->connector,
                        &imx_pd_connector_helper_funcs);
+       drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs,
+                          DRM_MODE_CONNECTOR_VGA);
 
-       ret = imx_drm_add_connector(&imxpd->connector,
-                       &imxpd->imx_drm_connector, THIS_MODULE);
-       if (ret) {
-               imx_drm_remove_encoder(imxpd->imx_drm_encoder);
-               dev_err(imxpd->dev, "adding connector failed with %d\n", ret);
-               return ret;
-       }
+       if (imxpd->panel)
+               drm_panel_attach(imxpd->panel, &imxpd->connector);
+
+       drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
 
        imxpd->connector.encoder = &imxpd->encoder;
 
        return 0;
 }
 
-static int imx_pd_probe(struct platform_device *pdev)
+static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
-       struct device_node *np = pdev->dev.of_node;
+       struct drm_device *drm = data;
+       struct device_node *np = dev->of_node;
+       struct device_node *panel_node;
        const u8 *edidp;
        struct imx_parallel_display *imxpd;
        int ret;
        const char *fmt;
 
-       imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+       imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
        if (!imxpd)
                return -ENOMEM;
 
@@ -225,30 +221,43 @@ static int imx_pd_probe(struct platform_device *pdev)
                        imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
        }
 
-       imxpd->dev = &pdev->dev;
+       panel_node = of_parse_phandle(np, "fsl,panel", 0);
+       if (panel_node)
+               imxpd->panel = of_drm_find_panel(panel_node);
 
-       ret = imx_pd_register(imxpd);
+       imxpd->dev = dev;
+
+       ret = imx_pd_register(drm, imxpd);
        if (ret)
                return ret;
 
-       ret = imx_drm_encoder_add_possible_crtcs(imxpd->imx_drm_encoder, np);
-
-       platform_set_drvdata(pdev, imxpd);
+       dev_set_drvdata(dev, imxpd);
 
        return 0;
 }
 
-static int imx_pd_remove(struct platform_device *pdev)
+static void imx_pd_unbind(struct device *dev, struct device *master,
+       void *data)
 {
-       struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
-       struct drm_connector *connector = &imxpd->connector;
-       struct drm_encoder *encoder = &imxpd->encoder;
+       struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
 
-       drm_mode_connector_detach_encoder(connector, encoder);
+       imxpd->encoder.funcs->destroy(&imxpd->encoder);
+       imxpd->connector.funcs->destroy(&imxpd->connector);
+}
 
-       imx_drm_remove_connector(imxpd->imx_drm_connector);
-       imx_drm_remove_encoder(imxpd->imx_drm_encoder);
+static const struct component_ops imx_pd_ops = {
+       .bind   = imx_pd_bind,
+       .unbind = imx_pd_unbind,
+};
 
+static int imx_pd_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &imx_pd_ops);
+}
+
+static int imx_pd_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &imx_pd_ops);
        return 0;
 }
 
index 7a6d85ebb29b006b235261c0f180c85e61296b23..e7a9d8dae4999b0d69b24b4cee88d1ff81322b07 100644 (file)
@@ -217,7 +217,7 @@ static int line6_send_raw_message_async_part(struct message *msg,
        Setup and start timer.
 */
 void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-                      void (*function) (unsigned long), unsigned long data)
+                      void (*function)(unsigned long), unsigned long data)
 {
        setup_timer(timer, function, data);
        timer->expires = jiffies + msecs * HZ / 1000;
index 34ae95e7e512871a74e9e9cd427ce28b3fb916f9..16e3fc2f1f1597e324cc8dd4c48d106b7338dc50 100644 (file)
@@ -204,7 +204,7 @@ extern int line6_send_sysex_message(struct usb_line6 *line6,
 extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count);
 extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-                             void (*function) (unsigned long),
+                             void (*function)(unsigned long),
                              unsigned long data);
 extern int line6_transmit_parameter(struct usb_line6 *line6, int param,
                                    u8 value);
index 90cadddec56ecda6c9f604699671927af8c4b034..eda04562d57675016ca9ceafacb652ec882f9f56 100644 (file)
@@ -91,9 +91,9 @@ enum {
        LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE |
                              LINE6_BIT_PODXTPRO,
        LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE,
-       LINE6_BITS_PODHDALL =   LINE6_BIT_PODHD300 |
-                               LINE6_BIT_PODHD400 |
-                               LINE6_BIT_PODHD500,
+       LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 |
+                             LINE6_BIT_PODHD400 |
+                             LINE6_BIT_PODHD500,
        LINE6_BITS_BASSPODXTALL = LINE6_BIT_BASSPODXT |
                                  LINE6_BIT_BASSPODXTLIVE |
                                  LINE6_BIT_BASSPODXTPRO
index 644a0000130a469cee58b18b760020dc823d3d8d..0727998a7667c7e82d9cc1f4d674f29ee916120b 100644 (file)
@@ -41,7 +41,7 @@
 #include "o2iblnd.h"
 #include <asm/div64.h>
 
-lnd_t the_o2iblnd = {
+static lnd_t the_o2iblnd = {
        .lnd_type       = O2IBLND,
        .lnd_startup    = kiblnd_startup,
        .lnd_shutdown   = kiblnd_shutdown,
@@ -53,8 +53,8 @@ lnd_t the_o2iblnd = {
 
 kib_data_t           kiblnd_data;
 
-__u32
-kiblnd_cksum (void *ptr, int nob)
+static __u32
+kiblnd_cksum(void *ptr, int nob)
 {
        char  *c  = ptr;
        __u32  sum = 0;
@@ -429,8 +429,8 @@ kiblnd_unlink_peer_locked (kib_peer_t *peer)
        kiblnd_peer_decref(peer);
 }
 
-int
-kiblnd_get_peer_info (lnet_ni_t *ni, int index,
+static int
+kiblnd_get_peer_info(lnet_ni_t *ni, int index,
                      lnet_nid_t *nidp, int *count)
 {
        kib_peer_t          *peer;
@@ -468,8 +468,8 @@ kiblnd_get_peer_info (lnet_ni_t *ni, int index,
        return -ENOENT;
 }
 
-void
-kiblnd_del_peer_locked (kib_peer_t *peer)
+static void
+kiblnd_del_peer_locked(kib_peer_t *peer)
 {
        struct list_head           *ctmp;
        struct list_head           *cnxt;
@@ -489,8 +489,8 @@ kiblnd_del_peer_locked (kib_peer_t *peer)
         * last ref on it. */
 }
 
-int
-kiblnd_del_peer (lnet_ni_t *ni, lnet_nid_t nid)
+static int
+kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
 {
        LIST_HEAD        (zombies);
        struct list_head            *ptmp;
@@ -543,8 +543,8 @@ kiblnd_del_peer (lnet_ni_t *ni, lnet_nid_t nid)
        return rc;
 }
 
-kib_conn_t *
-kiblnd_get_conn_by_idx (lnet_ni_t *ni, int index)
+static kib_conn_t *
+kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
 {
        kib_peer_t          *peer;
        struct list_head            *ptmp;
@@ -584,16 +584,16 @@ kiblnd_get_conn_by_idx (lnet_ni_t *ni, int index)
        return NULL;
 }
 
-void
-kiblnd_debug_rx (kib_rx_t *rx)
+static void
+kiblnd_debug_rx(kib_rx_t *rx)
 {
        CDEBUG(D_CONSOLE, "      %p status %d msg_type %x cred %d\n",
               rx, rx->rx_status, rx->rx_msg->ibm_type,
               rx->rx_msg->ibm_credits);
 }
 
-void
-kiblnd_debug_tx (kib_tx_t *tx)
+static void
+kiblnd_debug_tx(kib_tx_t *tx)
 {
        CDEBUG(D_CONSOLE, "      %p snd %d q %d w %d rc %d dl %lx "
               "cookie "LPX64" msg %s%s type %x cred %d\n",
@@ -604,8 +604,8 @@ kiblnd_debug_tx (kib_tx_t *tx)
               tx->tx_msg->ibm_type, tx->tx_msg->ibm_credits);
 }
 
-void
-kiblnd_debug_conn (kib_conn_t *conn)
+static void
+kiblnd_debug_conn(kib_conn_t *conn)
 {
        struct list_head        *tmp;
        int             i;
@@ -1039,8 +1039,8 @@ kiblnd_close_stale_conns_locked (kib_peer_t *peer,
        return count;
 }
 
-int
-kiblnd_close_matching_conns (lnet_ni_t *ni, lnet_nid_t nid)
+static int
+kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
 {
        kib_peer_t           *peer;
        struct list_head             *ptmp;
@@ -1440,7 +1440,7 @@ kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd)
        return mr;
 }
 
-void
+static void
 kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
 {
        LASSERT (pool->fpo_map_count == 0);
@@ -1454,7 +1454,7 @@ kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
        LIBCFS_FREE(pool, sizeof(kib_fmr_pool_t));
 }
 
-void
+static void
 kiblnd_destroy_fmr_pool_list(struct list_head *head)
 {
        kib_fmr_pool_t *pool;
@@ -1480,7 +1480,7 @@ static int kiblnd_fmr_flush_trigger(int ncpts)
        return max(IBLND_FMR_POOL_FLUSH, size);
 }
 
-int
+static int
 kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, kib_fmr_pool_t **pp_fpo)
 {
        /* FMR pool for RDMA */
@@ -1719,7 +1719,7 @@ kiblnd_init_pool(kib_poolset_t *ps, kib_pool_t *pool, int size)
        pool->po_size     = size;
 }
 
-void
+static void
 kiblnd_destroy_pool_list(struct list_head *head)
 {
        kib_pool_t *pool;
@@ -2192,7 +2192,7 @@ kiblnd_tx_init(kib_pool_t *pool, struct list_head *node)
        tx->tx_cookie = tps->tps_next_tx_cookie ++;
 }
 
-void
+static void
 kiblnd_net_fini_pools(kib_net_t *net)
 {
        int     i;
@@ -2234,7 +2234,7 @@ kiblnd_net_fini_pools(kib_net_t *net)
        }
 }
 
-int
+static int
 kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
 {
        unsigned long   flags;
@@ -2408,7 +2408,7 @@ kiblnd_hdev_get_attr(kib_hca_dev_t *hdev)
        return -EINVAL;
 }
 
-void
+static void
 kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev)
 {
        int     i;
@@ -2442,7 +2442,7 @@ kiblnd_hdev_destroy(kib_hca_dev_t *hdev)
        LIBCFS_FREE(hdev, sizeof(*hdev));
 }
 
-int
+static int
 kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
 {
        struct ib_mr *mr;
@@ -2746,7 +2746,7 @@ kiblnd_destroy_dev (kib_dev_t *dev)
        LIBCFS_FREE(dev, sizeof(*dev));
 }
 
-kib_dev_t *
+static kib_dev_t *
 kiblnd_create_dev(char *ifname)
 {
        struct net_device *netdev;
@@ -2800,7 +2800,7 @@ kiblnd_create_dev(char *ifname)
        return dev;
 }
 
-void
+static void
 kiblnd_base_shutdown(void)
 {
        struct kib_sched_info   *sched;
@@ -2940,7 +2940,7 @@ out:
        return;
 }
 
-int
+static int
 kiblnd_base_startup(void)
 {
        struct kib_sched_info   *sched;
@@ -3030,7 +3030,7 @@ kiblnd_base_startup(void)
        return -ENETDOWN;
 }
 
-int
+static int
 kiblnd_start_schedulers(struct kib_sched_info *sched)
 {
        int     rc = 0;
@@ -3071,7 +3071,7 @@ kiblnd_start_schedulers(struct kib_sched_info *sched)
        return rc;
 }
 
-int
+static int
 kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
 {
        int     cpt;
@@ -3097,7 +3097,7 @@ kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
        return 0;
 }
 
-kib_dev_t *
+static kib_dev_t *
 kiblnd_dev_search(char *ifname)
 {
        kib_dev_t       *alias = NULL;
@@ -3226,13 +3226,13 @@ failed:
        return -ENETDOWN;
 }
 
-void __exit
+static void __exit
 kiblnd_module_fini (void)
 {
        lnet_unregister_lnd(&the_o2iblnd);
 }
 
-int __init
+static int __init
 kiblnd_module_init (void)
 {
        int    rc;
index 4d692dcd96cfb76b296e23c7c34f4f2f4c6b71c6..76e1b68b38eda39f2d15f4f77baf30dcbddf07b0 100644 (file)
@@ -2392,7 +2392,11 @@ struct cl_io {
        /**
         * file is released, restore has to to be triggered by vvp layer
         */
-                            ci_restore_needed:1;
+                            ci_restore_needed:1,
+       /**
+        * O_NOATIME
+        */
+                            ci_noatime:1;
        /**
         * Number of pages owned by this IO. For invariant checking.
         */
index 4183a359f1f5356bd36f0a9f5fb8fad3c7423215..5f5b0ba9ea94afefbd9ac13edf7b623900f548c2 100644 (file)
@@ -1305,6 +1305,7 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
 #define OBD_CONNECT_SHORTIO     0x2000000000000ULL/* short io */
 #define OBD_CONNECT_PINGLESS   0x4000000000000ULL/* pings not required */
 #define OBD_CONNECT_FLOCK_DEAD 0x8000000000000ULL/* flock deadlock detection */
+#define OBD_CONNECT_DISP_STRIPE 0x10000000000000ULL/*create stripe disposition*/
 
 /* XXX README XXX:
  * Please DO NOT add flag values here before first ensuring that this same
@@ -1344,7 +1345,9 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
                                OBD_CONNECT_LIGHTWEIGHT | OBD_CONNECT_UMASK | \
                                OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\
                                OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE |\
-                               OBD_CONNECT_FLOCK_DEAD)
+                               OBD_CONNECT_FLOCK_DEAD | \
+                               OBD_CONNECT_DISP_STRIPE)
+
 #define OST_CONNECT_SUPPORTED  (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
                                OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
                                OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX | \
@@ -2109,19 +2112,32 @@ extern void lustre_swab_generic_32s (__u32 *val);
 #define DISP_LOOKUP_POS      0x00000008
 #define DISP_OPEN_CREATE     0x00000010
 #define DISP_OPEN_OPEN       0x00000020
-#define DISP_ENQ_COMPLETE    0x00400000
+#define DISP_ENQ_COMPLETE    0x00400000                /* obsolete and unused */
 #define DISP_ENQ_OPEN_REF    0x00800000
 #define DISP_ENQ_CREATE_REF  0x01000000
 #define DISP_OPEN_LOCK       0x02000000
 #define DISP_OPEN_LEASE      0x04000000
+#define DISP_OPEN_STRIPE     0x08000000
 
 /* INODE LOCK PARTS */
-#define MDS_INODELOCK_LOOKUP 0x000001       /* dentry, mode, owner, group */
-#define MDS_INODELOCK_UPDATE 0x000002       /* size, links, timestamps */
-#define MDS_INODELOCK_OPEN   0x000004       /* For opened files */
-#define MDS_INODELOCK_LAYOUT 0x000008       /* for layout */
-#define MDS_INODELOCK_PERM   0x000010       /* for permission */
-#define MDS_INODELOCK_XATTR  0x000020       /* extended attributes */
+#define MDS_INODELOCK_LOOKUP 0x000001  /* For namespace, dentry etc, and also
+                                        * was used to protect permission (mode,
+                                        * owner, group etc) before 2.4. */
+#define MDS_INODELOCK_UPDATE 0x000002  /* size, links, timestamps */
+#define MDS_INODELOCK_OPEN   0x000004  /* For opened files */
+#define MDS_INODELOCK_LAYOUT 0x000008  /* for layout */
+
+/* The PERM bit is added int 2.4, and it is used to protect permission(mode,
+ * owner, group, acl etc), so to separate the permission from LOOKUP lock.
+ * Because for remote directories(in DNE), these locks will be granted by
+ * different MDTs(different ldlm namespace).
+ *
+ * For local directory, MDT will always grant UPDATE_LOCK|PERM_LOCK together.
+ * For Remote directory, the master MDT, where the remote directory is, will
+ * grant UPDATE_LOCK|PERM_LOCK, and the remote MDT, where the name entry is,
+ * will grant LOOKUP_LOCK. */
+#define MDS_INODELOCK_PERM   0x000010
+#define MDS_INODELOCK_XATTR  0x000020  /* extended attributes */
 
 #define MDS_INODELOCK_MAXSHIFT 5
 /* This FULL lock is useful to take on unlink sort of operations */
index 2feb38b51af2d8d69da7f13f9aa966434e387726..6f7f48c7f2f10c290947958dd0314b2b2c117672 100644 (file)
@@ -380,6 +380,23 @@ static inline bool imp_connect_lvb_type(struct obd_import *imp)
                return false;
 }
 
+static inline __u64 exp_connect_ibits(struct obd_export *exp)
+{
+       struct obd_connect_data *ocd;
+
+       ocd = &exp->exp_connect_data;
+       return ocd->ocd_ibits_known;
+}
+
+static inline bool imp_connect_disp_stripe(struct obd_import *imp)
+{
+       struct obd_connect_data *ocd;
+
+       LASSERT(imp != NULL);
+       ocd = &imp->imp_connect_data;
+       return ocd->ocd_connect_flags & OBD_CONNECT_DISP_STRIPE;
+}
+
 extern struct obd_export *class_conn2export(struct lustre_handle *conn);
 extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
 
index 67259eb43cde1aa12208eab996481d3cf9789b8d..e9833ae8b171378f3effd46534936c641001fb5a 100644 (file)
@@ -180,6 +180,17 @@ struct obd_import {
        struct list_head                imp_delayed_list;
        /** @} */
 
+       /**
+        * List of requests that are retained for committed open replay. Once
+        * open is committed, open replay request will be moved from the
+        * imp_replay_list into the imp_committed_list.
+        * The imp_replay_cursor is for accelerating searching during replay.
+        * @{
+        */
+       struct list_head                imp_committed_list;
+       struct list_head               *imp_replay_cursor;
+       /** @} */
+
        /** obd device for this import */
        struct obd_device       *imp_obd;
 
index d8d08803542877f504947be3ceaa1c3cbfd55178..11382abf92910224a4a8fd85189523c329a98b62 100644 (file)
@@ -2621,6 +2621,8 @@ int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd);
  * request queues, request management, etc.
  * @{
  */
+void ptlrpc_request_committed(struct ptlrpc_request *req, int force);
+
 void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
                        struct ptlrpc_client *);
 void ptlrpc_cleanup_client(struct obd_import *imp);
index c3470ce62cff31aebf7d5b0310ba309b6507c750..1b386955adda7315be7beaebdf485fe151692a38 100644 (file)
@@ -1323,7 +1323,8 @@ struct md_open_data {
        struct obd_client_handle *mod_och;
        struct ptlrpc_request    *mod_open_req;
        struct ptlrpc_request    *mod_close_req;
-       atomic_t              mod_refcount;
+       atomic_t                  mod_refcount;
+       bool                      mod_is_create;
 };
 
 struct lookup_intent;
@@ -1392,7 +1393,7 @@ struct md_ops {
 
        int (*m_set_open_replay_data)(struct obd_export *,
                                      struct obd_client_handle *,
-                                     struct ptlrpc_request *);
+                                     struct lookup_intent *);
        int (*m_clear_open_replay_data)(struct obd_export *,
                                        struct obd_client_handle *);
        int (*m_set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *);
index 1c2ba19bd987234a610225c1ffe1484ecd25d1db..0a188207014ceedb5de5174cfb419bcb806e0e69 100644 (file)
@@ -2001,11 +2001,11 @@ static inline int md_getxattr(struct obd_export *exp,
 
 static inline int md_set_open_replay_data(struct obd_export *exp,
                                          struct obd_client_handle *och,
-                                         struct ptlrpc_request *open_req)
+                                         struct lookup_intent *it)
 {
        EXP_CHECK_MD_OP(exp, set_open_replay_data);
        EXP_MD_COUNTER_INCREMENT(exp, set_open_replay_data);
-       return MDP(exp->exp_obd, set_open_replay_data)(exp, och, open_req);
+       return MDP(exp->exp_obd, set_open_replay_data)(exp, och, it);
 }
 
 static inline int md_clear_open_replay_data(struct obd_export *exp,
index 3ed020eb89c03a27f0c213d7943e8baf8f07bbce..d87048dcc70c25cec635dbbb278d37f5146fed7a 100644 (file)
@@ -228,6 +228,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
 
                        lock_res_and_lock(lock);
                        LASSERT(lock->l_lvb_data == NULL);
+                       lock->l_lvb_type = LVB_T_LAYOUT;
                        lock->l_lvb_data = lvb_data;
                        lock->l_lvb_len = lvb_len;
                        unlock_res_and_lock(lock);
index 58bb256ee04728fec585f14395009a3ac6bf63df..77b1ef64ecc0c340a1132c35faef72e92398a5fe 100644 (file)
@@ -952,6 +952,7 @@ static int
 cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 {
        unsigned int  cpu = (unsigned long)hcpu;
+       bool         warn;
 
        switch (action) {
        case CPU_DEAD:
@@ -962,9 +963,21 @@ cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
                cpt_data.cpt_version++;
                spin_unlock(&cpt_data.cpt_lock);
        default:
-               CWARN("Lustre: can't support CPU hotplug well now, "
-                     "performance and stability could be impacted"
-                     "[CPU %u notify: %lx]\n", cpu, action);
+               if (action != CPU_DEAD && action != CPU_DEAD_FROZEN) {
+                       CDEBUG(D_INFO, "CPU changed [cpu %u action %lx]\n",
+                              cpu, action);
+                       break;
+               }
+
+               down(&cpt_data.cpt_mutex);
+               /* if all HTs in a core are offline, it may break affinity */
+               cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask);
+               warn = any_online_cpu(*cpt_data.cpt_cpumask) >= nr_cpu_ids;
+               up(&cpt_data.cpt_mutex);
+               CDEBUG(warn ? D_WARNING : D_INFO,
+                      "Lustre: can't support CPU plug-out well now, "
+                      "performance and stability could be impacted "
+                      "[CPU %u action: %lx]\n", cpu, action);
        }
 
        return NOTIFY_OK;
index 1a55c81892e0e8f692c167d17f0296814ad806dc..53813fca536f00097d7e13706cb20c9b2775fd38 100644 (file)
@@ -389,11 +389,11 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
                spin_unlock(&cfs_wi_data.wi_glock);
 
                if (sched->ws_cptab != NULL && sched->ws_cpt >= 0) {
-                       snprintf(name, sizeof(name), "%s_%02d_%02d",
+                       snprintf(name, sizeof(name), "%s_%02d_%02u",
                                 sched->ws_name, sched->ws_cpt,
                                 sched->ws_nthreads);
                } else {
-                       snprintf(name, sizeof(name), "%s_%02d",
+                       snprintf(name, sizeof(name), "%s_%02u",
                                 sched->ws_name, sched->ws_nthreads);
                }
 
index 3907c87c2ba1b03cc257d0bd03392df6dfc8ef9d..f971a543cb586afa69f4ad9aa9ff15b071267bd1 100644 (file)
@@ -241,9 +241,6 @@ void ll_intent_release(struct lookup_intent *it)
                 ptlrpc_req_finished(it->d.lustre.it_data); /* ll_file_open */
        if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */
                ptlrpc_req_finished(it->d.lustre.it_data);
-       if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate
-                                                   * to lookup */
-               ptlrpc_req_finished(it->d.lustre.it_data);
 
        it->d.lustre.it_disposition = 0;
        it->d.lustre.it_data = NULL;
@@ -328,262 +325,32 @@ void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft)
 
 }
 
-int ll_revalidate_it(struct dentry *de, int lookup_flags,
-                    struct lookup_intent *it)
+static int ll_revalidate_dentry(struct dentry *dentry,
+                               unsigned int lookup_flags)
 {
-       struct md_op_data *op_data;
-       struct ptlrpc_request *req = NULL;
-       struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
-       struct obd_export *exp;
-       struct inode *parent = de->d_parent->d_inode;
-       int rc;
-
-       CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
-              LL_IT2STR(it));
-
-       LASSERT(de != de->d_sb->s_root);
-
-       if (de->d_inode == NULL) {
-               __u64 ibits;
-
-               /* We can only use negative dentries if this is stat or lookup,
-                  for opens and stuff we do need to query server. */
-               /* If there is IT_CREAT in intent op set, then we must throw
-                  away this negative dentry and actually do the request to
-                  kernel to create whatever needs to be created (if possible)*/
-               if (it && (it->it_op & IT_CREAT))
-                       return 0;
+       struct inode *dir = dentry->d_parent->d_inode;
 
-               if (d_lustre_invalid(de))
-                       return 0;
-
-               ibits = MDS_INODELOCK_UPDATE;
-               rc = ll_have_md_lock(parent, &ibits, LCK_MINMODE);
-               GOTO(out_sa, rc);
-       }
-
-       /* Never execute intents for mount points.
-        * Attributes will be fixed up in ll_inode_revalidate_it */
-       if (d_mountpoint(de))
-               GOTO(out_sa, rc = 1);
-
-       exp = ll_i2mdexp(de->d_inode);
-
-       OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
-       ll_frob_intent(&it, &lookup_it);
-       LASSERT(it);
+       /*
+        * if open&create is set, talk to MDS to make sure file is created if
+        * necessary, because we can't do this in ->open() later since that's
+        * called on an inode. return 0 here to let lookup to handle this.
+        */
+       if ((lookup_flags & (LOOKUP_OPEN | LOOKUP_CREATE)) ==
+           (LOOKUP_OPEN | LOOKUP_CREATE))
+               return 0;
 
-       if (it->it_op == IT_LOOKUP && !d_lustre_invalid(de))
+       if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE))
                return 1;
 
-       if (it->it_op == IT_OPEN) {
-               struct inode *inode = de->d_inode;
-               struct ll_inode_info *lli = ll_i2info(inode);
-               struct obd_client_handle **och_p;
-               __u64 ibits;
-
-               /*
-                * We used to check for MDS_INODELOCK_OPEN here, but in fact
-                * just having LOOKUP lock is enough to justify inode is the
-                * same. And if inode is the same and we have suitable
-                * openhandle, then there is no point in doing another OPEN RPC
-                * just to throw away newly received openhandle.  There are no
-                * security implications too, if file owner or access mode is
-                * change, LOOKUP lock is revoked.
-                */
-
-
-               if (it->it_flags & FMODE_WRITE)
-                       och_p = &lli->lli_mds_write_och;
-               else if (it->it_flags & FMODE_EXEC)
-                       och_p = &lli->lli_mds_exec_och;
-               else
-                       och_p = &lli->lli_mds_read_och;
-
-               /* Check for the proper lock. */
-               ibits = MDS_INODELOCK_LOOKUP;
-               if (!ll_have_md_lock(inode, &ibits, LCK_MINMODE))
-                       goto do_lock;
-               mutex_lock(&lli->lli_och_mutex);
-               if (*och_p) { /* Everything is open already, do nothing */
-                       /* Originally it was idea to do not let them steal our
-                        * open handle from under us by (*och_usecount)++ here.
-                        * But in case we have the handle, but we cannot use it
-                        * due to later checks (e.g. O_CREAT|O_EXCL flags set),
-                        * nobody would decrement counter increased here. So we
-                        * just hope the lock won't be invalidated in between.
-                        * But if it would be, we'll reopen the open request to
-                        * MDS later during file open path.
-                        */
-                       mutex_unlock(&lli->lli_och_mutex);
-                       return 1;
-               }
-               mutex_unlock(&lli->lli_och_mutex);
-       }
-
-       if (it->it_op == IT_GETATTR) {
-               rc = ll_statahead_enter(parent, &de, 0);
-               if (rc == 1)
-                       goto mark;
-               else if (rc != -EAGAIN && rc != 0)
-                       GOTO(out, rc = 0);
-       }
-
-do_lock:
-       op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
-                                    de->d_name.name, de->d_name.len,
-                                    0, LUSTRE_OPC_ANY, NULL);
-       if (IS_ERR(op_data))
-               return PTR_ERR(op_data);
-
-       if (!IS_POSIXACL(parent) || !exp_connect_umask(exp))
-               it->it_create_mode &= ~current_umask();
-       it->it_create_mode |= M_CHECK_STALE;
-       rc = md_intent_lock(exp, op_data, NULL, 0, it,
-                           lookup_flags,
-                           &req, ll_md_blocking_ast, 0);
-       it->it_create_mode &= ~M_CHECK_STALE;
-       ll_finish_md_op_data(op_data);
-
-       /* If req is NULL, then md_intent_lock only tried to do a lock match;
-        * if all was well, it will return 1 if it found locks, 0 otherwise. */
-       if (req == NULL && rc >= 0) {
-               if (!rc)
-                       goto do_lookup;
-               GOTO(out, rc);
-       }
-
-       if (rc < 0) {
-               if (rc != -ESTALE) {
-                       CDEBUG(D_INFO, "ll_intent_lock: rc %d : it->it_status "
-                              "%d\n", rc, it->d.lustre.it_status);
-               }
-               GOTO(out, rc = 0);
-       }
-
-revalidate_finish:
-       rc = ll_revalidate_it_finish(req, it, de);
-       if (rc != 0) {
-               if (rc != -ESTALE && rc != -ENOENT)
-                       ll_intent_release(it);
-               GOTO(out, rc = 0);
-       }
-
-       if ((it->it_op & IT_OPEN) && de->d_inode &&
-           !S_ISREG(de->d_inode->i_mode) &&
-           !S_ISDIR(de->d_inode->i_mode)) {
-               ll_release_openhandle(de, it);
-       }
-       rc = 1;
-
-out:
-       /* We do not free request as it may be reused during following lookup
-        * (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
-        * be freed in ll_lookup_it or in ll_intent_release. But if
-        * request was not completed, we need to free it. (bug 5154, 9903) */
-       if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE))
-               ptlrpc_req_finished(req);
-       if (rc == 0) {
-               /* mdt may grant layout lock for the newly created file, so
-                * release the lock to avoid leaking */
-               ll_intent_drop_lock(it);
-               ll_invalidate_aliases(de->d_inode);
-       } else {
-               __u64 bits = 0;
-               __u64 matched_bits = 0;
-
-               CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
-                      "inode %p refc %d\n", de->d_name.len,
-                      de->d_name.name, de, de->d_parent, de->d_inode,
-                      d_count(de));
-
-               ll_set_lock_data(exp, de->d_inode, it, &bits);
-
-               /* Note: We have to match both LOOKUP and PERM lock
-                * here to make sure the dentry is valid and no one
-                * changing the permission.
-                * But if the client connects < 2.4 server, which will
-                * only grant LOOKUP lock, so we can only Match LOOKUP
-                * lock for old server */
-               if (exp_connect_flags(ll_i2mdexp(de->d_inode)) &&
-                                                       OBD_CONNECT_LVB_TYPE)
-                       matched_bits =
-                               MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM;
-               else
-                       matched_bits = MDS_INODELOCK_LOOKUP;
-
-               if (((bits & matched_bits) == matched_bits) &&
-                   d_lustre_invalid(de))
-                       d_lustre_revalidate(de);
-               ll_lookup_finish_locks(it, de);
-       }
-
-mark:
-       if (it != NULL && it->it_op == IT_GETATTR && rc > 0)
-               ll_statahead_mark(parent, de);
-       return rc;
+       if (d_need_statahead(dir, dentry) <= 0)
+               return 1;
 
-       /*
-        * This part is here to combat evil-evil race in real_lookup on 2.6
-        * kernels.  The race details are: We enter do_lookup() looking for some
-        * name, there is nothing in dcache for this name yet and d_lookup()
-        * returns NULL.  We proceed to real_lookup(), and while we do this,
-        * another process does open on the same file we looking up (most simple
-        * reproducer), open succeeds and the dentry is added. Now back to
-        * us. In real_lookup() we do d_lookup() again and suddenly find the
-        * dentry, so we call d_revalidate on it, but there is no lock, so
-        * without this code we would return 0, but unpatched real_lookup just
-        * returns -ENOENT in such a case instead of retrying the lookup. Once
-        * this is dealt with in real_lookup(), all of this ugly mess can go and
-        * we can just check locks in ->d_revalidate without doing any RPCs
-        * ever.
-        */
-do_lookup:
-       if (it != &lookup_it) {
-               /* MDS_INODELOCK_UPDATE needed for IT_GETATTR case. */
-               if (it->it_op == IT_GETATTR)
-                       lookup_it.it_op = IT_GETATTR;
-               ll_lookup_finish_locks(it, de);
-               it = &lookup_it;
-       }
+       if (lookup_flags & LOOKUP_RCU)
+               return -ECHILD;
 
-       /* Do real lookup here. */
-       op_data = ll_prep_md_op_data(NULL, parent, NULL, de->d_name.name,
-                                    de->d_name.len, 0, (it->it_op & IT_CREAT ?
-                                                        LUSTRE_OPC_CREATE :
-                                                        LUSTRE_OPC_ANY), NULL);
-       if (IS_ERR(op_data))
-               return PTR_ERR(op_data);
-
-       rc = md_intent_lock(exp, op_data, NULL, 0,  it, 0, &req,
-                           ll_md_blocking_ast, 0);
-       if (rc >= 0) {
-               struct mdt_body *mdt_body;
-               struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
-               mdt_body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-
-               if (de->d_inode)
-                       fid = *ll_inode2fid(de->d_inode);
-
-               /* see if we got same inode, if not - return error */
-               if (lu_fid_eq(&fid, &mdt_body->fid1)) {
-                       ll_finish_md_op_data(op_data);
-                       op_data = NULL;
-                       goto revalidate_finish;
-               }
-               ll_intent_release(it);
-       }
-       ll_finish_md_op_data(op_data);
-       GOTO(out, rc = 0);
-
-out_sa:
-       /*
-        * For rc == 1 case, should not return directly to prevent losing
-        * statahead windows; for rc == 0 case, the "lookup" will be done later.
-        */
-       if (it != NULL && it->it_op == IT_GETATTR && rc == 1)
-               ll_statahead_enter(parent, &de, 1);
-       goto mark;
+       do_statahead_enter(dir, &dentry, dentry->d_inode == NULL);
+       ll_statahead_mark(dir, dentry);
+       return 1;
 }
 
 /*
@@ -591,24 +358,13 @@ out_sa:
  */
 int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
 {
-       struct inode *parent = dentry->d_parent->d_inode;
-       int unplug = 0;
+       int rc;
 
-       CDEBUG(D_VFSTRACE, "VFS Op:name=%s,flags=%u\n",
+       CDEBUG(D_VFSTRACE, "VFS Op:name=%s, flags=%u\n",
               dentry->d_name.name, flags);
 
-       if (!(flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) &&
-           ll_need_statahead(parent, dentry) > 0) {
-               if (flags & LOOKUP_RCU)
-                       return -ECHILD;
-
-               if (dentry->d_inode == NULL)
-                       unplug = 1;
-               do_statahead_enter(parent, &dentry, unplug);
-               ll_statahead_mark(parent, dentry);
-       }
-
-       return 1;
+       rc = ll_revalidate_dentry(dentry, flags);
+       return rc;
 }
 
 
index fd0dd20e11704aad77f8ef5b0ec497a9a8e3d60d..7fbc18e3e654a19484b8f7c028f9964256eea72c 100644 (file)
@@ -362,7 +362,7 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash,
                struct ptlrpc_request *request;
                struct md_op_data *op_data;
 
-               op_data = ll_prep_md_op_data(NULL, dir, NULL, NULL, 0, 0,
+               op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0,
                LUSTRE_OPC_ANY, NULL);
                if (IS_ERR(op_data))
                        return (void *)op_data;
index 4c28f39e8b18b583c28edf8aa0b313c7d19045eb..70b48ab30fe87916a7e11eecfc0ce8dad50a8031 100644 (file)
@@ -205,7 +205,7 @@ out:
        return rc;
 }
 
-int ll_md_real_close(struct inode *inode, int flags)
+int ll_md_real_close(struct inode *inode, fmode_t fmode)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
        struct obd_client_handle **och_p;
@@ -213,30 +213,33 @@ int ll_md_real_close(struct inode *inode, int flags)
        __u64 *och_usecount;
        int rc = 0;
 
-       if (flags & FMODE_WRITE) {
+       if (fmode & FMODE_WRITE) {
                och_p = &lli->lli_mds_write_och;
                och_usecount = &lli->lli_open_fd_write_count;
-       } else if (flags & FMODE_EXEC) {
+       } else if (fmode & FMODE_EXEC) {
                och_p = &lli->lli_mds_exec_och;
                och_usecount = &lli->lli_open_fd_exec_count;
        } else {
-               LASSERT(flags & FMODE_READ);
+               LASSERT(fmode & FMODE_READ);
                och_p = &lli->lli_mds_read_och;
                och_usecount = &lli->lli_open_fd_read_count;
        }
 
        mutex_lock(&lli->lli_och_mutex);
-       if (*och_usecount) { /* There are still users of this handle, so
-                               skip freeing it. */
+       if (*och_usecount > 0) {
+               /* There are still users of this handle, so skip
+                * freeing it. */
                mutex_unlock(&lli->lli_och_mutex);
                return 0;
        }
+
        och=*och_p;
        *och_p = NULL;
        mutex_unlock(&lli->lli_och_mutex);
 
-       if (och) { /* There might be a race and somebody have freed this och
-                     already */
+       if (och != NULL) {
+               /* There might be a race and this handle may already
+                  be closed. */
                rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
                                               inode, och, NULL);
        }
@@ -443,8 +446,7 @@ static int ll_intent_file_open(struct file *file, void *lmm,
                                 itp, NULL);
 
 out:
-       ptlrpc_req_finished(itp->d.lustre.it_data);
-       it_clear_disposition(itp, DISP_ENQ_COMPLETE);
+       ptlrpc_req_finished(req);
        ll_intent_drop_lock(itp);
 
        return rc;
@@ -477,7 +479,7 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it,
        och->och_magic = OBD_CLIENT_HANDLE_MAGIC;
        och->och_flags = it->it_flags;
 
-       return md_set_open_replay_data(md_exp, och, req);
+       return md_set_open_replay_data(md_exp, och, it);
 }
 
 int ll_local_open(struct file *file, struct lookup_intent *it,
@@ -812,10 +814,7 @@ struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file,
         * doesn't deal with openhandle, so normal openhandle will be leaked. */
                                LDLM_FL_NO_LRU | LDLM_FL_EXCL);
        ll_finish_md_op_data(op_data);
-       if (req != NULL) {
-               ptlrpc_req_finished(req);
-               it_clear_disposition(&it, DISP_ENQ_COMPLETE);
-       }
+       ptlrpc_req_finished(req);
        if (rc < 0)
                GOTO(out_release_it, rc);
 
@@ -1032,6 +1031,33 @@ int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm,
        return rc;
 }
 
+static bool file_is_noatime(const struct file *file)
+{
+       const struct vfsmount *mnt = file->f_path.mnt;
+       const struct inode *inode = file->f_path.dentry->d_inode;
+
+       /* Adapted from file_accessed() and touch_atime().*/
+       if (file->f_flags & O_NOATIME)
+               return true;
+
+       if (inode->i_flags & S_NOATIME)
+               return true;
+
+       if (IS_NOATIME(inode))
+               return true;
+
+       if (mnt->mnt_flags & (MNT_NOATIME | MNT_READONLY))
+               return true;
+
+       if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+               return true;
+
+       if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+               return true;
+
+       return false;
+}
+
 void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
        struct inode *inode = file->f_dentry->d_inode;
@@ -1051,6 +1077,8 @@ void ll_io_init(struct cl_io *io, const struct file *file, int write)
        } else if (file->f_flags & O_APPEND) {
                io->ci_lockreq = CILR_MANDATORY;
        }
+
+       io->ci_noatime = file_is_noatime(file);
 }
 
 static ssize_t
@@ -2888,7 +2916,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
                        oit.it_op = IT_LOOKUP;
 
                /* Call getattr by fid, so do not provide name at all. */
-               op_data = ll_prep_md_op_data(NULL, dentry->d_parent->d_inode,
+               op_data = ll_prep_md_op_data(NULL, dentry->d_inode,
                                             dentry->d_inode, NULL, 0, 0,
                                             LUSTRE_OPC_ANY, NULL);
                if (IS_ERR(op_data))
index e27efd164fe838bbffbee9913268e45875efb1a5..f67c50829437d41a986759a4a617170dd909e934 100644 (file)
@@ -775,7 +775,7 @@ int ll_local_open(struct file *file,
 int ll_release_openhandle(struct dentry *, struct lookup_intent *);
 int ll_md_close(struct obd_export *md_exp, struct inode *inode,
                struct file *file);
-int ll_md_real_close(struct inode *inode, int flags);
+int ll_md_real_close(struct inode *inode, fmode_t fmode);
 void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data,
                      struct obd_client_handle **och, unsigned long flags);
 void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data);
@@ -1309,7 +1309,7 @@ ll_statahead_mark(struct inode *dir, struct dentry *dentry)
 }
 
 static inline int
-ll_need_statahead(struct inode *dir, struct dentry *dentryp)
+d_need_statahead(struct inode *dir, struct dentry *dentryp)
 {
        struct ll_inode_info  *lli;
        struct ll_dentry_data *ldd;
@@ -1354,7 +1354,7 @@ ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug)
 {
        int ret;
 
-       ret = ll_need_statahead(dir, *dentryp);
+       ret = d_need_statahead(dir, *dentryp);
        if (ret <= 0)
                return ret;
 
index 85c01e155680acb875ff8fd49a88850be56c88c4..7427f69e33b067ec39d39a3ee35161f9427580e3 100644 (file)
@@ -208,7 +208,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                  OBD_CONNECT_LAYOUTLOCK |
                                  OBD_CONNECT_PINGLESS |
                                  OBD_CONNECT_MAX_EASIZE |
-                                 OBD_CONNECT_FLOCK_DEAD;
+                                 OBD_CONNECT_FLOCK_DEAD |
+                                 OBD_CONNECT_DISP_STRIPE;
 
        if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
                data->ocd_connect_flags |= OBD_CONNECT_SOM;
index 93c3744e09ffd121d34cdc4a86ba02b6e30ed623..86ff708c8e3e269d4dc466b2fcb56fb05e658207 100644 (file)
@@ -195,101 +195,107 @@ static void ll_invalidate_negative_children(struct inode *dir)
 int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                       void *data, int flag)
 {
-       int rc;
        struct lustre_handle lockh;
+       int rc;
 
        switch (flag) {
        case LDLM_CB_BLOCKING:
                ldlm_lock2handle(lock, &lockh);
                rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
                if (rc < 0) {
-                       CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
+                       CDEBUG(D_INODE, "ldlm_cli_cancel: rc = %d\n", rc);
                        return rc;
                }
                break;
        case LDLM_CB_CANCELING: {
                struct inode *inode = ll_inode_from_resource_lock(lock);
-               struct ll_inode_info *lli;
                __u64 bits = lock->l_policy_data.l_inodebits.bits;
-               struct lu_fid *fid;
-               ldlm_mode_t mode = lock->l_req_mode;
 
                /* Inode is set to lock->l_resource->lr_lvb_inode
                 * for mdc - bug 24555 */
                LASSERT(lock->l_ast_data == NULL);
 
-               /* Invalidate all dentries associated with this inode */
                if (inode == NULL)
                        break;
 
+               /* Invalidate all dentries associated with this inode */
                LASSERT(lock->l_flags & LDLM_FL_CANCELING);
 
-               if (bits & MDS_INODELOCK_XATTR)
+               if (!fid_res_name_eq(ll_inode2fid(inode),
+                                    &lock->l_resource->lr_name)) {
+                       LDLM_ERROR(lock, "data mismatch with object "DFID"(%p)",
+                                  PFID(ll_inode2fid(inode)), inode);
+                       LBUG();
+               }
+
+               if (bits & MDS_INODELOCK_XATTR) {
                        ll_xattr_cache_destroy(inode);
+                       bits &= ~MDS_INODELOCK_XATTR;
+               }
 
                /* For OPEN locks we differentiate between lock modes
                 * LCK_CR, LCK_CW, LCK_PR - bug 22891 */
-               if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
-                           MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM))
-                       ll_have_md_lock(inode, &bits, LCK_MINMODE);
-
                if (bits & MDS_INODELOCK_OPEN)
-                       ll_have_md_lock(inode, &bits, mode);
-
-               fid = ll_inode2fid(inode);
-               if (!fid_res_name_eq(fid, &lock->l_resource->lr_name))
-                       LDLM_ERROR(lock, "data mismatch with object "
-                                  DFID" (%p)", PFID(fid), inode);
+                       ll_have_md_lock(inode, &bits, lock->l_req_mode);
 
                if (bits & MDS_INODELOCK_OPEN) {
-                       int flags = 0;
+                       fmode_t fmode;
+
                        switch (lock->l_req_mode) {
                        case LCK_CW:
-                               flags = FMODE_WRITE;
+                               fmode = FMODE_WRITE;
                                break;
                        case LCK_PR:
-                               flags = FMODE_EXEC;
+                               fmode = FMODE_EXEC;
                                break;
                        case LCK_CR:
-                               flags = FMODE_READ;
+                               fmode = FMODE_READ;
                                break;
                        default:
-                               CERROR("Unexpected lock mode for OPEN lock "
-                                      "%d, inode %ld\n", lock->l_req_mode,
-                                      inode->i_ino);
+                               LDLM_ERROR(lock, "bad lock mode for OPEN lock");
+                               LBUG();
                        }
-                       ll_md_real_close(inode, flags);
+
+                       ll_md_real_close(inode, fmode);
                }
 
-               lli = ll_i2info(inode);
+               if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
+                           MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM))
+                       ll_have_md_lock(inode, &bits, LCK_MINMODE);
+
                if (bits & MDS_INODELOCK_LAYOUT) {
-                       struct cl_object_conf conf = { { 0 } };
+                       struct cl_object_conf conf = {
+                               .coc_opc = OBJECT_CONF_INVALIDATE,
+                               .coc_inode = inode,
+                       };
 
-                       conf.coc_opc = OBJECT_CONF_INVALIDATE;
-                       conf.coc_inode = inode;
                        rc = ll_layout_conf(inode, &conf);
-                       if (rc)
-                               CDEBUG(D_INODE, "invaliding layout %d.\n", rc);
+                       if (rc < 0)
+                               CDEBUG(D_INODE, "cannot invalidate layout of "
+                                      DFID": rc = %d\n",
+                                      PFID(ll_inode2fid(inode)), rc);
                }
 
                if (bits & MDS_INODELOCK_UPDATE) {
+                       struct ll_inode_info *lli = ll_i2info(inode);
+
                        spin_lock(&lli->lli_lock);
                        lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK;
                        spin_unlock(&lli->lli_lock);
                }
 
-               if (S_ISDIR(inode->i_mode) &&
-                    (bits & MDS_INODELOCK_UPDATE)) {
+               if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) {
                        CDEBUG(D_INODE, "invalidating inode %lu\n",
                               inode->i_ino);
                        truncate_inode_pages(inode->i_mapping, 0);
                        ll_invalidate_negative_children(inode);
                }
 
-               if (inode->i_sb->s_root &&
-                   inode != inode->i_sb->s_root->d_inode &&
-                   (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)))
+               if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) &&
+                   inode->i_sb->s_root != NULL &&
+                   inode != inode->i_sb->s_root->d_inode)
                        ll_invalidate_aliases(inode);
+
                iput(inode);
                break;
        }
index 56dedceaf0a0c519adf0c4bb9d7e75efc5c1c364..9ba5a0a573909bb022f3426aa52ecadef2515b9d 100644 (file)
@@ -119,7 +119,6 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm,
        CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n",
               PFID(&body->fid1), tgt->ltd_idx);
 
-       it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
        rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it,
                            flags, &req, cb_blocking, extra_lock_flags);
        if (rc)
index 1bddd8f62fbfbcf6681599b3cca8be893df49bc2..3ba0a0a1d945f9be02cf4c1a9238acb6cd8e1530 100644 (file)
@@ -1744,7 +1744,6 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
        it->d.lustre.it_data = NULL;
        fid1 = body->fid1;
 
-       it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
        ptlrpc_req_finished(req);
 
        tgt = lmv_find_target(lmv, &fid1);
@@ -2593,7 +2592,7 @@ int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
 
 int lmv_set_open_replay_data(struct obd_export *exp,
                             struct obd_client_handle *och,
-                            struct ptlrpc_request *open_req)
+                            struct lookup_intent *it)
 {
        struct obd_device       *obd = exp->exp_obd;
        struct lmv_obd    *lmv = &obd->u.lmv;
@@ -2603,7 +2602,7 @@ int lmv_set_open_replay_data(struct obd_export *exp,
        if (IS_ERR(tgt))
                return PTR_ERR(tgt);
 
-       return md_set_open_replay_data(tgt->ltd_exp, och, open_req);
+       return md_set_open_replay_data(tgt->ltd_exp, och, it);
 }
 
 int lmv_clear_open_replay_data(struct obd_export *exp,
index 5a6ab70ed0a1a3a4126e836a3b144e4d880bf5d2..65133ea308b6b6c1c8e3acae995c55960a1700f1 100644 (file)
@@ -194,6 +194,7 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
                sub_io->ci_lockreq = io->ci_lockreq;
                sub_io->ci_type    = io->ci_type;
                sub_io->ci_no_srvlock = io->ci_no_srvlock;
+               sub_io->ci_noatime = io->ci_noatime;
 
                lov_sub_enter(sub);
                result = cl_io_sub_init(sub->sub_env, sub_io,
index fc21777b53c622dce5abff995d1fb40d11d4967e..c78bf003c2c524e8e8104e9ed0c23c38f318c002 100644 (file)
@@ -122,7 +122,7 @@ int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md);
 
 int mdc_set_open_replay_data(struct obd_export *exp,
                             struct obd_client_handle *och,
-                            struct ptlrpc_request *open_req);
+                            struct lookup_intent *it);
 
 int mdc_clear_open_replay_data(struct obd_export *exp,
                               struct obd_client_handle *och);
index 288a41ec60c9153c1feadeaddf9aba7e9398692b..b0d0e2a1744ef8e8a738a9af3395517679111ed1 100644 (file)
 #define DEBUG_SUBSYSTEM S_MDC
 
 # include <linux/module.h>
-# include <linux/pagemap.h>
-# include <linux/miscdevice.h>
 
-#include <lustre_acl.h>
+#include <linux/lustre_intent.h>
+#include <obd.h>
 #include <obd_class.h>
 #include <lustre_dlm.h>
-/* fid_res_name_eq() */
-#include <lustre_fid.h>
-#include <lprocfs_status.h>
+#include <lustre_fid.h> /* fid_res_name_eq() */
+#include <lustre_mdc.h>
+#include <lustre_net.h>
+#include <lustre_req_layout.h>
 #include "mdc_internal.h"
 
 struct mdc_getattr_args {
@@ -160,6 +160,8 @@ ldlm_mode_t mdc_lock_match(struct obd_export *exp, __u64 flags,
        ldlm_mode_t rc;
 
        fid_build_reg_res_name(fid, &res_id);
+       /* LU-4405: Clear bits not supported by server */
+       policy->l_inodebits.bits &= exp_connect_ibits(exp);
        rc = ldlm_lock_match(class_exp2obd(exp)->obd_namespace, flags,
                             &res_id, type, policy, mode, lockh, 0);
        return rc;
@@ -334,9 +336,9 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp,
                             max(lmmsize, obddev->u.cli.cl_default_mds_easize));
 
        rc = ldlm_prep_enqueue_req(exp, req, &cancels, count);
-       if (rc) {
+       if (rc < 0) {
                ptlrpc_request_free(req);
-               return NULL;
+               return ERR_PTR(rc);
        }
 
        spin_lock(&req->rq_lock);
@@ -639,7 +641,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                         * happens immediately after swabbing below, new reply
                         * is swabbed by that handler correctly.
                         */
-                       mdc_set_open_replay_data(NULL, NULL, req);
+                       mdc_set_open_replay_data(NULL, NULL, it);
                }
 
                if ((body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) {
@@ -751,6 +753,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                /* install lvb_data */
                lock_res_and_lock(lock);
                if (lock->l_lvb_data == NULL) {
+                       lock->l_lvb_type = LVB_T_LAYOUT;
                        lock->l_lvb_data = lmm;
                        lock->l_lvb_len = lvb_len;
                        lmm = NULL;
@@ -966,7 +969,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
        if (fid_is_sane(&op_data->op_fid2) &&
            it->it_create_mode & M_CHECK_STALE &&
            it->it_op != IT_GETATTR) {
-               it_set_disposition(it, DISP_ENQ_COMPLETE);
 
                /* Also: did we find the same inode? */
                /* sever can return one of two fids:
@@ -1061,7 +1063,23 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
                fid_build_reg_res_name(fid, &res_id);
                switch (it->it_op) {
                case IT_GETATTR:
-                       policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
+                       /* File attributes are held under multiple bits:
+                        * nlink is under lookup lock, size and times are
+                        * under UPDATE lock and recently we've also got
+                        * a separate permissions lock for owner/group/acl that
+                        * were protected by lookup lock before.
+                        * Getattr must provide all of that information,
+                        * so we need to ensure we have all of those locks.
+                        * Unfortunately, if the bits are split across multiple
+                        * locks, there's no easy way to match all of them here,
+                        * so an extra RPC would be performed to fetch all
+                        * of those bits at once for now. */
+                       /* For new MDTs(> 2.4), UPDATE|PERM should be enough,
+                        * but for old MDTs (< 2.4), permission is covered
+                        * by LOOKUP lock, so it needs to match all bits here.*/
+                       policy.l_inodebits.bits = MDS_INODELOCK_UPDATE |
+                                                 MDS_INODELOCK_LOOKUP |
+                                                 MDS_INODELOCK_PERM;
                        break;
                case IT_LAYOUT:
                        policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT;
@@ -1070,10 +1088,11 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
                        policy.l_inodebits.bits = MDS_INODELOCK_LOOKUP;
                        break;
                }
-               mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
-                                      LDLM_FL_BLOCK_GRANTED, &res_id,
+
+               mode = mdc_lock_match(exp, LDLM_FL_BLOCK_GRANTED, fid,
                                       LDLM_IBITS, &policy,
-                                      LCK_CR|LCK_CW|LCK_PR|LCK_PW, &lockh, 0);
+                                     LCK_CR | LCK_CW | LCK_PR | LCK_PW,
+                                     &lockh);
        }
 
        if (mode) {
@@ -1120,6 +1139,12 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
                    ldlm_blocking_callback cb_blocking,
                    __u64 extra_lock_flags)
 {
+       struct ldlm_enqueue_info einfo = {
+               .ei_type        = LDLM_IBITS,
+               .ei_mode        = it_to_lock_mode(it),
+               .ei_cb_bl       = cb_blocking,
+               .ei_cb_cp       = ldlm_completion_ast,
+       };
        struct lustre_handle lockh;
        int rc = 0;
 
@@ -1145,42 +1170,19 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
                        return rc;
        }
 
-       /* lookup_it may be called only after revalidate_it has run, because
-        * revalidate_it cannot return errors, only zero.  Returning zero causes
-        * this call to lookup, which *can* return an error.
-        *
-        * We only want to execute the request associated with the intent one
-        * time, however, so don't send the request again.  Instead, skip past
-        * this and use the request from revalidate.  In this case, revalidate
-        * never dropped its reference, so the refcounts are all OK */
-       if (!it_disposition(it, DISP_ENQ_COMPLETE)) {
-               struct ldlm_enqueue_info einfo = {
-                       .ei_type        = LDLM_IBITS,
-                       .ei_mode        = it_to_lock_mode(it),
-                       .ei_cb_bl       = cb_blocking,
-                       .ei_cb_cp       = ldlm_completion_ast,
-               };
-
-               /* For case if upper layer did not alloc fid, do it now. */
-               if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
-                       rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
-                       if (rc < 0) {
-                               CERROR("Can't alloc new fid, rc %d\n", rc);
-                               return rc;
-                       }
-               }
-               rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh,
-                                lmm, lmmsize, NULL, extra_lock_flags);
-               if (rc < 0)
+       /* For case if upper layer did not alloc fid, do it now. */
+       if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
+               rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
+               if (rc < 0) {
+                       CERROR("Can't alloc new fid, rc %d\n", rc);
                        return rc;
-       } else if (!fid_is_sane(&op_data->op_fid2) ||
-                  !(it->it_create_mode & M_CHECK_STALE)) {
-               /* DISP_ENQ_COMPLETE set means there is extra reference on
-                * request referenced from this intent, saved for subsequent
-                * lookup.  This path is executed when we proceed to this
-                * lookup, so we clear DISP_ENQ_COMPLETE */
-               it_clear_disposition(it, DISP_ENQ_COMPLETE);
+               }
        }
+       rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh, lmm, lmmsize, NULL,
+                        extra_lock_flags);
+       if (rc < 0)
+               return rc;
+
        *reqp = it->d.lustre.it_data;
        rc = mdc_finish_intent_lock(exp, *reqp, op_data, it, &lockh);
        return rc;
@@ -1262,8 +1264,8 @@ int mdc_intent_getattr_async(struct obd_export *exp,
 
        fid_build_reg_res_name(&op_data->op_fid1, &res_id);
        req = mdc_intent_getattr_pack(exp, it, op_data);
-       if (!req)
-               return -ENOMEM;
+       if (IS_ERR(req))
+               return PTR_ERR(req);
 
        rc = mdc_enter_request(&obddev->u.cli);
        if (rc != 0) {
index 1aea154e122be7fc47a5ca731d6db9e5b632652b..d79aa1641feffa4161f6edc533aa300d18a5fb93 100644 (file)
@@ -165,6 +165,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
                        req->rq_cb_data = *mod;
                        (*mod)->mod_open_req = req;
                        req->rq_commit_cb = mdc_commit_open;
+                       (*mod)->mod_is_create = true;
                        /**
                         * Take an extra reference on \var mod, it protects \var
                         * mod from being freed on eviction (commit callback is
index 17c8e1486daa7ec36e702356c674fb73bed98f73..d9ddb393491964163d33b338d96b45866fab1d89 100644 (file)
@@ -722,11 +722,12 @@ void mdc_commit_open(struct ptlrpc_request *req)
 
 int mdc_set_open_replay_data(struct obd_export *exp,
                             struct obd_client_handle *och,
-                            struct ptlrpc_request *open_req)
+                            struct lookup_intent *it)
 {
        struct md_open_data   *mod;
        struct mdt_rec_create *rec;
        struct mdt_body       *body;
+       struct ptlrpc_request *open_req = it->d.lustre.it_data;
        struct obd_import     *imp = open_req->rq_import;
 
        if (!open_req->rq_replay)
@@ -760,6 +761,8 @@ int mdc_set_open_replay_data(struct obd_export *exp,
                spin_lock(&open_req->rq_lock);
                och->och_mod = mod;
                mod->mod_och = och;
+               mod->mod_is_create = it_disposition(it, DISP_OPEN_CREATE) ||
+                                    it_disposition(it, DISP_OPEN_STRIPE);
                mod->mod_open_req = open_req;
                open_req->rq_cb_data = mod;
                open_req->rq_commit_cb = mdc_commit_open;
@@ -780,6 +783,23 @@ int mdc_set_open_replay_data(struct obd_export *exp,
        return 0;
 }
 
+static void mdc_free_open(struct md_open_data *mod)
+{
+       int committed = 0;
+
+       if (mod->mod_is_create == 0 &&
+           imp_connect_disp_stripe(mod->mod_open_req->rq_import))
+               committed = 1;
+
+       LASSERT(mod->mod_open_req->rq_replay == 0);
+
+       DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, "free open request\n");
+
+       ptlrpc_request_committed(mod->mod_open_req, committed);
+       if (mod->mod_close_req)
+               ptlrpc_request_committed(mod->mod_close_req, committed);
+}
+
 int mdc_clear_open_replay_data(struct obd_export *exp,
                               struct obd_client_handle *och)
 {
@@ -793,6 +813,8 @@ int mdc_clear_open_replay_data(struct obd_export *exp,
                return 0;
 
        LASSERT(mod != LP_POISON);
+       LASSERT(mod->mod_open_req != NULL);
+       mdc_free_open(mod);
 
        mod->mod_och = NULL;
        och->och_mod = NULL;
@@ -991,6 +1013,9 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data,
        if (mod) {
                if (rc != 0)
                        mod->mod_close_req = NULL;
+               LASSERT(mod->mod_open_req != NULL);
+               mdc_free_open(mod);
+
                /* Since now, mod is accessed through setattr req only,
                 * thus DW req does not keep a reference on mod anymore. */
                obd_mod_put(mod);
index d27f0411d355e913f9e873f136545c4d75414fc6..169c9ed56521abdbf32d0c8902bcee8ae98d7f9c 100644 (file)
@@ -1010,6 +1010,8 @@ struct obd_import *class_new_import(struct obd_device *obd)
        INIT_LIST_HEAD(&imp->imp_replay_list);
        INIT_LIST_HEAD(&imp->imp_sending_list);
        INIT_LIST_HEAD(&imp->imp_delayed_list);
+       INIT_LIST_HEAD(&imp->imp_committed_list);
+       imp->imp_replay_cursor = &imp->imp_committed_list;
        spin_lock_init(&imp->imp_lock);
        imp->imp_last_success_conn = 0;
        imp->imp_state = LUSTRE_IMP_NEW;
index 6e7d2e5610674964de9cc6d0b7a8a9128c2e04ed..1432dd74fe95099504426d035b7d9b421e3a3fc6 100644 (file)
@@ -99,6 +99,7 @@ static const char * const obd_connect_names[] = {
        "short_io",
        "pingless",
        "flock_deadlock",
+       "disp_stripe",
        "unknown",
        NULL
 };
index b92a02efad439a12206cd3c455bc4629d1ea1ec2..af25c19c88fa4cdce6fa6ace74921a2ebde636c1 100644 (file)
@@ -2394,6 +2394,12 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
                 * really sending the RPC. */
        case OES_TRUNC:
                /* race with truncate, page will be redirtied */
+       case OES_ACTIVE:
+               /* The extent is active so we need to abort and let the caller
+                * re-dirty the page. If we continued on here, and we were the
+                * one making the extent active, we could deadlock waiting for
+                * the page writeback to clear but it won't because the extent
+                * is active and won't be written out. */
                GOTO(out, rc = -EAGAIN);
        default:
                break;
index 777ae24bbfff465aa91c2e5169da20c662300e6a..5f3c545418d11cd765068ae6f3d5409e82618c5f 100644 (file)
@@ -512,19 +512,15 @@ static int osc_io_read_start(const struct lu_env *env,
        struct osc_io    *oio   = cl2osc_io(env, slice);
        struct cl_object *obj   = slice->cis_obj;
        struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
-       int           result = 0;
+       int rc = 0;
 
-       if (oio->oi_lockless == 0) {
+       if (oio->oi_lockless == 0 && !slice->cis_io->ci_noatime) {
                cl_object_attr_lock(obj);
-               result = cl_object_attr_get(env, obj, attr);
-               if (result == 0) {
-                       attr->cat_atime = LTIME_S(CURRENT_TIME);
-                       result = cl_object_attr_set(env, obj, attr,
-                                                   CAT_ATIME);
-               }
+               attr->cat_atime = LTIME_S(CURRENT_TIME);
+               rc = cl_object_attr_set(env, obj, attr, CAT_ATIME);
                cl_object_attr_unlock(obj);
        }
-       return result;
+       return rc;
 }
 
 static int osc_io_write_start(const struct lu_env *env,
index 6045a78a2baa21d309bbc3ba7712f2d23996527a..f395ae4ec94497ad35dc48b05a37c91d4953a438 100644 (file)
@@ -51,11 +51,8 @@ int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
 
                oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
                if (oqi) {
-                       obd_uid id = oqi->oqi_id;
-
-                       LASSERTF(id == qid[type],
-                                "The ids don't match %u != %u\n",
-                                id, qid[type]);
+                       /* do not try to access oqi here, it could have been
+                        * freed by osc_quota_setdq() */
 
                        /* the slot is busy, the user is about to run out of
                         * quota space on this OST */
index eb33bb7c86ae8bd61c1196dbcd4e30c5c43abb62..4c9e006950878afdb1660d26683cd94be219e053 100644 (file)
@@ -48,6 +48,7 @@
 #include "ptlrpc_internal.h"
 
 static int ptlrpc_send_new_req(struct ptlrpc_request *req);
+static int ptlrpcd_check_work(struct ptlrpc_request *req);
 
 /**
  * Initialize passed in client structure \a cl.
@@ -1190,7 +1191,9 @@ static int after_reply(struct ptlrpc_request *req)
                 * will roundup it */
                req->rq_replen       = req->rq_nob_received;
                req->rq_nob_received = 0;
+               spin_lock(&req->rq_lock);
                req->rq_resend       = 1;
+               spin_unlock(&req->rq_lock);
                return 0;
        }
 
@@ -1313,7 +1316,11 @@ static int after_reply(struct ptlrpc_request *req)
                        /** version recovery */
                        ptlrpc_save_versions(req);
                        ptlrpc_retain_replayable_request(req, imp);
-               } else if (req->rq_commit_cb != NULL) {
+               } else if (req->rq_commit_cb != NULL &&
+                          list_empty(&req->rq_replay_list)) {
+                       /* NB: don't call rq_commit_cb if it's already on
+                        * rq_replay_list, ptlrpc_free_committed() will call
+                        * it later, see LU-3618 for details */
                        spin_unlock(&imp->imp_lock);
                        req->rq_commit_cb(req);
                        spin_lock(&imp->imp_lock);
@@ -1408,7 +1415,9 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
                        req->rq_status = rc;
                        return 1;
                } else {
+                       spin_lock(&req->rq_lock);
                        req->rq_wait_ctx = 1;
+                       spin_unlock(&req->rq_lock);
                        return 0;
                }
        }
@@ -1423,7 +1432,9 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
        rc = ptl_send_rpc(req, 0);
        if (rc) {
                DEBUG_REQ(D_HA, req, "send failed (%d); expect timeout", rc);
+               spin_lock(&req->rq_lock);
                req->rq_net_err = 1;
+               spin_unlock(&req->rq_lock);
                return rc;
        }
        return 0;
@@ -1688,6 +1699,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
                                        spin_lock(&req->rq_lock);
                                        req->rq_net_err = 1;
                                        spin_unlock(&req->rq_lock);
+                                       continue;
                                }
                                /* need to reset the timeout */
                                force_timer_recalc = 1;
@@ -1773,6 +1785,10 @@ interpret:
 
                ptlrpc_req_interpret(env, req, req->rq_status);
 
+               if (ptlrpcd_check_work(req)) {
+                       atomic_dec(&set->set_remaining);
+                       continue;
+               }
                ptlrpc_rqphase_move(req, RQ_PHASE_COMPLETE);
 
                CDEBUG(req->rq_reqmsg != NULL ? D_RPCTRACE : 0,
@@ -2360,6 +2376,39 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 }
 EXPORT_SYMBOL(ptlrpc_unregister_reply);
 
+static void ptlrpc_free_request(struct ptlrpc_request *req)
+{
+       spin_lock(&req->rq_lock);
+       req->rq_replay = 0;
+       spin_unlock(&req->rq_lock);
+
+       if (req->rq_commit_cb != NULL)
+               req->rq_commit_cb(req);
+       list_del_init(&req->rq_replay_list);
+
+       __ptlrpc_req_finished(req, 1);
+}
+
+/**
+ * the request is committed and dropped from the replay list of its import
+ */
+void ptlrpc_request_committed(struct ptlrpc_request *req, int force)
+{
+       struct obd_import       *imp = req->rq_import;
+
+       spin_lock(&imp->imp_lock);
+       if (list_empty(&req->rq_replay_list)) {
+               spin_unlock(&imp->imp_lock);
+               return;
+       }
+
+       if (force || req->rq_transno <= imp->imp_peer_committed_transno)
+               ptlrpc_free_request(req);
+
+       spin_unlock(&imp->imp_lock);
+}
+EXPORT_SYMBOL(ptlrpc_request_committed);
+
 /**
  * Iterates through replay_list on import and prunes
  * all requests have transno smaller than last_committed for the
@@ -2370,9 +2419,9 @@ EXPORT_SYMBOL(ptlrpc_unregister_reply);
  */
 void ptlrpc_free_committed(struct obd_import *imp)
 {
-       struct list_head *tmp, *saved;
-       struct ptlrpc_request *req;
+       struct ptlrpc_request *req, *saved;
        struct ptlrpc_request *last_req = NULL; /* temporary fire escape */
+       bool                   skip_committed_list = true;
 
        LASSERT(imp != NULL);
 
@@ -2388,13 +2437,15 @@ void ptlrpc_free_committed(struct obd_import *imp)
        CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n",
               imp->imp_obd->obd_name, imp->imp_peer_committed_transno,
               imp->imp_generation);
+
+       if (imp->imp_generation != imp->imp_last_generation_checked)
+               skip_committed_list = false;
+
        imp->imp_last_transno_checked = imp->imp_peer_committed_transno;
        imp->imp_last_generation_checked = imp->imp_generation;
 
-       list_for_each_safe(tmp, saved, &imp->imp_replay_list) {
-               req = list_entry(tmp, struct ptlrpc_request,
-                                    rq_replay_list);
-
+       list_for_each_entry_safe(req, saved, &imp->imp_replay_list,
+                                rq_replay_list) {
                /* XXX ok to remove when 1357 resolved - rread 05/29/03  */
                LASSERT(req != last_req);
                last_req = req;
@@ -2408,27 +2459,34 @@ void ptlrpc_free_committed(struct obd_import *imp)
                        GOTO(free_req, 0);
                }
 
-               if (req->rq_replay) {
-                       DEBUG_REQ(D_RPCTRACE, req, "keeping (FL_REPLAY)");
-                       continue;
-               }
-
                /* not yet committed */
                if (req->rq_transno > imp->imp_peer_committed_transno) {
                        DEBUG_REQ(D_RPCTRACE, req, "stopping search");
                        break;
                }
 
+               if (req->rq_replay) {
+                       DEBUG_REQ(D_RPCTRACE, req, "keeping (FL_REPLAY)");
+                       list_move_tail(&req->rq_replay_list,
+                                      &imp->imp_committed_list);
+                       continue;
+               }
+
                DEBUG_REQ(D_INFO, req, "commit (last_committed "LPU64")",
                          imp->imp_peer_committed_transno);
 free_req:
-               spin_lock(&req->rq_lock);
-               req->rq_replay = 0;
-               spin_unlock(&req->rq_lock);
-               if (req->rq_commit_cb != NULL)
-                       req->rq_commit_cb(req);
-               list_del_init(&req->rq_replay_list);
-               __ptlrpc_req_finished(req, 1);
+               ptlrpc_free_request(req);
+       }
+       if (skip_committed_list)
+               return;
+
+       list_for_each_entry_safe(req, saved, &imp->imp_committed_list,
+                                rq_replay_list) {
+               LASSERT(req->rq_transno != 0);
+               if (req->rq_import_generation < imp->imp_generation) {
+                       DEBUG_REQ(D_RPCTRACE, req, "free stale open request");
+                       ptlrpc_free_request(req);
+               }
        }
 }
 
@@ -2904,22 +2962,50 @@ EXPORT_SYMBOL(ptlrpc_sample_next_xid);
  *    have delay before it really runs by ptlrpcd thread.
  */
 struct ptlrpc_work_async_args {
-       __u64   magic;
        int   (*cb)(const struct lu_env *, void *);
        void   *cbdata;
 };
 
-#define PTLRPC_WORK_MAGIC 0x6655436b676f4f44ULL /* magic code */
+static void ptlrpcd_add_work_req(struct ptlrpc_request *req)
+{
+       /* re-initialize the req */
+       req->rq_timeout         = obd_timeout;
+       req->rq_sent            = cfs_time_current_sec();
+       req->rq_deadline        = req->rq_sent + req->rq_timeout;
+       req->rq_reply_deadline  = req->rq_deadline;
+       req->rq_phase           = RQ_PHASE_INTERPRET;
+       req->rq_next_phase      = RQ_PHASE_COMPLETE;
+       req->rq_xid             = ptlrpc_next_xid();
+       req->rq_import_generation = req->rq_import->imp_generation;
+
+       ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
+}
 
 static int work_interpreter(const struct lu_env *env,
                            struct ptlrpc_request *req, void *data, int rc)
 {
        struct ptlrpc_work_async_args *arg = data;
 
-       LASSERT(arg->magic == PTLRPC_WORK_MAGIC);
+       LASSERT(ptlrpcd_check_work(req));
        LASSERT(arg->cb != NULL);
 
-       return arg->cb(env, arg->cbdata);
+       rc = arg->cb(env, arg->cbdata);
+
+       list_del_init(&req->rq_set_chain);
+       req->rq_set = NULL;
+
+       if (atomic_dec_return(&req->rq_refcount) > 1) {
+               atomic_set(&req->rq_refcount, 2);
+               ptlrpcd_add_work_req(req);
+       }
+       return rc;
+}
+
+static int worker_format;
+
+static int ptlrpcd_check_work(struct ptlrpc_request *req)
+{
+       return req->rq_pill.rc_fmt == (void *)&worker_format;
 }
 
 /**
@@ -2952,6 +3038,7 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
        req->rq_receiving_reply = 0;
        req->rq_must_unlink = 0;
        req->rq_no_delay = req->rq_no_resend = 1;
+       req->rq_pill.rc_fmt = (void *)&worker_format;
 
        spin_lock_init(&req->rq_lock);
        INIT_LIST_HEAD(&req->rq_list);
@@ -2965,7 +3052,6 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
 
        CLASSERT(sizeof(*args) <= sizeof(req->rq_async_args));
        args = ptlrpc_req_async_args(req);
-       args->magic  = PTLRPC_WORK_MAGIC;
        args->cb     = cb;
        args->cbdata = cbdata;
 
@@ -2995,25 +3081,8 @@ int ptlrpcd_queue_work(void *handler)
         * req as opaque data. - Jinshan
         */
        LASSERT(atomic_read(&req->rq_refcount) > 0);
-       if (atomic_read(&req->rq_refcount) > 1)
-               return -EBUSY;
-
-       if (atomic_inc_return(&req->rq_refcount) > 2) { /* race */
-               atomic_dec(&req->rq_refcount);
-               return -EBUSY;
-       }
-
-       /* re-initialize the req */
-       req->rq_timeout = obd_timeout;
-       req->rq_sent       = cfs_time_current_sec();
-       req->rq_deadline       = req->rq_sent + req->rq_timeout;
-       req->rq_reply_deadline = req->rq_deadline;
-       req->rq_phase     = RQ_PHASE_INTERPRET;
-       req->rq_next_phase     = RQ_PHASE_COMPLETE;
-       req->rq_xid         = ptlrpc_next_xid();
-       req->rq_import_generation = req->rq_import->imp_generation;
-
-       ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
+       if (atomic_inc_return(&req->rq_refcount) == 2)
+               ptlrpcd_add_work_req(req);
        return 0;
 }
 EXPORT_SYMBOL(ptlrpcd_queue_work);
index 82db0ed606529f57d1540d02baf6934f78ca5b42..537aa6204a516d0e3f199011bfd257339c4dee0f 100644 (file)
@@ -560,17 +560,30 @@ static int ptlrpc_first_transno(struct obd_import *imp, __u64 *transno)
        struct ptlrpc_request *req;
        struct list_head *tmp;
 
-       if (list_empty(&imp->imp_replay_list))
-               return 0;
-       tmp = imp->imp_replay_list.next;
-       req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
-       *transno = req->rq_transno;
-       if (req->rq_transno == 0) {
-               DEBUG_REQ(D_ERROR, req, "zero transno in replay");
-               LBUG();
+       /* The requests in committed_list always have smaller transnos than
+        * the requests in replay_list */
+       if (!list_empty(&imp->imp_committed_list)) {
+               tmp = imp->imp_committed_list.next;
+               req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+               *transno = req->rq_transno;
+               if (req->rq_transno == 0) {
+                       DEBUG_REQ(D_ERROR, req,
+                                 "zero transno in committed_list");
+                       LBUG();
+               }
+               return 1;
        }
-
-       return 1;
+       if (!list_empty(&imp->imp_replay_list)) {
+               tmp = imp->imp_replay_list.next;
+               req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+               *transno = req->rq_transno;
+               if (req->rq_transno == 0) {
+                       DEBUG_REQ(D_ERROR, req, "zero transno in replay_list");
+                       LBUG();
+               }
+               return 1;
+       }
+       return 0;
 }
 
 /**
index 1e94597eaea5c5a15db605dfc395a0af98365b3b..a47a8d807d5b4c52d19e3755c56e5933d35c0ba9 100644 (file)
@@ -511,7 +511,9 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
                CDEBUG(D_HA, "muting rpc for failed imp obd %s\n",
                       request->rq_import->imp_obd->obd_name);
                /* this prevents us from waiting in ptlrpc_queue_wait */
+               spin_lock(&request->rq_lock);
                request->rq_err = 1;
+               spin_unlock(&request->rq_lock);
                request->rq_status = -ENODEV;
                return -ENODEV;
        }
@@ -553,7 +555,9 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
                        if (rc) {
                                /* this prevents us from looping in
                                 * ptlrpc_queue_wait */
+                               spin_lock(&request->rq_lock);
                                request->rq_err = 1;
+                               spin_unlock(&request->rq_lock);
                                request->rq_status = rc;
                                GOTO(cleanup_bulk, rc);
                        }
index 84c39e083ea4bef97acfdabb2d2424cd76540b58..48ae328ce24ec138063647ab68b5e824c4a6b8a4 100644 (file)
@@ -105,24 +105,59 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
         * imp_lock is being held by ptlrpc_replay, but it's not. it's
         * just a little race...
         */
-       list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+
+       /* Replay all the committed open requests on committed_list first */
+       if (!list_empty(&imp->imp_committed_list)) {
+               tmp = imp->imp_committed_list.prev;
                req = list_entry(tmp, struct ptlrpc_request,
                                     rq_replay_list);
 
-               /* If need to resend the last sent transno (because a
-                  reconnect has occurred), then stop on the matching
-                  req and send it again. If, however, the last sent
-                  transno has been committed then we continue replay
-                  from the next request. */
+               /* The last request on committed_list hasn't been replayed */
                if (req->rq_transno > last_transno) {
-                       if (imp->imp_resend_replay)
-                               lustre_msg_add_flags(req->rq_reqmsg,
-                                                    MSG_RESENT);
-                       break;
+                       /* Since the imp_committed_list is immutable before
+                        * all of it's requests being replayed, it's safe to
+                        * use a cursor to accelerate the search */
+                       imp->imp_replay_cursor = imp->imp_replay_cursor->next;
+
+                       while (imp->imp_replay_cursor !=
+                              &imp->imp_committed_list) {
+                               req = list_entry(imp->imp_replay_cursor,
+                                                struct ptlrpc_request,
+                                                rq_replay_list);
+                               if (req->rq_transno > last_transno)
+                                       break;
+
+                               req = NULL;
+                               imp->imp_replay_cursor =
+                                       imp->imp_replay_cursor->next;
+                       }
+               } else {
+                       /* All requests on committed_list have been replayed */
+                       imp->imp_replay_cursor = &imp->imp_committed_list;
+                       req = NULL;
+               }
+       }
+
+       /* All the requests in committed list have been replayed, let's replay
+        * the imp_replay_list */
+       if (req == NULL) {
+               list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+                       req = list_entry(tmp, struct ptlrpc_request,
+                                        rq_replay_list);
+
+                       if (req->rq_transno > last_transno)
+                               break;
+                       req = NULL;
                }
-               req = NULL;
        }
 
+       /* If need to resend the last sent transno (because a reconnect
+        * has occurred), then stop on the matching req and send it again.
+        * If, however, the last sent transno has been committed then we
+        * continue replay from the next request. */
+       if (req != NULL && imp->imp_resend_replay)
+               lustre_msg_add_flags(req->rq_reqmsg, MSG_RESENT);
+
        spin_lock(&imp->imp_lock);
        imp->imp_resend_replay = 0;
        spin_unlock(&imp->imp_lock);
index d8ea25486a331b1ebbe613b15707c9d70546bba0..31b269a5fff768bb7fff82edfca35ead48c93fe7 100644 (file)
@@ -307,7 +307,7 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
 }
 
 static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
-                               void *accel_priv)
+                               void *accel_priv, select_queue_fallback_t fallback)
 {
        return (u16)smp_processor_id();
 }
index bdaec8d2ca0c18f0562c76fb8fbaaa8e45d4aa2e..2a98a2153e1646a189ef07c2074309bb21cd2d82 100644 (file)
  *      driver will use this memory instead of kernel memory for pools. This
  *      allows 32bit userspace application to access the buffers, but also
  *      requires all received packets to be copied.
- *  CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
- *      This kernel config option allows the user to control the number of
- *      packet and work queue buffers allocated by the driver. If this is zero,
- *      the driver uses the default from below.
  *  USE_SKBUFFS_IN_HW
  *      Tells the driver to populate the packet buffers with kernel skbuffs.
  *      This allows the driver to receive packets without copying them. It also
index 199059d64c9b56796a8a3fb3cf4157ed3ee71ab5..55c13481a56a70d773f15632f20d66fdeb5cbd20 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <asm/octeon/octeon.h>
 
+#include "ethernet-mem.h"
 #include "ethernet-defines.h"
 
 #include <asm/octeon/cvmx-fpa.h>
index ea53af30dfa7c619f7d500a8dc3518d648916270..40297ceb86af6d855e06d31fbc6718a18a78b0b8 100644 (file)
@@ -43,7 +43,7 @@
 #include <asm/octeon/cvmx-npi-defs.h>
 #include <asm/octeon/cvmx-gmxx-defs.h>
 
-DEFINE_SPINLOCK(global_register_lock);
+static DEFINE_SPINLOCK(global_register_lock);
 
 static int number_rgmii_ports;
 
index 47541e1608f35404cd80d93f768cecf67e549ba2..8ca55c4e9db25b0766652e040a4dc902b45d8d2e 100644 (file)
@@ -95,7 +95,7 @@ static void cvm_oct_kick_tx_poll_watchdog(void)
        cvmx_write_csr(CVMX_CIU_TIMX(1), ciu_timx.u64);
 }
 
-void cvm_oct_free_tx_skbs(struct net_device *dev)
+static void cvm_oct_free_tx_skbs(struct net_device *dev)
 {
        int32_t skb_to_free;
        int qos, queues_per_port;
index 089dc4b9efd4cbfb76c1b1a5efcb50dab7b50360..ff7214aac9dd6ed05c524c69fa23e35767d2dcce 100644 (file)
 #include <asm/octeon/cvmx-gmxx-defs.h>
 #include <asm/octeon/cvmx-smix-defs.h>
 
-#if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \
-       && CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
-int num_packet_buffers = CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS;
-#else
-int num_packet_buffers = 1024;
-#endif
+static int num_packet_buffers = 1024;
 module_param(num_packet_buffers, int, 0444);
 MODULE_PARM_DESC(num_packet_buffers, "\n"
        "\tNumber of packet buffers to allocate and store in the\n"
-       "\tFPA. By default, 1024 packet buffers are used unless\n"
-       "\tCONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS is defined.");
+       "\tFPA. By default, 1024 packet buffers are used.\n");
 
 int pow_receive_group = 15;
 module_param(pow_receive_group, int, 0444);
index 743695077346ff608f617a674459210e94868ced..29a23a325d71eefbbd3652bf3cc01a8c4d33c918 100644 (file)
@@ -284,11 +284,11 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
                                          ai->app_id);
                                break;
                        }
-                       oz_polling_lock_bh();
+                       spin_lock_bh(&g_polling_lock);
                        pd->total_apps |= (1<<ai->app_id);
                        if (resume)
                                pd->paused_apps &= ~(1<<ai->app_id);
-                       oz_polling_unlock_bh();
+                       spin_unlock_bh(&g_polling_lock);
                }
        }
        return rc;
@@ -304,14 +304,14 @@ void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
        oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause);
        for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
                if (apps & (1<<ai->app_id)) {
-                       oz_polling_lock_bh();
+                       spin_lock_bh(&g_polling_lock);
                        if (pause) {
                                pd->paused_apps |= (1<<ai->app_id);
                        } else {
                                pd->total_apps &= ~(1<<ai->app_id);
                                pd->paused_apps &= ~(1<<ai->app_id);
                        }
-                       oz_polling_unlock_bh();
+                       spin_unlock_bh(&g_polling_lock);
                        ai->stop(pd, pause);
                }
        }
@@ -349,17 +349,17 @@ void oz_pd_stop(struct oz_pd *pd)
 
        oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state);
        oz_pd_indicate_farewells(pd);
-       oz_polling_lock_bh();
+       spin_lock_bh(&g_polling_lock);
        stop_apps = pd->total_apps;
        pd->total_apps = 0;
        pd->paused_apps = 0;
-       oz_polling_unlock_bh();
+       spin_unlock_bh(&g_polling_lock);
        oz_services_stop(pd, stop_apps, 0);
-       oz_polling_lock_bh();
+       spin_lock_bh(&g_polling_lock);
        oz_pd_set_state(pd, OZ_PD_S_STOPPED);
        /* Remove from PD list.*/
        list_del(&pd->link);
-       oz_polling_unlock_bh();
+       spin_unlock_bh(&g_polling_lock);
        oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count));
        oz_pd_put(pd);
 }
@@ -372,9 +372,9 @@ int oz_pd_sleep(struct oz_pd *pd)
        int do_stop = 0;
        u16 stop_apps;
 
-       oz_polling_lock_bh();
+       spin_lock_bh(&g_polling_lock);
        if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) {
-               oz_polling_unlock_bh();
+               spin_unlock_bh(&g_polling_lock);
                return 0;
        }
        if (pd->keep_alive && pd->session_id)
@@ -383,7 +383,7 @@ int oz_pd_sleep(struct oz_pd *pd)
                do_stop = 1;
 
        stop_apps = pd->total_apps;
-       oz_polling_unlock_bh();
+       spin_unlock_bh(&g_polling_lock);
        if (do_stop) {
                oz_pd_stop(pd);
        } else {
@@ -999,15 +999,15 @@ void oz_pd_indicate_farewells(struct oz_pd *pd)
        const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB-1];
 
        while (1) {
-               oz_polling_lock_bh();
+               spin_lock_bh(&g_polling_lock);
                if (list_empty(&pd->farewell_list)) {
-                       oz_polling_unlock_bh();
+                       spin_unlock_bh(&g_polling_lock);
                        break;
                }
                f = list_first_entry(&pd->farewell_list,
                                struct oz_farewell, link);
                list_del(&f->link);
-               oz_polling_unlock_bh();
+               spin_unlock_bh(&g_polling_lock);
                if (ai->farewell)
                        ai->farewell(pd, f->ep_num, f->report, f->len);
                kfree(f);
index 12c712956888e6d2f60dc1cbe3fb5eeab27c3f8c..56e6fdf9b0bf5fa2aaea9b79c5ff839768b9e4b6 100644 (file)
 #define OZ_TIMER_HEARTBEAT     2
 #define OZ_TIMER_STOP          3
 
+/* 
+ *External spinlock variable
+ */
+extern spinlock_t g_polling_lock;
+
 /* Data structure that hold information on a frame for transmisson. This is
  * built when the frame is first transmitted and is used to rebuild the frame
  * if a re-transmission is required.
index e7138ed325dda09fa8e1e9b34122af88fd32bf5c..c1325a67d320edc9bfbb5ef46a66ad51ed538802 100644 (file)
@@ -37,10 +37,14 @@ struct oz_binding {
        struct list_head link;
 };
 
+/*
+ * External variable
+ */
+
+DEFINE_SPINLOCK(g_polling_lock);
 /*
  * Static external variables.
  */
-static DEFINE_SPINLOCK(g_polling_lock);
 static LIST_HEAD(g_pd_list);
 static LIST_HEAD(g_binding);
 static DEFINE_SPINLOCK(g_binding_lock);
@@ -794,12 +798,3 @@ int oz_get_pd_list(struct oz_mac_addr *addr, int max_count)
        return count;
 }
 
-void oz_polling_lock_bh(void)
-{
-       spin_lock_bh(&g_polling_lock);
-}
-
-void oz_polling_unlock_bh(void)
-{
-       spin_unlock_bh(&g_polling_lock);
-}
index 0c49c8a0e815f98b395edb516542641294a1bca5..cb38e02c968ea34b866f5016da420a14a04301e9 100644 (file)
@@ -59,8 +59,6 @@ void oz_binding_remove(const char *net_dev);
 void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
 void oz_timer_delete(struct oz_pd *pd, int type);
 void oz_pd_request_heartbeat(struct oz_pd *pd);
-void oz_polling_lock_bh(void);
-void oz_polling_unlock_bh(void);
 void oz_pd_heartbeat_handler(unsigned long data);
 void oz_pd_timeout_handler(unsigned long data);
 enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
index ec4b1fd1402199563cf294d000f08e41a8ab03a8..08f9a4896116a3c4368a616d134a2d5a065f9371 100644 (file)
@@ -171,8 +171,8 @@ struct logical_input {
 
        union {
                struct {        /* valid when type == INPUT_TYPE_STD */
-                       void (*press_fct) (int);
-                       void (*release_fct) (int);
+                       void (*press_fct)(int);
+                       void (*release_fct)(int);
                        int press_data;
                        int release_data;
                } std;
@@ -417,9 +417,9 @@ static char lcd_must_clear;
 static char lcd_left_shift;
 static char init_in_progress;
 
-static void (*lcd_write_cmd) (int);
-static void (*lcd_write_data) (int);
-static void (*lcd_clear_fast) (void);
+static void (*lcd_write_cmd)(int);
+static void (*lcd_write_data)(int);
+static void (*lcd_clear_fast)(void);
 
 static DEFINE_SPINLOCK(pprt_lock);
 static struct timer_list scan_timer;
@@ -457,14 +457,12 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
 static int lcd_type = -1;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-                "LCD type: 0=none, 1=old //, 2=serial ks0074, "
-                "3=hantronix //, 4=nexcom //, 5=compiled-in");
+                "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in");
 
 static int lcd_proto = -1;
 module_param(lcd_proto, int, 0000);
 MODULE_PARM_DESC(lcd_proto,
-               "LCD communication: 0=parallel (//), 1=serial,"
-               "2=TI LCD Interface");
+               "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
 
 static int lcd_charset = -1;
 module_param(lcd_charset, int, 0000);
@@ -473,8 +471,7 @@ MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
 static int keypad_type = -1;
 module_param(keypad_type, int, 0000);
 MODULE_PARM_DESC(keypad_type,
-                "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, "
-                "3=nexcom 4 keys");
+                "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
 
 static int profile = DEFAULT_PROFILE;
 module_param(profile, int, 0000);
@@ -494,38 +491,32 @@ MODULE_PARM_DESC(profile,
 static int lcd_e_pin  = PIN_NOT_SET;
 module_param(lcd_e_pin, int, 0000);
 MODULE_PARM_DESC(lcd_e_pin,
-                "# of the // port pin connected to LCD 'E' signal, "
-                "with polarity (-17..17)");
+                "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
 
 static int lcd_rs_pin = PIN_NOT_SET;
 module_param(lcd_rs_pin, int, 0000);
 MODULE_PARM_DESC(lcd_rs_pin,
-                "# of the // port pin connected to LCD 'RS' signal, "
-                "with polarity (-17..17)");
+                "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
 
 static int lcd_rw_pin = PIN_NOT_SET;
 module_param(lcd_rw_pin, int, 0000);
 MODULE_PARM_DESC(lcd_rw_pin,
-                "# of the // port pin connected to LCD 'RW' signal, "
-                "with polarity (-17..17)");
+                "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
 
 static int lcd_bl_pin = PIN_NOT_SET;
 module_param(lcd_bl_pin, int, 0000);
 MODULE_PARM_DESC(lcd_bl_pin,
-                "# of the // port pin connected to LCD backlight, "
-                "with polarity (-17..17)");
+                "# of the // port pin connected to LCD backlight, with polarity (-17..17)");
 
 static int lcd_da_pin = PIN_NOT_SET;
 module_param(lcd_da_pin, int, 0000);
 MODULE_PARM_DESC(lcd_da_pin,
-                "# of the // port pin connected to serial LCD 'SDA' "
-                "signal, with polarity (-17..17)");
+                "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
 
 static int lcd_cl_pin = PIN_NOT_SET;
 module_param(lcd_cl_pin, int, 0000);
 MODULE_PARM_DESC(lcd_cl_pin,
-                "# of the // port pin connected to serial LCD 'SCL' "
-                "signal, with polarity (-17..17)");
+                "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
 
 static const unsigned char *lcd_char_conv;
 
@@ -2017,9 +2008,9 @@ static struct logical_input *panel_bind_key(const char *name, const char *press,
  * be bound.
  */
 static struct logical_input *panel_bind_callback(char *name,
-                                                void (*press_fct) (int),
+                                                void (*press_fct)(int),
                                                 int press_data,
-                                                void (*release_fct) (int),
+                                                void (*release_fct)(int),
                                                 int release_data)
 {
        struct logical_input *callback;
diff --git a/drivers/staging/rtl8187se/Module.symvers b/drivers/staging/rtl8187se/Module.symvers
new file mode 100644 (file)
index 0000000..e69de29
index 09ffd9bc89918240d33947c795f347610193be97..4978b2bba1869660290808467ac053f267481431 100644 (file)
@@ -709,10 +709,10 @@ enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
 
 #define MAX_IE_LEN                                             0xFF //+YJ,080625
 
-typedef struct _CHANNEL_LIST{
-       u8      Channel[MAX_CHANNEL_NUMBER + 1];
-       u8      Len;
-}CHANNEL_LIST, *PCHANNEL_LIST;
+struct rtl8187se_channel_list {
+       u8      channel[MAX_CHANNEL_NUMBER + 1];
+       u8      len;
+};
 
 //by amy for ps
 #define IEEE80211_WATCH_DOG_TIME    2000
index 8999ec62450d220a8bc96ec6ec30956a3159dc7d..5ac46737157a76654cd34f4be21f99f5b4003c8b 100644 (file)
@@ -1,19 +1,18 @@
 /*
-   This is part of rtl8180 OpenSource driver.
-   Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
-   Released under the terms of GPL (General Public Licence)
-
-   Parts of this driver are based on the GPL part of the
-   official realtek driver
-
-   Parts of this driver are based on the rtl8180 driver skeleton
-   from Patric Schenke & Andres Salomon
-
-   Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
-   We want to thanks the Authors of those projects and the Ndiswrapper
-   project Authors.
-*/
+ * This is part of rtl8180 OpenSource driver.
+ * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
+ * Released under the terms of GPL (General Public Licence)
+ *
+ * Parts of this driver are based on the GPL part of the official realtek driver
+ *
+ * Parts of this driver are based on the rtl8180 driver skeleton from Patric
+ * Schenke & Andres Salomon
+ *
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
+ *
+ * We want to thanks the Authors of those projects and the Ndiswrapper project
+ * Authors.
+ */
 
 #ifndef R8180H
 #define R8180H
 #include <linux/interrupt.h>
 
 #define RTL8180_MODULE_NAME "r8180"
-#define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
-#define DMESGW(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
-#define DMESGE(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
+#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
+#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
+#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-//#include <linux/config.h>
+/* #include <linux/config.h> */
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
-#include <linux/rtnetlink.h>   //for rtnl_lock()
+#include <linux/rtnetlink.h> /* for rtnl_lock() */
 #include <linux/wireless.h>
 #include <linux/timer.h>
-#include <linux/proc_fs.h>     // Necessary because we use the proc fs
+#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */
 #include <linux/if_arp.h>
 #include "ieee80211/ieee80211.h"
 #include <asm/io.h>
-//#include <asm/semaphore.h>
+/* #include <asm/semaphore.h> */
 
 #define EPROM_93c46 0
 #define EPROM_93c56 1
 
-#define RTL_IOCTL_WPA_SUPPLICANT               SIOCIWFIRSTPRIV+30
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
 
 #define DEFAULT_FRAG_THRESHOLD 2342U
-#define MIN_FRAG_THRESHOLD     256U
+#define MIN_FRAG_THRESHOLD 256U
 #define DEFAULT_RTS_THRESHOLD 2342U
 #define MIN_RTS_THRESHOLD 0U
 #define MAX_RTS_THRESHOLD 2342U
 #define DEFAULT_RETRY_RTS 7
 #define DEFAULT_RETRY_DATA 7
 
-#define BEACON_QUEUE                                   6
+#define BEACON_QUEUE 6
 
-#define aSifsTime      10
+#define aSifsTime 10
 
-#define sCrcLng         4
-#define sAckCtsLng     112             // bits in ACK and CTS frames
-//+by amy 080312
-#define RATE_ADAPTIVE_TIMER_PERIOD     300
+#define sCrcLng 4
+#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
+/* +by amy 080312. */
+#define RATE_ADAPTIVE_TIMER_PERIOD 300
 
 typedef enum _WIRELESS_MODE {
        WIRELESS_MODE_UNKNOWN = 0x00,
@@ -77,115 +76,111 @@ typedef enum _WIRELESS_MODE {
        WIRELESS_MODE_AUTO = 0x08,
 } WIRELESS_MODE;
 
-typedef struct         ChnlAccessSetting {
-       u16 SIFS_Timer;
-       u16 DIFS_Timer;
-       u16 SlotTimeTimer;
-       u16 EIFS_Timer;
-       u16 CWminIndex;
-       u16 CWmaxIndex;
-}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING;
+struct chnl_access_setting {
+       u16 sifs_timer;
+       u16 difs_timer;
+       u16 slot_time_timer;
+       u16 eifs_timer;
+       u16 cwmin_index;
+       u16 cwmax_index;
+};
 
-typedef enum{
-        NIC_8185 = 1,
-        NIC_8185B
-        } nic_t;
+typedef enum {
+       NIC_8185 = 1,
+       NIC_8185B
+       } nic_t;
 
 typedef u32 AC_CODING;
-#define AC0_BE 0               // ACI: 0x00    // Best Effort
-#define AC1_BK 1               // ACI: 0x01    // Background
-#define AC2_VI 2               // ACI: 0x10    // Video
-#define AC3_VO 3               // ACI: 0x11    // Voice
-#define AC_MAX 4               // Max: define total number; Should not to be used as a real enum.
-
-//
-// ECWmin/ECWmax field.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
-//
-typedef        union _ECW{
-       u8      charData;
-       struct
-       {
-               u8      ECWmin:4;
-               u8      ECWmax:4;
-       }f;     // Field
-}ECW, *PECW;
-
-//
-// ACI/AIFSN Field.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
-//
-typedef        union _ACI_AIFSN{
-       u8      charData;
-
-       struct
-       {
-               u8      AIFSN:4;
-               u8      ACM:1;
-               u8      ACI:2;
-               u8      Reserved:1;
-       }f;     // Field
-}ACI_AIFSN, *PACI_AIFSN;
-
-//
-// AC Parameters Record Format.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
-//
-typedef        union _AC_PARAM{
-       u32     longData;
-       u8      charData[4];
-
-       struct
-       {
-               ACI_AIFSN       AciAifsn;
-               ECW             Ecw;
-               u16             TXOPLimit;
-       }f;     // Field
-}AC_PARAM, *PAC_PARAM;
+#define AC0_BE 0 /* ACI: 0x00 */ /* Best Effort. */
+#define AC1_BK 1 /* ACI: 0x01 */ /* Background. */
+#define AC2_VI 2 /* ACI: 0x10 */ /* Video. */
+#define AC3_VO 3 /* ACI: 0x11 */ /* Voice. */
+#define AC_MAX 4 /* Max: define total number; Should not to be used as a real
+                  * enum.
+                  */
 
-/* it is a wrong definition. -xiong-2006-11-17
-typedef struct ThreeWireReg {
-       u16     longData;
+/*
+ * ECWmin/ECWmax field.
+ * Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
+ */
+typedef union _ECW {
+       u8 charData;
        struct {
-               u8      enableB;
-               u8      data;
-               u8      clk;
-               u8      read_write;
+               u8 ECWmin:4;
+               u8 ECWmax:4;
+       } f;    /* Field */
+} ECW, *PECW;
+
+/*
+ * ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
+ */
+typedef union _ACI_AIFSN {
+       u8 charData;
+
+       struct {
+               u8 AIFSN:4;
+               u8 ACM:1;
+               u8 ACI:2;
+               u8 Reserved:1;
+       } f;    /* Field */
+} ACI_AIFSN, *PACI_AIFSN;
+
+/*
+ * AC Parameters Record Format.
+ * Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
+ */
+typedef union _AC_PARAM {
+       u32 longData;
+       u8 charData[4];
+
+       struct {
+               ACI_AIFSN AciAifsn;
+               ECW Ecw;
+               u16 TXOPLimit;
+       } f;    /* Field */
+} AC_PARAM, *PAC_PARAM;
+
+/* it is a wrong definition. -xiong-2006-11-17
+ * typedef struct ThreeWireReg {
+ *     u16     longData;
+ *     struct {
+ *             u8 enableB;
+ *             u8 data;
+ *             u8 clk;
+ *             u8 read_write;
+ *     } struc;
+ * } ThreeWireReg;
+ */
+
+typedef union _ThreeWire {
+       struct _ThreeWireStruc {
+               u16 data:1;
+               u16 clk:1;
+               u16 enableB:1;
+               u16 read_write:1;
+               u16 resv1:12;
+               /* u2Byte resv2:14; */
+               /* u2Byte ThreeWireEnable:1; */
+               /* u2Byte resv3:1; */
        } struc;
+       u16 longData;
 } ThreeWireReg;
-*/
-
-typedef        union _ThreeWire{
-       struct _ThreeWireStruc{
-               u16             data:1;
-               u16             clk:1;
-               u16             enableB:1;
-               u16             read_write:1;
-               u16             resv1:12;
-//             u2Byte  resv2:14;
-//             u2Byte  ThreeWireEnable:1;
-//             u2Byte  resv3:1;
-       }struc;
-       u16                     longData;
-}ThreeWireReg;
-
-
-typedef struct buffer
-{
+
+
+typedef struct buffer {
        struct buffer *next;
        u32 *buf;
        dma_addr_t dma;
 } buffer;
 
-//YJ,modified,080828
-typedef struct Stats
-{
+/* YJ,modified,080828. */
+struct stats {
        unsigned long txrdu;
        unsigned long rxrdu;
        unsigned long rxnolast;
        unsigned long rxnodata;
-//     unsigned long rxreset;
-//     unsigned long rxwrkaround;
+       /* unsigned long rxreset; */
+       /* unsigned long rxwrkaround; */
        unsigned long rxnopointer;
        unsigned long txnperr;
        unsigned long txresumed;
@@ -207,52 +202,59 @@ typedef struct Stats
        unsigned long txbeaconerr;
        unsigned long txlpokint;
        unsigned long txlperr;
-       unsigned long txretry;//retry number  tony 20060601
-       unsigned long rxcrcerrmin;//crc error (0-500)
-       unsigned long rxcrcerrmid;//crc error (500-1000)
-       unsigned long rxcrcerrmax;//crc error (>1000)
-       unsigned long rxicverr;//ICV error
-} Stats;
+       unsigned long txretry; /* retry number tony 20060601 */
+       unsigned long rxcrcerrmin; /* crc error (0-500) */
+       unsigned long rxcrcerrmid; /* crc error (500-1000) */
+       unsigned long rxcrcerrmax; /* crc error (>1000) */
+       unsigned long rxicverr; /* ICV error */
+};
 
 #define MAX_LD_SLOT_NUM 10
-#define KEEP_ALIVE_INTERVAL                            20 // in seconds.
-#define CHECK_FOR_HANG_PERIOD                  2 //be equal to watchdog check time
-#define DEFAULT_KEEP_ALIVE_LEVEL                       1
-#define DEFAULT_SLOT_NUM                                       2
-#define POWER_PROFILE_AC                                       0
-#define POWER_PROFILE_BATTERY                  1
-
-typedef struct _link_detect_t
-{
-       u32                             RxFrameNum[MAX_LD_SLOT_NUM];    // number of Rx Frame / CheckForHang_period  to determine link status
-       u16                             SlotNum;        // number of CheckForHang period to determine link status, default is 2
-       u16                             SlotIndex;
-
-       u32                             NumTxOkInPeriod;  //number of packet transmitted during CheckForHang
-       u32                             NumRxOkInPeriod;  //number of packet received during CheckForHang
-
-       u8                              IdleCount;     // (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)
-       u32                             LastNumTxUnicast;
-       u32                             LastNumRxUnicast;
-
-       bool                            bBusyTraffic;    //when it is set to 1, UI cann't scan at will.
-}link_detect_t, *plink_detect_t;
-
-//YJ,modified,080828,end
-
-//by amy for led
-//================================================================================
-// LED customization.
-//================================================================================
-
-typedef        enum _LED_STRATEGY_8185{
-       SW_LED_MODE0, //
-       SW_LED_MODE1, //
-       HW_LED, // HW control 2 LEDs, LED0 and LED1 (there are 4 different control modes)
-}LED_STRATEGY_8185, *PLED_STRATEGY_8185;
-//by amy for led
-//by amy for power save
-typedef        enum _LED_CTL_MODE{
+#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */
+#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */
+#define DEFAULT_KEEP_ALIVE_LEVEL 1
+#define DEFAULT_SLOT_NUM 2
+#define POWER_PROFILE_AC 0
+#define POWER_PROFILE_BATTERY 1
+
+struct link_detect_t {
+       u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame.
+                                           * CheckForHang_period  to determine
+                                           * link status.
+                                           */
+       u16 slot_num; /* number of CheckForHang period to determine link status,
+                      * default is 2.
+                      */
+       u16 slot_index;
+       u32 num_tx_ok_in_period; /* number of packet transmitted during
+                                 * CheckForHang.
+                                 */
+       u32 num_rx_ok_in_period; /* number of packet received during
+                                 * CheckForHang.
+                                 */
+       u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */
+       u32 last_num_tx_unicast;
+       u32 last_num_rx_unicast;
+
+       bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */
+};
+
+/* YJ,modified,080828,end */
+
+/* by amy for led
+ * ==========================================================================
+ * LED customization.
+ * ==========================================================================
+ */
+typedef enum _LED_STRATEGY_8185 {
+       SW_LED_MODE0,
+       SW_LED_MODE1,
+       HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
+                * control modes). */
+} LED_STRATEGY_8185, *PLED_STRATEGY_8185;
+/* by amy for led. */
+/* by amy for power save. */
+typedef enum _LED_CTL_MODE {
        LED_CTL_POWER_ON = 1,
        LED_CTL_LINK = 2,
        LED_CTL_NO_LINK = 3,
@@ -260,73 +262,74 @@ typedef   enum _LED_CTL_MODE{
        LED_CTL_RX = 5,
        LED_CTL_SITE_SURVEY = 6,
        LED_CTL_POWER_OFF = 7
-}LED_CTL_MODE;
+} LED_CTL_MODE;
 
-typedef        enum _RT_RF_POWER_STATE
-{
+typedef enum _RT_RF_POWER_STATE {
        eRfOn,
        eRfSleep,
        eRfOff
-}RT_RF_POWER_STATE;
-
-enum   _ReasonCode{
-       unspec_reason   = 0x1,
-       auth_not_valid  = 0x2,
-       deauth_lv_ss    = 0x3,
-       inactivity              = 0x4,
-       ap_overload             = 0x5,
-       class2_err              = 0x6,
-       class3_err              = 0x7,
-       disas_lv_ss             = 0x8,
-       asoc_not_auth   = 0x9,
-
-       //----MIC_CHECK
-       mic_failure             = 0xe,
-       //----END MIC_CHECK
-
-       // Reason code defined in 802.11i D10.0 p.28.
-       invalid_IE              = 0x0d,
-       four_way_tmout  = 0x0f,
-       two_way_tmout   = 0x10,
-       IE_dismatch             = 0x11,
+} RT_RF_POWER_STATE;
+
+enum _ReasonCode {
+       unspec_reason = 0x1,
+       auth_not_valid = 0x2,
+       deauth_lv_ss = 0x3,
+       inactivity = 0x4,
+       ap_overload = 0x5,
+       class2_err = 0x6,
+       class3_err = 0x7,
+       disas_lv_ss = 0x8,
+       asoc_not_auth = 0x9,
+
+       /* ----MIC_CHECK */
+       mic_failure = 0xe,
+       /* ----END MIC_CHECK */
+
+       /* Reason code defined in 802.11i D10.0 p.28. */
+       invalid_IE = 0x0d,
+       four_way_tmout = 0x0f,
+       two_way_tmout = 0x10,
+       IE_dismatch = 0x11,
        invalid_Gcipher = 0x12,
        invalid_Pcipher = 0x13,
-       invalid_AKMP    = 0x14,
+       invalid_AKMP = 0x14,
        unsup_RSNIEver = 0x15,
-       invalid_RSNIE   = 0x16,
-       auth_802_1x_fail= 0x17,
-       ciper_reject            = 0x18,
-
-       // Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15.
-       QoS_unspec              = 0x20, // 32
-       QAP_bandwidth   = 0x21, // 33
-       poor_condition  = 0x22, // 34
-       no_facility             = 0x23, // 35
-                                                       // Where is 36???
-       req_declined    = 0x25, // 37
-       invalid_param   = 0x26, // 38
-       req_not_honored= 0x27,  // 39
-       TS_not_created  = 0x2F, // 47
-       DL_not_allowed  = 0x30, // 48
-       dest_not_exist  = 0x31, // 49
-       dest_not_QSTA   = 0x32, // 50
+       invalid_RSNIE = 0x16,
+       auth_802_1x_fail = 0x17,
+       ciper_reject = 0x18,
+
+       /* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie,
+        * 2005-11-15.
+        */
+       QoS_unspec = 0x20, /* 32 */
+       QAP_bandwidth = 0x21, /* 33 */
+       poor_condition = 0x22, /* 34 */
+       no_facility = 0x23, /* 35 */
+       /* Where is 36??? */
+       req_declined = 0x25, /* 37 */
+       invalid_param = 0x26, /* 38 */
+       req_not_honored = 0x27, /* 39 */
+       TS_not_created = 0x2F, /* 47 */
+       DL_not_allowed = 0x30, /* 48 */
+       dest_not_exist = 0x31, /* 49 */
+       dest_not_QSTA = 0x32, /* 50 */
 };
-typedef        enum _RT_PS_MODE
-{
-       eActive,        // Active/Continuous access.
-       eMaxPs,         // Max power save mode.
-       eFastPs         // Fast power save mode.
-}RT_PS_MODE;
-//by amy for power save
-typedef struct r8180_priv
-{
+
+typedef enum _RT_PS_MODE {
+       eActive, /* Active/Continuous access. */
+       eMaxPs, /* Max power save mode. */
+       eFastPs /* Fast power save mode. */
+} RT_PS_MODE;
+
+/* by amy for power save. */
+typedef struct r8180_priv {
        struct pci_dev *pdev;
 
        short epromtype;
        int irq;
        struct ieee80211_device *ieee80211;
 
-       short plcp_preamble_mode; // 0:auto 1:short 2:long
+       short plcp_preamble_mode; /* 0:auto 1:short 2:long */
 
        spinlock_t irq_th_lock;
        spinlock_t tx_lock;
@@ -339,19 +342,20 @@ typedef struct r8180_priv
        short chan;
        short sens;
        short max_sens;
-       u8 chtxpwr[15]; //channels from 1 to 14, 0 not used
-       u8 chtxpwr_ofdm[15]; //channels from 1 to 14, 0 not used
-       //u8 challow[15]; //channels from 1 to 14, 0 not used
-       u8 channel_plan;  // it's the channel plan index
+       u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
+       u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
+       /* u8 challow[15]; */ /* channels from 1 to 14, 0 not used. */
+       u8 channel_plan;  /* it's the channel plan index. */
        short up;
-       short crcmon; //if 1 allow bad crc frame reception in monitor mode
+       short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
 
        struct timer_list scan_timer;
-       /*short scanpending;
-       short stopscan;*/
+       /* short scanpending;
+        * short stopscan;
+        */
        spinlock_t scan_lock;
        u8 active_probe;
-       //u8 active_scan_num;
+       /* u8 active_scan_num; */
        struct semaphore wx_sem;
        short hw_wep;
 
@@ -359,20 +363,20 @@ typedef struct r8180_priv
        short antb;
        short diversity;
        u32 key0[4];
-       short (*rf_set_sens)(struct net_device *dev,short sens);
-       void (*rf_set_chan)(struct net_device *dev,short ch);
+       short (*rf_set_sens)(struct net_device *dev, short sens);
+       void (*rf_set_chan)(struct net_device *dev, short ch);
        void (*rf_close)(struct net_device *dev);
        void (*rf_init)(struct net_device *dev);
        void (*rf_sleep)(struct net_device *dev);
        void (*rf_wakeup)(struct net_device *dev);
-       //short rate;
+       /* short rate; */
        short promisc;
-       /*stats*/
-       struct Stats stats;
-       struct _link_detect_t link_detect;  //YJ,add,080828
+       /* stats */
+       struct stats stats;
+       struct link_detect_t link_detect; /* YJ,add,080828 */
        struct iw_statistics wstats;
 
-       /*RX stuff*/
+       /* RX stuff. */
        u32 *rxring;
        u32 *rxringtail;
        dma_addr_t rxringdma;
@@ -387,27 +391,27 @@ typedef struct r8180_priv
 
        u32 rx_prevlen;
 
-       /*TX stuff*/
-/*
-       u32 *txlpring;
-       u32 *txhpring;
-       u32 *txnpring;
-       dma_addr_t txlpringdma;
-       dma_addr_t txhpringdma;
-       dma_addr_t txnpringdma;
-       u32 *txlpringtail;
-       u32 *txhpringtail;
-       u32 *txnpringtail;
-       u32 *txlpringhead;
-       u32 *txhpringhead;
-       u32 *txnpringhead;
-       struct buffer *txlpbufs;
-       struct buffer *txhpbufs;
-       struct buffer *txnpbufs;
-       struct buffer *txlpbufstail;
-       struct buffer *txhpbufstail;
-       struct buffer *txnpbufstail;
-*/
+       /* TX stuff */
+       /*
+        * u32 *txlpring;
+        * u32 *txhpring;
+        * u32 *txnpring;
+        * dma_addr_t txlpringdma;
+        * dma_addr_t txhpringdma;
+        * dma_addr_t txnpringdma;
+        * u32 *txlpringtail;
+        * u32 *txhpringtail;
+        * u32 *txnpringtail;
+        * u32 *txlpringhead;
+        * u32 *txhpringhead;
+        * u32 *txnpringhead;
+        * struct buffer *txlpbufs;
+        * struct buffer *txhpbufs;
+        * struct buffer *txnpbufs;
+        * struct buffer *txlpbufstail;
+        * struct buffer *txhpbufstail;
+        * struct buffer *txnpbufstail;
+        */
        u32 *txmapring;
        u32 *txbkpring;
        u32 *txbepring;
@@ -447,54 +451,56 @@ typedef struct r8180_priv
 
        int txringcount;
        int txbuffsize;
-       //struct tx_pendingbuf txnp_pending;
-       //struct tasklet_struct irq_tx_tasklet;
+       /* struct tx_pendingbuf txnp_pending; */
+       /* struct tasklet_struct irq_tx_tasklet; */
        struct tasklet_struct irq_rx_tasklet;
        u8 dma_poll_mask;
-       //short tx_suspend;
+       /* short tx_suspend; */
 
-       /* adhoc/master mode stuff */
+       /* adhoc/master mode stuff. */
        u32 *txbeaconringtail;
        dma_addr_t txbeaconringdma;
        u32 *txbeaconring;
        int txbeaconcount;
        struct buffer *txbeaconbufs;
        struct buffer *txbeaconbufstail;
-       //char *master_essid;
-       //u16 master_beaconinterval;
-       //u32 master_beaconsize;
-       //u16 beacon_interval;
+       /* char *master_essid; */
+       /* u16 master_beaconinterval; */
+       /* u32 master_beaconsize; */
+       /* u16 beacon_interval; */
 
        u8 retry_data;
        u8 retry_rts;
        u16 rts;
 
-//by amy for led
+       /* by amy for led. */
        LED_STRATEGY_8185 LedStrategy;
-//by amy for led
+       /* by amy for led. */
 
-//by amy for power save
+       /* by amy for power save. */
        struct timer_list watch_dog_timer;
        bool bInactivePs;
        bool bSwRfProcessing;
-       RT_RF_POWER_STATE       eInactivePowerState;
+       RT_RF_POWER_STATE eInactivePowerState;
        RT_RF_POWER_STATE eRFPowerState;
        u32 RfOffReason;
        bool RFChangeInProgress;
        bool SetRFPowerStateInProgress;
-       u8   RFProgType;
+       u8 RFProgType;
        bool bLeisurePs;
        RT_PS_MODE dot11PowerSaveMode;
-       //u32 NumRxOkInPeriod;   //YJ,del,080828
-       //u32 NumTxOkInPeriod;   //YJ,del,080828
-       u8   TxPollingTimes;
-
-       bool    bApBufOurFrame;// TRUE if AP buffer our unicast data , we will keep eAwake until receive data or timeout.
-       u8      WaitBufDataBcnCount;
-       u8      WaitBufDataTimeOut;
-
-//by amy for power save
-//by amy for antenna
+       /* u32 NumRxOkInPeriod;*/ /* YJ,del,080828 */
+       /* u32 NumTxOkInPeriod;*/ /* YJ,del,080828 */
+       u8 TxPollingTimes;
+
+       bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will
+                             * keep eAwake until receive data or timeout.
+                             */
+       u8 WaitBufDataBcnCount;
+       u8 WaitBufDataTimeOut;
+
+       /* by amy for power save. */
+       /* by amy for antenna. */
        u8 EEPROMSwAntennaDiversity;
        bool EEPROMDefaultAntenna1;
        u8 RegSwAntennaDiversityMechanism;
@@ -503,115 +509,133 @@ typedef struct r8180_priv
        bool bDefaultAntenna1;
        u8 SignalStrength;
        long Stats_SignalStrength;
-       long LastSignalStrengthInPercent; // In percentage, used for smoothing, e.g. Moving Average.
-       u8       SignalQuality; // in 0-100 index.
+       long LastSignalStrengthInPercent; /* In percentage, used for smoothing,
+                                          * e.g. Moving Average.
+                                          */
+       u8 SignalQuality; /* in 0-100 index. */
        long Stats_SignalQuality;
-       long RecvSignalPower; // in dBm.
+       long RecvSignalPower; /* in dBm. */
        long Stats_RecvSignalPower;
-       u8       LastRxPktAntenna;      // +by amy 080312 Antenna which received the lasted packet. 0: Aux, 1:Main. Added by Roger, 2008.01.25.
+       u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted
+                             * packet. 0: Aux, 1:Main. Added by Roger,
+                             * 2008.01.25.
+                             */
        u32 AdRxOkCnt;
        long AdRxSignalStrength;
-       u8 CurrAntennaIndex;                    // Index to current Antenna (both Tx and Rx).
-       u8 AdTickCount;                         // Times of SwAntennaDiversityTimer happened.
-       u8 AdCheckPeriod;                               // # of period SwAntennaDiversityTimer to check Rx signal strength for SW Antenna Diversity.
-       u8 AdMinCheckPeriod;                    // Min value of AdCheckPeriod.
-       u8 AdMaxCheckPeriod;                    // Max value of AdCheckPeriod.
-       long AdRxSsThreshold;                   // Signal strength threshold to switch antenna.
-       long AdMaxRxSsThreshold;                        // Max value of AdRxSsThreshold.
-       bool bAdSwitchedChecking;               // TRUE if we shall shall check Rx signal strength for last time switching antenna.
-       long AdRxSsBeforeSwitched;              // Rx signal strength before we switched antenna.
+       u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */
+       u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */
+       u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx
+                          * signal strength for SW Antenna Diversity.
+                          */
+       u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */
+       u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */
+       long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */
+       long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */
+       bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal
+                                  * strength for last time switching antenna.
+                                  */
+       long AdRxSsBeforeSwitched; /* Rx signal strength before we switched
+                                   * antenna.
+                                   */
        struct timer_list SwAntennaDiversityTimer;
-//by amy for antenna
-//{by amy 080312
-//
-       // Crystal calibration.
-       // Added by Roger, 2007.12.11.
-       //
-       bool            bXtalCalibration; // Crystal calibration.
-       u8                      XtalCal_Xin; // Crystal calibration for Xin. 0~7.5pF
-       u8                      XtalCal_Xout; // Crystal calibration for Xout. 0~7.5pF
-       //
-       // Tx power tracking with thermal meter indication.
-       // Added by Roger, 2007.12.11.
-       //
-       bool            bTxPowerTrack; // Tx Power tracking.
-       u8                      ThermalMeter; // Thermal meter reference indication.
-       //
-       // Dynamic Initial Gain Adjustment Mechanism. Added by Bruce, 2007-02-14.
-       //
-       bool                            bDigMechanism; // TRUE if DIG is enabled, FALSE ow.
-       bool                            bRegHighPowerMechanism; // For High Power Mechanism. 061010, by rcnjko.
-       u32                                     FalseAlarmRegValue;
-       u8                                      RegDigOfdmFaUpTh; // Upper threshold of OFDM false alarm, which is used in DIG.
-       u8                                      DIG_NumberFallbackVote;
-       u8                                      DIG_NumberUpgradeVote;
-       // For HW antenna diversity, added by Roger, 2008.01.30.
-       u32                     AdMainAntennaRxOkCnt;           // Main antenna Rx OK count.
-       u32                     AdAuxAntennaRxOkCnt;            // Aux antenna Rx OK count.
-       bool            bHWAdSwitched;                          // TRUE if we has switched default antenna by HW evaluation.
-       // RF High Power upper/lower threshold.
-       u8                                      RegHiPwrUpperTh;
-       u8                                      RegHiPwrLowerTh;
-       // RF RSSI High Power upper/lower Threshold.
-       u8                                      RegRSSIHiPwrUpperTh;
-       u8                                      RegRSSIHiPwrLowerTh;
-       // Current CCK RSSI value to determine CCK high power, asked by SD3 DZ, by Bruce, 2007-04-12.
-       u8                      CurCCKRSSI;
-       bool        bCurCCKPkt;
-       //
-       // High Power Mechanism. Added by amy, 080312.
-       //
-       bool                                    bToUpdateTxPwr;
-       long                                    UndecoratedSmoothedSS;
-       long                                    UndercorateSmoothedRxPower;
-       u8                                              RSSI;
-       char                                    RxPower;
-        u8 InitialGain;
-        //For adjust Dig Threshold during Legacy/Leisure Power Save Mode
-       u32                             DozePeriodInPast2Sec;
-        // Don't access BB/RF under disable PLL situation.
-       u8                                      InitialGainBackUp;
-        u8 RegBModeGainStage;
-//by amy for rate adaptive
-    struct timer_list rateadapter_timer;
-       u32    RateAdaptivePeriod;
-       bool   bEnhanceTxPwr;
-       bool   bUpdateARFR;
-       int        ForcedDataRate; // Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
-       u32     NumTxUnicast; //YJ,add,080828,for keep alive
-       u8      keepAliveLevel; //YJ,add,080828,for KeepAlive
-       unsigned long   NumTxOkTotal;
-       u16                                 LastRetryCnt;
-        u16                                     LastRetryRate;
-        unsigned long       LastTxokCnt;
-        unsigned long           LastRxokCnt;
-        u16                                     CurrRetryCnt;
-        unsigned long           LastTxOKBytes;
-       unsigned long               NumTxOkBytesTotal;
-        u8                          LastFailTxRate;
-        long                        LastFailTxRateSS;
-        u8                          FailTxRateCount;
-        u32                         LastTxThroughput;
-        //for up rate
-        unsigned short          bTryuping;
-        u8                                      CurrTxRate;     //the rate before up
-        u16                                     CurrRetryRate;
-        u16                                     TryupingCount;
-        u8                                      TryDownCountLowData;
-        u8                                      TryupingCountNoData;
-
-        u8                  CurrentOperaRate;
-//by amy for rate adaptive
-//by amy 080312}
-//     short wq_hurryup;
-//     struct workqueue_struct *workqueue;
+       /* by amy for antenna {by amy 080312 */
+
+       /* Crystal calibration. Added by Roger, 2007.12.11. */
+
+       bool bXtalCalibration; /* Crystal calibration.*/
+       u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */
+       u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */
+
+       /* Tx power tracking with thermal meter indication.
+        * Added by Roger, 2007.12.11.
+        */
+
+       bool bTxPowerTrack; /* Tx Power tracking. */
+       u8 ThermalMeter; /* Thermal meter reference indication. */
+
+       /* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce,
+        * 2007-02-14.
+        */
+       bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */
+       bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010,
+                                     * by rcnjko.
+                                     */
+       u32 FalseAlarmRegValue;
+       u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is
+                             * used in DIG.
+                             */
+       u8 DIG_NumberFallbackVote;
+       u8 DIG_NumberUpgradeVote;
+       /* For HW antenna diversity, added by Roger, 2008.01.30. */
+       u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */
+       u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */
+       bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW
+                            * evaluation.
+                            */
+       /* RF High Power upper/lower threshold. */
+       u8 RegHiPwrUpperTh;
+       u8 RegHiPwrLowerTh;
+       /* RF RSSI High Power upper/lower Threshold. */
+       u8 RegRSSIHiPwrUpperTh;
+       u8 RegRSSIHiPwrLowerTh;
+       /* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ,
+        * by Bruce, 2007-04-12.
+        */
+       u8 CurCCKRSSI;
+       bool bCurCCKPkt;
+       /* High Power Mechanism. Added by amy, 080312. */
+       bool bToUpdateTxPwr;
+       long UndecoratedSmoothedSS;
+       long UndecoratedSmoothedRxPower;
+       u8 RSSI;
+       char RxPower;
+       u8 InitialGain;
+       /* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */
+       u32 DozePeriodInPast2Sec;
+       /* Don't access BB/RF under disable PLL situation. */
+       u8 InitialGainBackUp;
+       u8 RegBModeGainStage;
+       /* by amy for rate adaptive */
+       struct timer_list rateadapter_timer;
+       u32 RateAdaptivePeriod;
+       bool bEnhanceTxPwr;
+       bool bUpdateARFR;
+       int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
+                            */
+       u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */
+       u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */
+       unsigned long NumTxOkTotal;
+       u16 LastRetryCnt;
+       u16 LastRetryRate;
+       unsigned long LastTxokCnt;
+       unsigned long LastRxokCnt;
+       u16 CurrRetryCnt;
+       unsigned long LastTxOKBytes;
+       unsigned long NumTxOkBytesTotal;
+       u8 LastFailTxRate;
+       long LastFailTxRateSS;
+       u8 FailTxRateCount;
+       u32 LastTxThroughput;
+       /* for up rate. */
+       unsigned short bTryuping;
+       u8 CurrTxRate; /* the rate before up. */
+       u16 CurrRetryRate;
+       u16 TryupingCount;
+       u8 TryDownCountLowData;
+       u8 TryupingCountNoData;
+
+       u8 CurrentOperaRate;
+       /* by amy for rate adaptive. */
+       /* by amy 080312} */
+       /* short wq_hurryup; */
+       /* struct workqueue_struct *workqueue; */
        struct work_struct reset_wq;
        struct work_struct watch_dog_wq;
        short ack_tx_to_ieee;
 
        u8 dma_poll_stop_mask;
 
-       //u8 RegThreeWireMode;
+       /* u8 RegThreeWireMode; */
        u16 ShortRetryLimit;
        u16 LongRetryLimit;
        u16 EarlyRxThreshold;
@@ -619,8 +643,8 @@ typedef struct r8180_priv
        u32 ReceiveConfig;
        u32 IntrMask;
 
-       struct  ChnlAccessSetting  ChannelAccessSetting;
-}r8180_priv;
+       struct chnl_access_setting ChannelAccessSetting;
+} r8180_priv;
 
 #define MANAGE_PRIORITY 0
 #define BK_PRIORITY 1
@@ -632,7 +656,7 @@ typedef struct r8180_priv
 
 #define LOW_PRIORITY VI_PRIORITY
 #define NORM_PRIORITY VO_PRIORITY
-//AC2Queue mapping
+/* AC2Queue mapping. */
 #define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
                ((_ac) == WME_AC_VI) ? VI_PRIORITY : \
                ((_ac) == WME_AC_BK) ? BK_PRIORITY : \
@@ -673,7 +697,7 @@ void UpdateInitialGain(struct net_device *dev);
 bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
                          bool bAntDiversity);
 
-//#ifdef CONFIG_RTL8185B
+/* #ifdef CONFIG_RTL8185B */
 void rtl8185b_adapter_start(struct net_device *dev);
 void rtl8185b_rx_enable(struct net_device *dev);
 void rtl8185b_tx_enable(struct net_device *dev);
@@ -682,8 +706,8 @@ void rtl8185b_irq_enable(struct net_device *dev);
 void fix_rx_fifo(struct net_device *dev);
 void fix_tx_fifo(struct net_device *dev);
 void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch);
-void rtl8180_rate_adapter(struct work_struct * work);
-//#endif
+void rtl8180_rate_adapter(struct work_struct *work);
+/* #endif */
 bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet,
                         u32 ChangeSource);
 
index 6cafee22bec4fecb7842c53ae28fb8c3427afe8b..dc434b88dcc6d4545cab026dca51862bc5daef53 100644 (file)
@@ -1,31 +1,31 @@
 /*
  This is part of rtl818x pci OpenSource driver - v 0.1
  Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
  Released under the terms of GPL (General Public License)
-
  Parts of this driver are based on the GPL part of the official
  Realtek driver.
-
  Parts of this driver are based on the rtl8180 driver skeleton
  from Patric Schenke & Andres Salomon.
-
  Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
  Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
-
  RSSI calc function from 'The Deuce'
-
  Some ideas borrowed from the 8139too.c driver included in linux kernel.
-
  We (I?) want to thanks the Authors of those projecs and also the
  Ndiswrapper's project Authors.
-
  A big big thanks goes also to Realtek corp. for their help in my attempt to
  add RTL8185 and RTL8225 support, and to David Young also.
-
  Power management interface routines.
  Written by Mariusz Matuszek.
-*/
* This is part of rtl818x pci OpenSource driver - v 0.1
* Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
* Released under the terms of GPL (General Public License)
+ *
* Parts of this driver are based on the GPL part of the official
* Realtek driver.
+ *
* Parts of this driver are based on the rtl8180 driver skeleton
* from Patric Schenke & Andres Salomon.
+ *
* Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
+ *
* Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
+ *
* RSSI calc function from 'The Deuce'
+ *
* Some ideas borrowed from the 8139too.c driver included in linux kernel.
+ *
* We (I?) want to thanks the Authors of those projecs and also the
* Ndiswrapper's project Authors.
+ *
* A big big thanks goes also to Realtek corp. for their help in my attempt to
* add RTL8185 and RTL8225 support, and to David Young also.
+ *
* Power management interface routines.
* Written by Mariusz Matuszek.
+ */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
@@ -258,7 +258,9 @@ static int proc_get_stats_tx(struct seq_file *m, void *v)
        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
        unsigned long totalOK;
 
-       totalOK = priv->stats.txnpokint+priv->stats.txhpokint+priv->stats.txlpokint;
+       totalOK = priv->stats.txnpokint + priv->stats.txhpokint +
+               priv->stats.txlpokint;
+
        seq_printf(m,
                "TX OK: %lu\n"
                "TX Error: %lu\n"
@@ -347,9 +349,9 @@ static void rtl8180_proc_init_one(struct net_device *dev)
 }
 
 /*
-  FIXME: check if we can use some standard already-existent
-  data type+functions in kernel
-*/
* FIXME: check if we can use some standard already-existent
+ * data type+functions in kernel.
+ */
 
 static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
                        struct buffer **bufferhead)
@@ -468,9 +470,11 @@ static short check_nic_enought_desc(struct net_device *dev, int priority)
 {
        struct r8180_priv *priv = ieee80211_priv(dev);
        struct ieee80211_device *ieee = netdev_priv(dev);
-       int requiredbyte, required;
+       int requiredbyte;
+       int required;
 
-       requiredbyte = priv->ieee80211->fts + sizeof(struct ieee80211_header_data);
+       requiredbyte = priv->ieee80211->fts +
+               sizeof(struct ieee80211_header_data);
 
        if (ieee->current_network.QoS_Enable)
                requiredbyte += 2;
@@ -484,7 +488,7 @@ static short check_nic_enought_desc(struct net_device *dev, int priority)
         * between the tail and the head
         */
 
-       return (required+2 < get_curr_tx_free_desc(dev, priority));
+       return required + 2 < get_curr_tx_free_desc(dev, priority);
 }
 
 void fix_tx_fifo(struct net_device *dev)
@@ -649,7 +653,7 @@ void rtl8180_set_chan(struct net_device *dev, short ch)
        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
        if ((ch > 14) || (ch < 1)) {
-               printk("In %s: Invalid chnanel %d\n", __func__, ch);
+               netdev_err(dev, "In %s: Invalid channel %d\n", __func__, ch);
                return;
        }
 
@@ -742,43 +746,50 @@ static short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
 
                switch (addr) {
                case TX_MANAGEPRIORITY_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txmapbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txmapbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer NP");
                                return -ENOMEM;
                        }
                        break;
                case TX_BKPRIORITY_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txbkpbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txbkpbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer LP");
                                return -ENOMEM;
                        }
                        break;
                case TX_BEPRIORITY_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txbepbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txbepbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer NP");
                                return -ENOMEM;
                        }
                        break;
                case TX_VIPRIORITY_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txvipbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txvipbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer LP");
                                return -ENOMEM;
                        }
                        break;
                case TX_VOPRIORITY_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txvopbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txvopbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer NP");
                                return -ENOMEM;
                        }
                        break;
                case TX_HIGHPRIORITY_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txhpbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txhpbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer HP");
                                return -ENOMEM;
                        }
                        break;
                case TX_BEACON_RING_ADDR:
-                       if (-1 == buffer_add(&(priv->txbeaconbufs), buf, dma_tmp, NULL)) {
+                       if (-1 == buffer_add(&priv->txbeaconbufs,
+                               buf, dma_tmp, NULL)) {
                                DMESGE("Unable to allocate mem for buffer BP");
                                return -ENOMEM;
                        }
@@ -897,8 +908,8 @@ static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
                return -1;
        }
 
-       desc = (u32 *)pci_alloc_consistent(pdev, sizeof(u32)*rx_desc_size*count+256,
-                                         &dma_desc);
+       desc = (u32 *)pci_alloc_consistent(pdev,
+               sizeof(u32) * rx_desc_size * count + 256, &dma_desc);
 
        if (dma_desc & 0xff)
                /*
@@ -935,7 +946,8 @@ static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
                tmp = tmp+rx_desc_size;
        }
 
-       *(tmp-rx_desc_size) = *(tmp-rx_desc_size) | (1<<30); /* this is the last descriptor */
+       /* this is the last descriptor */
+       *(tmp - rx_desc_size) = *(tmp - rx_desc_size) | (1 << 30);
 
        return 0;
 }
@@ -1009,7 +1021,8 @@ inline u16 ieeerate2rtlrate(int rate)
        }
 }
 
-static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540, 720};
+static u16 rtl_rate[] = {10, 20, 55, 110, 60,
+       90, 120, 180, 240, 360, 480, 540, 720};
 
 inline u16 rtl8180_rate2rate(short rate)
 {
@@ -1143,23 +1156,30 @@ static long TranslateToDbm8185(u8 SignalStrengthIndex)
 /*
  * Perform signal smoothing for dynamic mechanism.
  * This is different with PerformSignalSmoothing8185 in smoothing formula.
- * No dramatic adjustion is apply because dynamic mechanism need some degree
- * of correctness. Ported from 8187B.
+ * No dramatic adjustment is applied because dynamic mechanism need some
+ * degree of correctness. Ported from 8187B.
  */
 static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
                                                  bool bCckRate)
 {
-       /* Determin the current packet is CCK rate. */
+       long smoothedSS;
+       long smoothedRx;
+
+       /* Determine the current packet is CCK rate. */
        priv->bCurCCKPkt = bCckRate;
 
+       smoothedSS = priv->SignalStrength * 10;
+
        if (priv->UndecoratedSmoothedSS >= 0)
-               priv->UndecoratedSmoothedSS = ((priv->UndecoratedSmoothedSS * 5) +
-                                              (priv->SignalStrength * 10)) / 6;
-       else
-               priv->UndecoratedSmoothedSS = priv->SignalStrength * 10;
+               smoothedSS = ((priv->UndecoratedSmoothedSS * 5) +
+                               smoothedSS) / 6;
 
-       priv->UndercorateSmoothedRxPower = ((priv->UndercorateSmoothedRxPower * 50) +
-                                           (priv->RxPower * 11)) / 60;
+       priv->UndecoratedSmoothedSS = smoothedSS;
+
+       smoothedRx = ((priv->UndecoratedSmoothedRxPower * 50) +
+                       (priv->RxPower * 11)) / 60;
+
+       priv->UndecoratedSmoothedRxPower = smoothedRx;
 
        if (bCckRate)
                priv->CurCCKRSSI = priv->RSSI;
@@ -1206,8 +1226,9 @@ static void rtl8180_rx(struct net_device *dev)
        rx_desc_size = 8;
 
        if ((*(priv->rxringtail)) & (1<<31)) {
-               /* we have got an RX int, but the descriptor
-                * we are pointing is empty */
+               /* we have got an RX int, but the descriptor. we are pointing
+                * is empty.
+                */
 
                priv->stats.rxnodata++;
                priv->ieee80211->stats.rx_errors++;
@@ -1216,7 +1237,8 @@ static void rtl8180_rx(struct net_device *dev)
                tmp = priv->rxringtail;
                do {
                        if (tmp == priv->rxring)
-                               tmp  = priv->rxring + (priv->rxringcount - 1)*rx_desc_size;
+                               tmp  = priv->rxring + (priv->rxringcount - 1) *
+                                       rx_desc_size;
                        else
                                tmp -= rx_desc_size;
 
@@ -1254,10 +1276,9 @@ static void rtl8180_rx(struct net_device *dev)
                if (last) {
                        lastlen = ((*priv->rxringtail) & 0xfff);
 
-                       /* if the last descriptor (that should
-                        * tell us the total packet len) tell
-                        * us something less than the descriptors
-                        * len we had until now, then there is some
+                       /* if the last descriptor (that should tell us the total
+                        * packet len) tell us something less than the
+                        * descriptors len we had until now, then there is some
                         * problem..
                         * workaround to prevent kernel panic
                         */
@@ -1293,31 +1314,36 @@ static void rtl8180_rx(struct net_device *dev)
                priv->rx_prevlen += len;
 
                if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) {
-                       /* HW is probably passing several buggy frames
-                       * without FD or LD flag set.
-                       * Throw this garbage away to prevent skb
-                       * memory exhausting
-                       */
+                       /* HW is probably passing several buggy frames without
+                        * FD or LD flag set.
+                        * Throw this garbage away to prevent skb memory
+                        * exhausting
+                        */
                        if (!priv->rx_skb_complete)
                                dev_kfree_skb_any(priv->rx_skb);
                        priv->rx_skb_complete = 1;
                }
 
-               signal = (unsigned char)(((*(priv->rxringtail+3)) & (0x00ff0000))>>16);
+               signal = (unsigned char)(*(priv->rxringtail + 3) &
+                       0x00ff0000) >> 16;
                signal = (signal & 0xfe) >> 1;
 
                quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff));
 
                stats.mac_time[0] = *(priv->rxringtail+1);
                stats.mac_time[1] = *(priv->rxringtail+2);
-               rxpower = ((char)(((*(priv->rxringtail+4)) & (0x00ff0000))>>16))/2 - 42;
-               RSSI = ((u8)(((*(priv->rxringtail+3)) & (0x0000ff00))>>8)) & (0x7f);
+
+               rxpower = ((char)((*(priv->rxringtail + 4) &
+                       0x00ff0000) >> 16)) / 2 - 42;
+
+               RSSI = ((u8)((*(priv->rxringtail + 3) &
+                       0x0000ff00) >> 8)) & 0x7f;
 
                rate = ((*(priv->rxringtail)) &
                        ((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20;
 
                stats.rate = rtl8180_rate2rate(rate);
-               Antenna = (((*(priv->rxringtail+3)) & (0x00008000)) == 0) ? 0 : 1;
+               Antenna = (*(priv->rxringtail + 3) & 0x00008000) == 0 ? 0 : 1;
                if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
                        RxAGC_dBm = rxpower+1;  /* bias */
                } else { /* CCK rate. */
@@ -1326,7 +1352,8 @@ static void rtl8180_rx(struct net_device *dev)
                        LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */
                        BB  = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */
 
-                       RxAGC_dBm = -(LNA_gain[LNA] + (BB*2)); /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
+                       /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
+                       RxAGC_dBm = -(LNA_gain[LNA] + (BB * 2));
 
                        RxAGC_dBm += 4; /* bias */
                }
@@ -1354,21 +1381,25 @@ static void rtl8180_rx(struct net_device *dev)
                priv->RSSI = RSSI;
                /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
                if (quality >= 127)
-                       quality = 1; /*0; */ /* 0 will cause epc to show signal zero , walk around now; */
+                       /* 0 causes epc to show signal zero, walk around now */
+                       quality = 1;
                else if (quality < 27)
                        quality = 100;
                else
                        quality = 127 - quality;
                priv->SignalQuality = quality;
 
-               stats.signal = (u8)quality; /*priv->wstats.qual.level = priv->SignalStrength; */
+               /*priv->wstats.qual.level = priv->SignalStrength; */
+               stats.signal = (u8) quality;
+
                stats.signalstrength = RXAGC;
                if (stats.signalstrength > 100)
                        stats.signalstrength = 100;
-               stats.signalstrength = (stats.signalstrength * 70)/100 + 30;
+               stats.signalstrength = (stats.signalstrength * 70) / 100 + 30;
                /* printk("==========================>rx : RXAGC is %d,signalstrength is %d\n",RXAGC,stats.signalstrength); */
                stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
-               stats.noise = priv->wstats.qual.noise = 100 - priv->wstats.qual.qual;
+               stats.noise = priv->wstats.qual.noise =
+                       100 - priv->wstats.qual.qual;
                bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) |
                           (((*(priv->rxringtail)) & (0x04000000)) != 0) |
                           (((*(priv->rxringtail)) & (0x08000000)) != 0) |
@@ -1397,27 +1428,40 @@ static void rtl8180_rx(struct net_device *dev)
 
                        /* For good-looking singal strength. */
                        SignalStrengthIndex = NetgearSignalStrengthTranslate(
-                                                       priv->LastSignalStrengthInPercent,
-                                                       priv->SignalStrength);
+                               priv->LastSignalStrengthInPercent,
+                               priv->SignalStrength);
 
                        priv->LastSignalStrengthInPercent = SignalStrengthIndex;
-                       priv->Stats_SignalStrength = TranslateToDbm8185((u8)SignalStrengthIndex);
-               /*
-                * We need more correct power of received packets and the  "SignalStrength" of RxStats is beautified,
-                * so we record the correct power here.
-                */
-                       priv->Stats_SignalQuality = (long)(priv->Stats_SignalQuality * 5 + (long)priv->SignalQuality + 5) / 6;
-                       priv->Stats_RecvSignalPower = (long)(priv->Stats_RecvSignalPower * 5 + priv->RecvSignalPower - 1) / 6;
+                       priv->Stats_SignalStrength =
+                               TranslateToDbm8185((u8)SignalStrengthIndex);
+
+                       /*
+                        * We need more correct power of received packets and
+                        * the "SignalStrength" of RxStats is beautified, so we
+                        * record the correct power here.
+                        */
 
-               /* Figure out which antenna that received the last packet. */
-                       priv->LastRxPktAntenna = Antenna ? 1 : 0; /* 0: aux, 1: main. */
+                       priv->Stats_SignalQuality = (long)(
+                               priv->Stats_SignalQuality * 5 +
+                               (long)priv->SignalQuality + 5) / 6;
+
+                       priv->Stats_RecvSignalPower = (long)(
+                               priv->Stats_RecvSignalPower * 5 +
+                               priv->RecvSignalPower - 1) / 6;
+
+                       /*
+                        * Figure out which antenna received the last packet.
+                        * 0: aux, 1: main
+                        */
+                       priv->LastRxPktAntenna = Antenna ? 1 : 0;
                        SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
                }
 
                if (first) {
                        if (!priv->rx_skb_complete) {
                                /* seems that HW sometimes fails to receive and
-                                  doesn't provide the last descriptor */
+                                * doesn't provide the last descriptor.
+                                */
                                dev_kfree_skb_any(priv->rx_skb);
                                priv->stats.rxnolast++;
                        }
@@ -1428,15 +1472,16 @@ static void rtl8180_rx(struct net_device *dev)
                        priv->rx_skb_complete = 0;
                        priv->rx_skb->dev = dev;
                } else {
-                       /* if we are here we should have already RXed
-                       * the first frame.
-                       * If we get here and the skb is not allocated then
-                       * we have just throw out garbage (skb not allocated)
-                       * and we are still rxing garbage....
-                       */
+                       /* if we are here we should have already RXed the first
+                        * frame.
+                        * If we get here and the skb is not allocated then
+                        * we have just throw out garbage (skb not allocated)
+                        * and we are still rxing garbage....
+                        */
                        if (!priv->rx_skb_complete) {
 
-                               tmp_skb = dev_alloc_skb(priv->rx_skb->len+len+2);
+                               tmp_skb = dev_alloc_skb(
+                                       priv->rx_skb->len + len + 2);
 
                                if (!tmp_skb)
                                        goto drop;
@@ -1454,13 +1499,8 @@ static void rtl8180_rx(struct net_device *dev)
                }
 
                if (!priv->rx_skb_complete) {
-                       if (padding) {
-                               memcpy(skb_put(priv->rx_skb, len),
-                                       (((unsigned char *)priv->rxbuffer->buf) + 2), len);
-                       } else {
-                               memcpy(skb_put(priv->rx_skb, len),
-                                       priv->rxbuffer->buf, len);
-                       }
+                       memcpy(skb_put(priv->rx_skb, len), ((unsigned char *)
+                               priv->rxbuffer->buf) + (padding ? 2 : 0), len);
                }
 
                if (last && !priv->rx_skb_complete) {
@@ -1538,7 +1578,7 @@ static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
 {
        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
        int mode;
-       struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *) skb->data;
+       struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *)skb->data;
        short morefrag = (h->frame_control) & IEEE80211_FCTL_MOREFRAGS;
        unsigned long flags;
        int priority;
@@ -1547,11 +1587,10 @@ static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
 
        rate = ieeerate2rtlrate(rate);
        /*
-        * This function doesn't require lock because we make
-        * sure it's called with the tx_lock already acquired.
-        * this come from the kernel's hard_xmit callback (through
-        * the ieee stack, or from the try_wake_queue (again through
-        * the ieee stack.
+        * This function doesn't require lock because we make sure it's called
+        * with the tx_lock already acquired.
+        * This come from the kernel's hard_xmit callback (through the ieee
+        * stack, or from the try_wake_queue (again through the ieee stack.
         */
        priority = AC2Q(skb->priority);
        spin_lock_irqsave(&priv->tx_lock, flags);
@@ -1613,55 +1652,6 @@ static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-/* longpre 144+48 shortpre 72+24 */
-u16 rtl8180_len2duration(u32 len, short rate, short *ext)
-{
-       u16 duration;
-       u16 drift;
-       *ext = 0;
-
-       switch (rate) {
-       case 0: /* 1mbps */
-               *ext = 0;
-               duration = ((len+4)<<4) / 0x2;
-               drift = ((len+4)<<4) % 0x2;
-               if (drift == 0)
-                       break;
-               duration++;
-               break;
-       case 1: /* 2mbps */
-               *ext = 0;
-               duration = ((len+4)<<4) / 0x4;
-               drift = ((len+4)<<4) % 0x4;
-               if (drift == 0)
-                       break;
-               duration++;
-               break;
-       case 2: /* 5.5mbps */
-               *ext = 0;
-               duration = ((len+4)<<4) / 0xb;
-               drift = ((len+4)<<4) % 0xb;
-               if (drift == 0)
-                       break;
-               duration++;
-               break;
-       default:
-       case 3: /* 11mbps */
-               *ext = 0;
-               duration = ((len+4)<<4) / 0x16;
-               drift = ((len+4)<<4) % 0x16;
-               if (drift == 0)
-                       break;
-               duration++;
-               if (drift > 6)
-                       break;
-               *ext = 1;
-               break;
-       }
-
-       return duration;
-}
-
 static void rtl8180_prepare_beacon(struct net_device *dev)
 {
        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -1669,7 +1659,10 @@ static void rtl8180_prepare_beacon(struct net_device *dev)
 
        u16 word  = read_nic_word(dev, BcnItv);
        word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */
-       word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval); /* 0x64; */
+
+       /* word |= 0x64; */
+       word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval);
+
        write_nic_word(dev, BcnItv, word);
 
        skb = ieee80211_get_beacon(priv->ieee80211);
@@ -1681,9 +1674,9 @@ static void rtl8180_prepare_beacon(struct net_device *dev)
 }
 
 /*
- * This function do the real dirty work: it enqueues a TX command
- * descriptor in the ring buffer, copyes the frame in a TX buffer
- * and kicks the NIC to ensure it does the DMA transfer.
+ * This function do the real dirty work: it enqueues a TX command descriptor in
+ * the ring buffer, copyes the frame in a TX buffer and kicks the NIC to ensure
+ * it does the DMA transfer.
  */
 short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
                 short morefrag, short descfrag, int rate)
@@ -1697,16 +1690,17 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
        int buflen;
        int count;
        struct buffer *buflist;
-       struct ieee80211_hdr_3addr *frag_hdr = (struct ieee80211_hdr_3addr *)txbuf;
+       struct ieee80211_hdr_3addr *frag_hdr =
+               (struct ieee80211_hdr_3addr *)txbuf;
        u8 dest[ETH_ALEN];
-       u8                      bUseShortPreamble = 0;
-       u8                      bCTSEnable = 0;
-       u8                      bRTSEnable = 0;
-       u16                     Duration = 0;
-       u16                     RtsDur = 0;
-       u16                     ThisFrameTime = 0;
-       u16                     TxDescDuration = 0;
-       bool                    ownbit_flag = false;
+       u8 bUseShortPreamble = 0;
+       u8 bCTSEnable = 0;
+       u8 bRTSEnable = 0;
+       u16 Duration = 0;
+       u16 RtsDur = 0;
+       u16 ThisFrameTime = 0;
+       u16 TxDescDuration = 0;
+       bool ownbit_flag = false;
 
        switch (priority) {
        case MANAGE_PRIORITY:
@@ -1756,74 +1750,80 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
                break;
        }
 
-               memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
-               if (is_multicast_ether_addr(dest)) {
-                       Duration = 0;
-                       RtsDur = 0;
-                       bRTSEnable = 0;
+       memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
+       if (is_multicast_ether_addr(dest)) {
+               Duration = 0;
+               RtsDur = 0;
+               bRTSEnable = 0;
+               bCTSEnable = 0;
+
+               ThisFrameTime = ComputeTxTime(len + sCrcLng,
+                       rtl8180_rate2rate(rate), 0, bUseShortPreamble);
+               TxDescDuration = ThisFrameTime;
+       } else { /* Unicast packet */
+               u16 AckTime;
+
+               /* YJ,add,080828,for Keep alive */
+               priv->NumTxUnicast++;
+
+               /* Figure out ACK rate according to BSS basic rate
+                * and Tx rate.
+                * AckCTSLng = 14 use 1M bps send
+                */
+               AckTime = ComputeTxTime(14, 10, 0, 0);
+
+               if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
+                       u16 RtsTime, CtsTime;
+                       /* u16 CtsRate; */
+                       bRTSEnable = 1;
                        bCTSEnable = 0;
 
-                       ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate),
-                                                     0, bUseShortPreamble);
-                       TxDescDuration = ThisFrameTime;
-               } else { /* Unicast packet */
-                       u16 AckTime;
-
-                       /* YJ,add,080828,for Keep alive */
-                       priv->NumTxUnicast++;
-
-                       /* Figure out ACK rate according to BSS basic rate
-                        * and Tx rate. */
-                       AckTime = ComputeTxTime(14, 10, 0, 0);  /* AckCTSLng = 14 use 1M bps send */
-
-                       if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
-                               u16 RtsTime, CtsTime;
-                               /* u16 CtsRate; */
-                               bRTSEnable = 1;
-                               bCTSEnable = 0;
-
-                               /* Rate and time required for RTS. */
-                               RtsTime = ComputeTxTime(sAckCtsLng/8, priv->ieee80211->basic_rate, 0, 0);
-                               /* Rate and time required for CTS. */
-                               CtsTime = ComputeTxTime(14, 10, 0, 0);  /* AckCTSLng = 14 use 1M bps send */
-
-                               /* Figure out time required to transmit this frame. */
-                               ThisFrameTime = ComputeTxTime(len + sCrcLng,
-                                               rtl8180_rate2rate(rate),
-                                               0,
-                                               bUseShortPreamble);
-
-                               /* RTS-CTS-ThisFrame-ACK. */
-                               RtsDur = CtsTime + ThisFrameTime + AckTime + 3*aSifsTime;
-
-                               TxDescDuration = RtsTime + RtsDur;
-                       } else { /* Normal case. */
-                               bCTSEnable = 0;
-                               bRTSEnable = 0;
-                               RtsDur = 0;
-
-                               ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate),
-                                                             0, bUseShortPreamble);
-                               TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
-                       }
+                       /* Rate and time required for RTS. */
+                       RtsTime = ComputeTxTime(sAckCtsLng / 8,
+                               priv->ieee80211->basic_rate, 0, 0);
 
-                       if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) {
-                               /* ThisFrame-ACK. */
-                               Duration = aSifsTime + AckTime;
-                       } else { /* One or more fragments remained. */
-                               u16 NextFragTime;
-                               NextFragTime = ComputeTxTime(len + sCrcLng, /* pretend following packet length equal current packet */
-                                               rtl8180_rate2rate(rate),
-                                               0,
-                                               bUseShortPreamble);
-
-                               /* ThisFrag-ACk-NextFrag-ACK. */
-                               Duration = NextFragTime + 3*aSifsTime + 2*AckTime;
-                       }
+                       /* Rate and time required for CTS.
+                        * AckCTSLng = 14 use 1M bps send
+                        */
+                       CtsTime = ComputeTxTime(14, 10, 0, 0);
 
-               } /* End of Unicast packet */
+                       /* Figure out time required to transmit this frame. */
+                       ThisFrameTime = ComputeTxTime(len + sCrcLng,
+                               rtl8180_rate2rate(rate), 0,
+                               bUseShortPreamble);
 
-               frag_hdr->duration_id = Duration;
+                       /* RTS-CTS-ThisFrame-ACK. */
+                       RtsDur = CtsTime + ThisFrameTime +
+                               AckTime + 3 * aSifsTime;
+
+                       TxDescDuration = RtsTime + RtsDur;
+               } else { /* Normal case. */
+                       bCTSEnable = 0;
+                       bRTSEnable = 0;
+                       RtsDur = 0;
+
+                       ThisFrameTime = ComputeTxTime(len + sCrcLng,
+                               rtl8180_rate2rate(rate), 0, bUseShortPreamble);
+                       TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
+               }
+
+               if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) {
+                       /* ThisFrame-ACK. */
+                       Duration = aSifsTime + AckTime;
+               } else { /* One or more fragments remained. */
+                       u16 NextFragTime;
+
+                       /* pretend following packet length = current packet */
+                       NextFragTime = ComputeTxTime(len + sCrcLng,
+                               rtl8180_rate2rate(rate), 0, bUseShortPreamble);
+
+                       /* ThisFrag-ACk-NextFrag-ACK. */
+                       Duration = NextFragTime + 3 * aSifsTime + 2 * AckTime;
+               }
+
+       } /* End of Unicast packet */
+
+       frag_hdr->duration_id = Duration;
 
        buflen = priv->txbuffsize;
        remain = len;
@@ -1832,7 +1832,8 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
        while (remain != 0) {
                mb();
                if (!buflist) {
-                       DMESGE("TX buffer error, cannot TX frames. pri %d.", priority);
+                       DMESGE("TX buffer error, cannot TX frames. pri %d.",
+                               priority);
                        return -1;
                }
                buf = buflist->buf;
@@ -1851,43 +1852,54 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
                *(tail+6) = 0;
                *(tail+7) = 0;
 
-               /* FIXME: this should be triggered by HW encryption parameters.*/
+               /* FIXME: should be triggered by HW encryption parameters.*/
                *tail |= (1<<15); /* no encrypt */
 
                if (remain == len && !descfrag) {
                        ownbit_flag = false;
-                       *tail = *tail | (1<<29); /* fist segment of the packet */
+                       *tail = *tail | (1 << 29); /* first segment of packet */
                        *tail = *tail | (len);
                } else {
                        ownbit_flag = true;
                }
 
                for (i = 0; i < buflen && remain > 0; i++, remain--) {
-                       ((u8 *)buf)[i] = txbuf[i]; /* copy data into descriptor pointed DMAble buffer */
+                       /* copy data into descriptor pointed DMAble buffer */
+                       ((u8 *)buf)[i] = txbuf[i];
+
                        if (remain == 4 && i+4 >= buflen)
                                break;
                        /* ensure the last desc has at least 4 bytes payload */
-
                }
                txbuf = txbuf + i;
                *(tail+3) = *(tail+3) & ~0xfff;
                *(tail+3) = *(tail+3) | i; /* buffer length */
-               /* Use short preamble or not */
-               if (priv->ieee80211->current_network.capability&WLAN_CAPABILITY_SHORT_PREAMBLE)
-                       if (priv->plcp_preamble_mode == 1 && rate != 0) /*  short mode now, not long! */
-                       ; /* *tail |= (1<<16); */                               /* enable short preamble mode. */
+
+               /* Use short preamble or not - if true, enable short preamble */
+               /*
+               if (priv->ieee80211->current_network.capability &
+                       WLAN_CAPABILITY_SHORT_PREAMBLE &&
+                       priv->plcp_preamble_mode == 1 && rate != 0) {
+                       *tail |= (1 << 16);
+               }
+               */
 
                if (bCTSEnable)
                        *tail |= (1<<18);
 
                if (bRTSEnable) { /* rts enable */
-                       *tail |= ((ieeerate2rtlrate(priv->ieee80211->basic_rate))<<19); /* RTS RATE */
+                       /* RTS RATE */
+                       *tail |= (ieeerate2rtlrate(
+                               priv->ieee80211->basic_rate) << 19);
+
                        *tail |= (1<<23); /* rts enable */
                        *(tail+1) |= (RtsDur&0xffff); /* RTS Duration */
                }
                *(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */
                /* *(tail+3) |= (0xe6<<16); */
-               *(tail+5) |= (11<<8); /* (priv->retry_data<<8); */ /* retry lim; */
+
+               /* (priv->retry_data<<8); */
+               *(tail + 5) |= (11 << 8); /* retry lim; */
 
                *tail = *tail | ((rate&0xf) << 24);
 
@@ -1901,7 +1913,8 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
 
                wmb();
                if (ownbit_flag)
-                       *tail = *tail | (1<<31); /* descriptor ready to be txed */
+                       /* descriptor ready to be txed */
+                       *tail |= (1 << 31);
 
                if ((tail - begin)/8 == count-1)
                        tail = begin;
@@ -1983,7 +1996,8 @@ static void rtl8180_rq_tx_ack(struct net_device *dev)
 
        struct r8180_priv *priv = ieee80211_priv(dev);
 
-       write_nic_byte(dev, CONFIG4, read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
+       write_nic_byte(dev, CONFIG4,
+               read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
        priv->ack_tx_to_ieee = 1;
 }
 
@@ -2031,7 +2045,8 @@ static void rtl8180_hw_wakeup(struct net_device *dev)
        struct r8180_priv *priv = ieee80211_priv(dev);
 
        spin_lock_irqsave(&priv->ps_lock, flags);
-       write_nic_byte(dev, CONFIG4, read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
+       write_nic_byte(dev, CONFIG4,
+               read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
        if (priv->rf_wakeup)
                priv->rf_wakeup(dev);
        spin_unlock_irqrestore(&priv->ps_lock, flags);
@@ -2063,13 +2078,13 @@ static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
        tl -= MSECS(4+16+7);
 
        /*
-        * If the interval in witch we are requested to sleep is too
+        * If the interval in which we are requested to sleep is too
         * short then give up and remain awake
         */
        if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME))
                || ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
                spin_unlock_irqrestore(&priv->ps_lock, flags);
-               printk("too short to sleep\n");
+               netdev_warn(dev, "too short to sleep\n");
                return;
        }
 
@@ -2078,7 +2093,8 @@ static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
 
                priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp);
                /* as tl may be less than rb */
-               queue_delayed_work(priv->ieee80211->wq, &priv->ieee80211->hw_wakeup_wq, tmp);
+               queue_delayed_work(priv->ieee80211->wq,
+                       &priv->ieee80211->hw_wakeup_wq, tmp);
        }
        /*
         * If we suspect the TimerInt is gone beyond tl
@@ -2095,16 +2111,49 @@ static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
        spin_unlock_irqrestore(&priv->ps_lock, flags);
 }
 
+static void rtl8180_wmm_single_param_update(struct net_device *dev,
+       u8 mode, AC_CODING eACI, PAC_PARAM param)
+{
+       u8 u1bAIFS;
+       u32 u4bAcParam;
+
+       /* Retrieve parameters to update. */
+       /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
+       u1bAIFS = param->f.AciAifsn.f.AIFSN * ((mode & IEEE_G) == IEEE_G ?
+               9 : 20) + aSifsTime;
+       u4bAcParam = (((u32)param->f.TXOPLimit << AC_PARAM_TXOP_LIMIT_OFFSET) |
+               ((u32)param->f.Ecw.f.ECWmax << AC_PARAM_ECW_MAX_OFFSET) |
+               ((u32)param->f.Ecw.f.ECWmin << AC_PARAM_ECW_MIN_OFFSET) |
+               ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
+
+       switch (eACI) {
+       case AC1_BK:
+               write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
+               return;
+       case AC0_BE:
+               write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
+               return;
+       case AC2_VI:
+               write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
+               return;
+       case AC3_VO:
+               write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
+               return;
+       default:
+               pr_warn("SetHwReg8185(): invalid ACI: %d!\n", eACI);
+               return;
+       }
+}
+
 static void rtl8180_wmm_param_update(struct work_struct *work)
 {
-       struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wmm_param_update_wq);
+       struct ieee80211_device *ieee = container_of(work,
+               struct ieee80211_device, wmm_param_update_wq);
        struct net_device *dev = ieee->dev;
        u8 *ac_param = (u8 *)(ieee->current_network.wmm_param);
        u8 mode = ieee->current_network.mode;
-       AC_CODING       eACI;
-       AC_PARAM        AcParam;
-       PAC_PARAM       pAcParam;
-       u8 i;
+       AC_CODING eACI;
+       AC_PARAM AcParam;
 
        if (!ieee->current_network.QoS_Enable) {
                /* legacy ac_xx_param update */
@@ -2114,78 +2163,24 @@ static void rtl8180_wmm_param_update(struct work_struct *work)
                AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */
                AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */
                AcParam.f.TXOPLimit = 0;
+
                for (eACI = 0; eACI < AC_MAX; eACI++) {
                        AcParam.f.AciAifsn.f.ACI = (u8)eACI;
-                       {
-                               u8              u1bAIFS;
-                               u32             u4bAcParam;
-                               pAcParam = (PAC_PARAM)(&AcParam);
-                               /* Retrieve parameters to update. */
-                               u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
-                               u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit))<<AC_PARAM_TXOP_LIMIT_OFFSET)|
-                                             (((u32)(pAcParam->f.Ecw.f.ECWmax))<<AC_PARAM_ECW_MAX_OFFSET)|
-                                             (((u32)(pAcParam->f.Ecw.f.ECWmin))<<AC_PARAM_ECW_MIN_OFFSET)|
-                                              (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
-                               switch (eACI) {
-                               case AC1_BK:
-                                       write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
-                                       break;
-                               case AC0_BE:
-                                       write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
-                                       break;
-                               case AC2_VI:
-                                       write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
-                                       break;
-                               case AC3_VO:
-                                       write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
-                                       break;
-                               default:
-                                       pr_warn("SetHwReg8185():invalid ACI: %d!\n",
-                                               eACI);
-                                       break;
-                               }
-                       }
+
+                       rtl8180_wmm_single_param_update(dev, mode, eACI,
+                               (PAC_PARAM)&AcParam);
                }
                return;
        }
 
-       for (i = 0; i < AC_MAX; i++) {
+       for (eACI = 0; eACI < AC_MAX; eACI++) {
                /* AcParam.longData = 0; */
-               pAcParam = (AC_PARAM *)ac_param;
-               {
-                       AC_CODING       eACI;
-                       u8              u1bAIFS;
-                       u32             u4bAcParam;
-
-                       /* Retrieve parameters to update. */
-                       eACI = pAcParam->f.AciAifsn.f.ACI;
-                       /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
-                       u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
-                       u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET)    |
-                                       (((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET)  |
-                                       (((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET)  |
-                                       (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
-
-                       switch (eACI) {
-                       case AC1_BK:
-                               write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
-                               break;
-                       case AC0_BE:
-                               write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
-                               break;
-                       case AC2_VI:
-                               write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
-                               break;
-                       case AC3_VO:
-                               write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
-                               break;
-                       default:
-                               pr_warn("SetHwReg8185(): invalid ACI: %d !\n",
-                                       eACI);
-                               break;
-                       }
-               }
-               ac_param += (sizeof(AC_PARAM));
+
+               rtl8180_wmm_single_param_update(dev, mode,
+                       ((PAC_PARAM)ac_param)->f.AciAifsn.f.ACI,
+                       (PAC_PARAM)ac_param);
+
+               ac_param += sizeof(AC_PARAM);
        }
 }
 
@@ -2208,7 +2203,8 @@ static void watch_dog_adaptive(unsigned long data)
 
        /* Tx High Power Mechanism. */
        if (CheckHighPower((struct net_device *)data))
-               queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->tx_pw_wq);
+               queue_work(priv->ieee80211->wq,
+                       (void *)&priv->ieee80211->tx_pw_wq);
 
        /* Tx Power Tracking on 87SE. */
        if (CheckTxPwrTracking((struct net_device *)data))
@@ -2216,27 +2212,59 @@ static void watch_dog_adaptive(unsigned long data)
 
        /* Perform DIG immediately. */
        if (CheckDig((struct net_device *)data))
-               queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_dig_wq);
+               queue_work(priv->ieee80211->wq,
+                       (void *)&priv->ieee80211->hw_dig_wq);
+
        rtl8180_watch_dog((struct net_device *)data);
 
-       queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
+       queue_work(priv->ieee80211->wq,
+               (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
+
+       priv->watch_dog_timer.expires = jiffies +
+               MSECS(IEEE80211_WATCH_DOG_TIME);
 
-       priv->watch_dog_timer.expires = jiffies + MSECS(IEEE80211_WATCH_DOG_TIME);
        add_timer(&priv->watch_dog_timer);
 }
 
-static CHANNEL_LIST ChannelPlan[] = {
-       {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64},19},         /* FCC */
-       {{1,2,3,4,5,6,7,8,9,10,11},11},                                 /* IC */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},   /* ETSI */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},   /* Spain. Change to ETSI. */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},   /* France. Change to ETSI. */
-       {{14,36,40,44,48,52,56,60,64},9},                               /* MKK */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,14, 36,40,44,48,52,56,60,64},22},/* MKK1 */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},   /* Israel. */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,34,38,42,46},17},               /* For 11a , TELEC */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},  /* For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626 */
-       {{1,2,3,4,5,6,7,8,9,10,11,12,13},13} /* world wide 13: ch1~ch11 active scan, ch12~13 passive //lzm add 080826 */
+static struct rtl8187se_channel_list channel_plan_list[] = {
+       /* FCC */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40,
+               44, 48, 52, 56, 60, 64}, 19},
+
+       /* IC */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
+
+       /* ETSI */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+               44, 48, 52, 56, 60, 64}, 21},
+
+       /* Spain. Change to ETSI. */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+               44, 48, 52, 56, 60, 64}, 21},
+
+       /* France. Change to ETSI. */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+               44, 48, 52, 56, 60, 64}, 21},
+
+       /* MKK */
+       {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9},
+
+       /* MKK1 */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36,
+               40, 44, 48, 52, 56, 60, 64}, 22},
+
+       /* Israel. */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+               44, 48, 52, 56, 60, 64}, 21},
+
+       /* For 11a , TELEC */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17},
+
+       /* For Global Domain. 1-11 active, 12-14 passive. //+YJ, 080626 */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+
+       /* world wide 13: ch1~ch11 active, ch12~13 passive //lzm add 080826 */
+       {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}
 };
 
 static void rtl8180_set_channel_map(u8 channel_plan,
@@ -2261,13 +2289,13 @@ static void rtl8180_set_channel_map(u8 channel_plan,
                {
                        Dot11d_Init(ieee);
                        ieee->bGlobalDomain = false;
-                       if (ChannelPlan[channel_plan].Len != 0) {
+                       if (channel_plan_list[channel_plan].len != 0) {
                                /* Clear old channel map */
                                memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
                                /* Set new channel map */
-                               for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
-                                       if (ChannelPlan[channel_plan].Channel[i] <= 14)
-                                               GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
+                               for (i = 0; i < channel_plan_list[channel_plan].len; i++) {
+                                       if (channel_plan_list[channel_plan].channel[i] <= 14)
+                                               GET_DOT11D_INFO(ieee)->channel_map[channel_plan_list[channel_plan].channel[i]] = 1;
                                }
                        }
                        break;
@@ -2300,15 +2328,15 @@ static void rtl8180_set_channel_map(u8 channel_plan,
 void GPIOChangeRFWorkItemCallBack(struct work_struct *work);
 
 /* YJ,add,080828 */
-static void rtl8180_statistics_init(struct Stats *pstats)
+static void rtl8180_statistics_init(struct stats *pstats)
 {
-       memset(pstats, 0, sizeof(struct Stats));
+       memset(pstats, 0, sizeof(struct stats));
 }
 
-static void rtl8180_link_detect_init(plink_detect_t plink_detect)
+static void rtl8180_link_detect_init(struct link_detect_t *plink_detect)
 {
-       memset(plink_detect, 0, sizeof(link_detect_t));
-       plink_detect->SlotNum = DEFAULT_SLOT_NUM;
+       memset(plink_detect, 0, sizeof(struct link_detect_t));
+       plink_detect->slot_num = DEFAULT_SLOT_NUM;
 }
 
 /* YJ,add,080828,end */
@@ -2360,7 +2388,7 @@ static short rtl8180_init(struct net_device *dev)
        eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
        priv->channel_plan = eeprom_val & 0xFF;
        if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) {
-               printk("rtl8180_init:Error channel plan! Set to default.\n");
+               netdev_err(dev, "rtl8180_init: Invalid channel plan! Set to default.\n");
                priv->channel_plan = 0;
        }
 
@@ -2385,7 +2413,8 @@ static short rtl8180_init(struct net_device *dev)
        rtl8180_link_detect_init(&priv->link_detect);
 
        priv->ack_tx_to_ieee = 0;
-       priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
+       priv->ieee80211->current_network.beacon_interval =
+               DEFAULT_BEACONINTERVAL;
        priv->ieee80211->iw_mode = IW_MODE_INFRA;
        priv->ieee80211->softmac_features  = IEEE_SOFTMAC_SCAN |
                IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
@@ -2431,7 +2460,8 @@ static short rtl8180_init(struct net_device *dev)
        priv->AdRxSsBeforeSwitched = 0;
        init_timer(&priv->SwAntennaDiversityTimer);
        priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
-       priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback;
+       priv->SwAntennaDiversityTimer.function =
+               (void *)SwAntennaDiversityTimerCallback;
        priv->bDigMechanism = true;
        priv->InitialGain = 6;
        priv->bXtalCalibration = false;
@@ -2440,7 +2470,8 @@ static short rtl8180_init(struct net_device *dev)
        priv->bTxPowerTrack = false;
        priv->ThermalMeter = 0;
        priv->FalseAlarmRegValue = 0;
-       priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm, which is used in DIG. */
+       priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm,
+                                       which is used in DIG. */
        priv->DIG_NumberFallbackVote = 0;
        priv->DIG_NumberUpgradeVote = 0;
        priv->LastSignalStrengthInPercent = 0;
@@ -2585,7 +2616,8 @@ static short rtl8180_init(struct net_device *dev)
                priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity;
        else
                /* 1:disable antenna diversity, 2: enable antenna diversity. */
-               priv->bSwAntennaDiverity = priv->RegSwAntennaDiversityMechanism == 2;
+               priv->bSwAntennaDiverity =
+                       priv->RegSwAntennaDiversityMechanism == 2;
 
        if (priv->RegDefaultAntenna == 0)
                /* 0: default from EEPROM. */
@@ -2669,7 +2701,8 @@ static short rtl8180_init(struct net_device *dev)
                                  TX_BEACON_RING_ADDR))
                return -ENOMEM;
 
-       if (request_irq(dev->irq, rtl8180_interrupt, IRQF_SHARED, dev->name, dev)) {
+       if (request_irq(dev->irq, rtl8180_interrupt,
+               IRQF_SHARED, dev->name, dev)) {
                DMESGE("Error allocating IRQ %d", dev->irq);
                return -1;
        } else {
@@ -2768,16 +2801,19 @@ static void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data)
 
        phyw = ((data<<8) | adr);
 
-       /* Note that, we must write 0xff7c after 0x7d-0x7f to write BB register. */
+       /* Note: we must write 0xff7c after 0x7d-0x7f to write BB register. */
        write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24));
        write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16));
        write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8));
        write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff)));
 
-       /* this is ok to fail when we write AGC table. check for AGC table might be
-        * done by masking with 0x7f instead of 0xff
+       /* this is ok to fail when we write AGC table. check for AGC table
+        * might be done by masking with 0x7f instead of 0xff
         */
-       /* if (phyr != (data&0xff)) DMESGW("Phy write timeout %x %x %x", phyr, data, adr); */
+       /*
+       if (phyr != (data&0xff))
+               DMESGW("Phy write timeout %x %x %x", phyr, data, adr);
+       */
 }
 
 inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data)
@@ -2812,9 +2848,9 @@ void rtl8180_start_tx_beacon(struct net_device *dev)
        word  = read_nic_word(dev, BintrItv);
        word &= ~BintrItv_BintrItv;
        word |= 1000; /* priv->ieee80211->current_network.beacon_interval *
-               ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
-       // FIXME: check if correct ^^ worked with 0x3e8;
-       */
+                      * ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
+                      * FIXME: check if correct ^^ worked with 0x3e8;
+                      */
        write_nic_word(dev, BintrItv, word);
 
        rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
@@ -2846,25 +2882,26 @@ static bool MgntActSet_802_11_PowerSaveMode(struct r8180_priv *priv,
 
 static void LeisurePSEnter(struct r8180_priv *priv)
 {
-       if (priv->bLeisurePs) {
+       if (priv->bLeisurePs)
                if (priv->ieee80211->ps == IEEE80211_PS_DISABLED)
                        /* IEEE80211_PS_ENABLE */
-                       MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
-       }
+                       MgntActSet_802_11_PowerSaveMode(priv,
+                               IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST);
 }
 
 static void LeisurePSLeave(struct r8180_priv *priv)
 {
-       if (priv->bLeisurePs) {
+       if (priv->bLeisurePs)
                if (priv->ieee80211->ps != IEEE80211_PS_DISABLED)
-                       MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_DISABLED);
-       }
+                       MgntActSet_802_11_PowerSaveMode(
+                               priv, IEEE80211_PS_DISABLED);
 }
 
 void rtl8180_hw_wakeup_wq(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
-       struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_wakeup_wq);
+       struct ieee80211_device *ieee = container_of(
+               dwork, struct ieee80211_device, hw_wakeup_wq);
        struct net_device *dev = ieee->dev;
 
        rtl8180_hw_wakeup(dev);
@@ -2873,7 +2910,8 @@ void rtl8180_hw_wakeup_wq(struct work_struct *work)
 void rtl8180_hw_sleep_wq(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
-       struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_sleep_wq);
+       struct ieee80211_device *ieee = container_of(
+               dwork, struct ieee80211_device, hw_sleep_wq);
        struct net_device *dev = ieee->dev;
 
        rtl8180_hw_sleep_down(dev);
@@ -2890,23 +2928,30 @@ static void MgntLinkKeepAlive(struct r8180_priv *priv)
                 */
 
                if ((priv->keepAliveLevel == 2) ||
-                       (priv->link_detect.LastNumTxUnicast == priv->NumTxUnicast &&
-                       priv->link_detect.LastNumRxUnicast == priv->ieee80211->NumRxUnicast)
+                       (priv->link_detect.last_num_tx_unicast ==
+                               priv->NumTxUnicast &&
+                       priv->link_detect.last_num_rx_unicast ==
+                               priv->ieee80211->NumRxUnicast)
                        ) {
-                       priv->link_detect.IdleCount++;
+                       priv->link_detect.idle_count++;
 
                        /*
-                        * Send a Keep-Alive packet packet to AP if we had been idle for a while.
+                        * Send a Keep-Alive packet packet to AP if we had
+                        * been idle for a while.
                         */
-                       if (priv->link_detect.IdleCount >= ((KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)-1)) {
-                               priv->link_detect.IdleCount = 0;
-                               ieee80211_sta_ps_send_null_frame(priv->ieee80211, false);
+                       if (priv->link_detect.idle_count >=
+                               KEEP_ALIVE_INTERVAL /
+                               CHECK_FOR_HANG_PERIOD - 1) {
+                               priv->link_detect.idle_count = 0;
+                               ieee80211_sta_ps_send_null_frame(
+                                       priv->ieee80211, false);
                        }
                } else {
-                       priv->link_detect.IdleCount = 0;
+                       priv->link_detect.idle_count = 0;
                }
-               priv->link_detect.LastNumTxUnicast = priv->NumTxUnicast;
-               priv->link_detect.LastNumRxUnicast = priv->ieee80211->NumRxUnicast;
+               priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast;
+               priv->link_detect.last_num_rx_unicast =
+                       priv->ieee80211->NumRxUnicast;
        }
 }
 
@@ -2926,15 +2971,22 @@ void rtl8180_watch_dog(struct net_device *dev)
                        IPSEnter(dev);
        }
        /* YJ,add,080828,for link state check */
-       if ((priv->ieee80211->state == IEEE80211_LINKED) && (priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
-               SlotIndex = (priv->link_detect.SlotIndex++) % priv->link_detect.SlotNum;
-               priv->link_detect.RxFrameNum[SlotIndex] = priv->ieee80211->NumRxDataInPeriod + priv->ieee80211->NumRxBcnInPeriod;
-               for (i = 0; i < priv->link_detect.SlotNum; i++)
-                       TotalRxNum += priv->link_detect.RxFrameNum[i];
+       if ((priv->ieee80211->state == IEEE80211_LINKED) &&
+               (priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
+               SlotIndex = (priv->link_detect.slot_index++) %
+                       priv->link_detect.slot_num;
+
+               priv->link_detect.rx_frame_num[SlotIndex] =
+                       priv->ieee80211->NumRxDataInPeriod +
+                       priv->ieee80211->NumRxBcnInPeriod;
+
+               for (i = 0; i < priv->link_detect.slot_num; i++)
+                       TotalRxNum += priv->link_detect.rx_frame_num[i];
 
                if (TotalRxNum == 0) {
                        priv->ieee80211->state = IEEE80211_ASSOCIATING;
-                       queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
+                       queue_work(priv->ieee80211->wq,
+                               &priv->ieee80211->associate_procedure_wq);
                }
        }
 
@@ -2945,13 +2997,15 @@ void rtl8180_watch_dog(struct net_device *dev)
        LeisurePSLeave(priv);
 
        if (priv->ieee80211->state == IEEE80211_LINKED) {
-               priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
-               if (priv->link_detect.NumRxOkInPeriod > 666 ||
-                       priv->link_detect.NumTxOkInPeriod > 666) {
+               priv->link_detect.num_rx_ok_in_period =
+                       priv->ieee80211->NumRxDataInPeriod;
+               if (priv->link_detect.num_rx_ok_in_period > 666 ||
+                       priv->link_detect.num_tx_ok_in_period > 666) {
                        bBusyTraffic = true;
                }
-               if (((priv->link_detect.NumRxOkInPeriod + priv->link_detect.NumTxOkInPeriod) > 8)
-                       || (priv->link_detect.NumRxOkInPeriod > 2)) {
+               if ((priv->link_detect.num_rx_ok_in_period +
+                       priv->link_detect.num_tx_ok_in_period > 8)
+                       || (priv->link_detect.num_rx_ok_in_period > 2)) {
                        bEnterPS = false;
                } else
                        bEnterPS = true;
@@ -2962,9 +3016,9 @@ void rtl8180_watch_dog(struct net_device *dev)
                        LeisurePSLeave(priv);
        } else
                LeisurePSLeave(priv);
-       priv->link_detect.bBusyTraffic = bBusyTraffic;
-       priv->link_detect.NumRxOkInPeriod = 0;
-       priv->link_detect.NumTxOkInPeriod = 0;
+       priv->link_detect.b_busy_traffic = bBusyTraffic;
+       priv->link_detect.num_rx_ok_in_period = 0;
+       priv->link_detect.num_tx_ok_in_period = 0;
        priv->ieee80211->NumRxDataInPeriod = 0;
        priv->ieee80211->NumRxBcnInPeriod = 0;
 }
@@ -3048,14 +3102,16 @@ int rtl8180_down(struct net_device *dev)
        cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
        del_timer_sync(&priv->SwAntennaDiversityTimer);
        SetZebraRFPowerState8185(dev, eRfOff);
-       memset(&(priv->ieee80211->current_network), 0, sizeof(struct ieee80211_network));
+       memset(&priv->ieee80211->current_network,
+               0, sizeof(struct ieee80211_network));
        priv->ieee80211->state = IEEE80211_NOLINK;
        return 0;
 }
 
 void rtl8180_restart_wq(struct work_struct *work)
 {
-       struct r8180_priv *priv = container_of(work, struct r8180_priv, reset_wq);
+       struct r8180_priv *priv = container_of(
+               work, struct r8180_priv, reset_wq);
        struct net_device *dev = priv->dev;
 
        down(&priv->wx_sem);
@@ -3116,7 +3172,8 @@ static int r8180_set_mac_adr(struct net_device *dev, void *mac)
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
 
        if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
-               memcpy(priv->ieee80211->current_network.bssid, dev->dev_addr, ETH_ALEN);
+               memcpy(priv->ieee80211->current_network.bssid,
+                       dev->dev_addr, ETH_ALEN);
 
        if (priv->up) {
                rtl8180_down(dev);
@@ -3137,7 +3194,8 @@ static int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        switch (cmd) {
        case RTL_IOCTL_WPA_SUPPLICANT:
-               ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
+               ret = ieee80211_wpa_supplicant_ioctl(
+                       priv->ieee80211, &wrq->u.data);
                return ret;
        default:
                return -EOPNOTSUPP;
@@ -3586,7 +3644,7 @@ static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
        }
 
        if (inta & ISR_THPDOK) { /* High priority tx ok */
-               priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+               priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
                priv->stats.txhpokint++;
                rtl8180_tx_isr(dev, HI_PRIORITY, 0);
        }
@@ -3649,14 +3707,14 @@ static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
                priv->stats.txoverflow++;
 
        if (inta & ISR_TNPDOK) { /* Normal priority tx ok */
-               priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+               priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
                priv->stats.txnpokint++;
                rtl8180_tx_isr(dev, NORM_PRIORITY, 0);
                rtl8180_try_wake_queue(dev, NORM_PRIORITY);
        }
 
        if (inta & ISR_TLPDOK) { /* Low priority tx ok */
-               priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+               priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
                priv->stats.txlpokint++;
                rtl8180_tx_isr(dev, LOW_PRIORITY, 0);
                rtl8180_try_wake_queue(dev, LOW_PRIORITY);
@@ -3664,14 +3722,14 @@ static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
 
        if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */
                priv->stats.txbkpokint++;
-               priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+               priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
                rtl8180_tx_isr(dev, BK_PRIORITY, 0);
                rtl8180_try_wake_queue(dev, BE_PRIORITY);
        }
 
        if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */
                priv->stats.txbeperr++;
-               priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+               priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
                rtl8180_tx_isr(dev, BE_PRIORITY, 0);
                rtl8180_try_wake_queue(dev, BE_PRIORITY);
        }
@@ -3688,7 +3746,8 @@ void rtl8180_irq_rx_tasklet(struct r8180_priv *priv)
 
 void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
 {
-       struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
+       struct ieee80211_device *ieee = container_of(
+               work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
        struct net_device *dev = ieee->dev;
        struct r8180_priv *priv = ieee80211_priv(dev);
        u8 btPSR;
@@ -3698,7 +3757,8 @@ void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
 
        char *argv[3];
        static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
-       static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
+       static char *envp[] = {"HOME=/", "TERM=linux",
+               "PATH=/usr/bin:/bin", NULL};
        static int readf_count;
 
        readf_count = (readf_count+1)%0xffff;
index 9b676e027cadbc40f5916f3b9094be477c379b30..b55249170f18b2f36cb02ca127c766a32b222063 100644 (file)
@@ -29,7 +29,7 @@ static u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
 
 #define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
 
-static CHANNEL_LIST DefaultChannelPlan[] = {
+static struct rtl8187se_channel_list default_channel_plan[] = {
        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19},              /* FCC */
        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                                              /* IC */
        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},      /* ETSI */
@@ -337,7 +337,7 @@ static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
                }       else    {
                        /* prevent scan in BusyTraffic */
                        /* FIXME: Need to consider last scan time */
-                       if ((priv->link_detect.bBusyTraffic) && (true)) {
+                       if ((priv->link_detect.b_busy_traffic) && (true)) {
                                ret = 0;
                                printk("Now traffic is busy, please try later!\n");
                        }       else
@@ -1030,15 +1030,15 @@ static int r8180_wx_set_channelplan(struct net_device *dev,
 
        /* unsigned long flags; */
        down(&priv->wx_sem);
-       if (DefaultChannelPlan[*val].Len != 0)  {
+       if (default_channel_plan[*val].len != 0) {
                priv->channel_plan = *val;
                /* Clear old channel map 8 */
                for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
                        GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0;
 
                /* Set new channel map */
-               for (i = 1; i <= DefaultChannelPlan[*val].Len; i++)
-                       GET_DOT11D_INFO(priv->ieee80211)->channel_map[DefaultChannelPlan[*val].Channel[i-1]] = 1;
+               for (i = 1; i <= default_channel_plan[*val].len; i++)
+                       GET_DOT11D_INFO(priv->ieee80211)->channel_map[default_channel_plan[*val].channel[i-1]] = 1;
 
        }
        up(&priv->wx_sem);
index c8b9baff1dbce491adff7db3aed358bf48464c28..48eda5564ba50cb92e297f9b9ae891d893068adf 100644 (file)
@@ -873,7 +873,7 @@ static u8 GetSupportedWirelessMode8185(struct net_device *dev)
 static void
 ActUpdateChannelAccessSetting(struct net_device *dev,
                              WIRELESS_MODE WirelessMode,
-                             PCHANNEL_ACCESS_SETTING ChnlAccessSetting)
+                             struct chnl_access_setting *chnl_access_setting)
 {
        AC_CODING       eACI;
 
@@ -890,25 +890,25 @@ ActUpdateChannelAccessSetting(struct net_device *dev,
         */
 
        /* Suggested by Jong, 2005.12.08. */
-       ChnlAccessSetting->SIFS_Timer = 0x22;
-       ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
-       ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
+       chnl_access_setting->sifs_timer = 0x22;
+       chnl_access_setting->difs_timer = 0x1C; /* 2006.06.02, by rcnjko. */
+       chnl_access_setting->slot_time_timer = 9; /* 2006.06.02, by rcnjko. */
        /*
         * Suggested by wcchu, it is the default value of EIFS register,
         * 2005.12.08.
         */
-       ChnlAccessSetting->EIFS_Timer = 0x5B;
-       ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
-       ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
+       chnl_access_setting->eifs_timer = 0x5B;
+       chnl_access_setting->cwmin_index = 3; /* 2006.06.02, by rcnjko. */
+       chnl_access_setting->cwmax_index = 7; /* 2006.06.02, by rcnjko. */
 
-       write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
+       write_nic_byte(dev, SIFS, chnl_access_setting->sifs_timer);
        /*
         * Rewrited from directly use PlatformEFIOWrite1Byte(),
         * by Annie, 2006-03-29.
         */
-       write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer);
+       write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer);
 
-       write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
+       write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer);
 
        /*
         * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS
index 62a614706308e3aba40048410759d16ede29380a..0f1c1e5d25dd1a2d2663d5a610d1521cfb78e06a 100644 (file)
@@ -94,7 +94,7 @@ static void update_BCNTIM(struct adapter *padapter)
                } else {
                        tim_ielen = 0;
 
-                       /* calucate head_len */
+                       /* calculate head_len */
                        offset = _FIXED_IE_LENGTH_;
                        offset += pnetwork_mlmeext->Ssid.SsidLength + 2;
 
@@ -129,7 +129,7 @@ static void update_BCNTIM(struct adapter *padapter)
                *dst_ie++ = tim_ielen;
 
                *dst_ie++ = 0;/* DTIM count */
-               *dst_ie++ = 1;/* DTIM peroid */
+               *dst_ie++ = 1;/* DTIM period */
 
                if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */
                        *dst_ie++ = BIT(0);/* bitmap ctrl */
@@ -821,7 +821,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
        /* update cur_wireless_mode */
        update_wireless_mode(padapter);
 
-       /* udpate capability after cur_wireless_mode updated */
+       /* update capability after cur_wireless_mode updated */
        update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork));
 
        /* let pnetwork_mlmeext == pnetwork_mlme. */
@@ -1415,7 +1415,7 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
 
 /*
 op_mode
-Set to 0 (HT pure) under the followign conditions
+Set to 0 (HT pure) under the following conditions
        - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
        - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
 Set to 1 (HT non-member protection) if there may be non-HT STAs
@@ -1494,7 +1494,7 @@ static int rtw_ht_operation_update(struct adapter *padapter)
 
 void associated_clients_update(struct adapter *padapter, u8 updated)
 {
-       /* update associcated stations cap. */
+       /* update associated stations cap. */
        if (updated) {
                struct list_head *phead, *plist;
                struct sta_info *psta = NULL;
@@ -1647,7 +1647,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
                update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
        }
 
-       /* update associcated stations cap. */
+       /* update associated stations cap. */
        associated_clients_update(padapter,  beacon_updated);
 
        DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
@@ -1711,7 +1711,7 @@ u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
                update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
        }
 
-       /* update associcated stations cap. */
+       /* update associated stations cap. */
 
        DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
 
index 75e38d4ff4c38dc166e48e742e83fc4d16c89484..96c8a93ad97fcda6d877e7dc4664962777064bbb 100644 (file)
@@ -543,10 +543,10 @@ int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
                        if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
                                if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
                                        /*  L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
-                                       DEBUG_INFO("NAT25: Set DA as boardcast\n");
+                                       DEBUG_INFO("NAT25: Set DA as broadcast\n");
                                        memset(skb->data, 0xff, ETH_ALEN);
                                } else {
-                                       /*  forward unknow IP packet to upper TCP/IP */
+                                       /*  forward unknown IP packet to upper TCP/IP */
                                        DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
                                        if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0) {
                                                printk("Re-init netdev_br_init() due to br_mac == 0!\n");
@@ -932,7 +932,7 @@ int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
                                                (ph->code == PADO_CODE ? "PADO" : "PADS"),      skb->dev->name);
                                } else { /*  not add relay tag */
                                        if (!priv->pppoe_connection_in_progress) {
-                                               DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
+                                               DEBUG_ERR("Discard PPPoE packet due to no connection in progress!\n");
                                                return -1;
                                        }
                                        memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
index 1812ba9659b8d0f9b1f3648adf9017211dec3627..78a7adf6160927e3f7ebe811dbbb3f6e479a23f4 100644 (file)
@@ -233,7 +233,7 @@ int proc_get_rf_info(char *page, char **start,
        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
        int len = 0;
 
-       len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n",
+       len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offset=%d\n",
                                        pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
        *eof = 1;
        return len;
index 807b7d4befffe7105aa3ae290fe0d7cbf1f228b0..2a54e3369f649bf1f5e74c6c5e0f44030a5a6c1e 100644 (file)
@@ -401,7 +401,7 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
 
                if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-                               rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not */
+                               rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether  issue dis-assoc_cmd or not */
               }
 
                *pold_state = networktype;
@@ -563,7 +563,7 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
                break;
        }
        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                ("rtw_set_802_11_add_wep:befor memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
+                ("rtw_set_802_11_add_wep:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
                 wep->KeyLength, wep->KeyIndex, keyid));
 
        memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
index c197b228071d9b51fa259dfbbac7ec95cd02e980..4942759b19c8130379eb6d2811ebc7bd0038e344 100644 (file)
@@ -171,7 +171,7 @@ static struct rt_channel_plan_map   RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
        {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
 };
 
-static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
+static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the combination for max channel numbers */
 
 /*
  * Search the @param channel_num in given @param channel_set
@@ -1942,7 +1942,7 @@ void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 
        /*      Commented by Albert 20110306 */
-       /*      According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
+       /*      According to the P2P Specification, the group negotiation request frame should contain 9 P2P attributes */
        /*      1. P2P Capability */
        /*      2. Group Owner Intent */
        /*      3. Configuration Timeout */
@@ -2307,7 +2307,7 @@ static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame
        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 
        /*      Commented by Albert 20100908 */
-       /*      According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
+       /*      According to the P2P Specification, the group negotiation response frame should contain 9 P2P attributes */
        /*      1. Status */
        /*      2. P2P Capability */
        /*      3. Group Owner Intent */
@@ -2609,7 +2609,7 @@ static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 
        /*      Commented by Albert 20110306 */
-       /*      According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
+       /*      According to the P2P Specification, the group negotiation request frame should contain 5 P2P attributes */
        /*      1. Status */
        /*      2. P2P Capability */
        /*      3. Operating Channel */
@@ -4347,7 +4347,7 @@ struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
 
 /****************************************************************************
 
-Following are some TX fuctions for WiFi MLME
+Following are some TX functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -5001,7 +5001,7 @@ exit:
        return ret;
 }
 
-/*  if psta == NULL, indiate we are station(client) now... */
+/*  if psta == NULL, indicate we are station(client) now... */
 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
 {
        struct xmit_frame *pmgntframe;
@@ -5612,7 +5612,7 @@ exit:
        return;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
 {
        int ret = _FAIL;
@@ -5682,7 +5682,7 @@ exit:
 }
 
 
-/* when wait_ms > 0 , this function shoule be called at process context */
+/* when wait_ms > 0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
 {
@@ -5692,7 +5692,7 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow
        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 
-       /* da == NULL, assum it's null data for sta to ap*/
+       /* da == NULL, assume it's null data for sta to ap*/
        if (da == NULL)
                da = get_my_bssid(&(pmlmeinfo->network));
 
@@ -5727,7 +5727,7 @@ exit:
        return ret;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
 {
        int ret = _FAIL;
@@ -5805,7 +5805,7 @@ exit:
        return ret;
 }
 
-/* when wait_ms > 0 , this function shoule be called at process context */
+/* when wait_ms > 0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
 {
@@ -5815,7 +5815,7 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int
        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 
-       /* da == NULL, assum it's null data for sta to ap*/
+       /* da == NULL, assume it's null data for sta to ap*/
        if (da == NULL)
                da = get_my_bssid(&(pmlmeinfo->network));
 
@@ -6361,7 +6361,7 @@ unsigned int send_beacon(struct adapter *padapter)
 
 /****************************************************************************
 
-Following are some utitity fuctions for WiFi MLME
+Following are some utility functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -6474,7 +6474,7 @@ void site_survey(struct adapter *padapter)
                {
                        /*  20100721:Interrupt scan operation here. */
                        /*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
-                       /*  It compares the scan result and select beter one to do connection. */
+                       /*  It compares the scan result and select better one to do connection. */
                        if (rtw_hal_antdiv_before_linked(padapter)) {
                                pmlmeext->sitesurvey_res.bss_cnt = 0;
                                pmlmeext->sitesurvey_res.channel_idx = -1;
@@ -6713,7 +6713,7 @@ void start_create_ibss(struct adapter *padapter)
        /* update wireless mode */
        update_wireless_mode(padapter);
 
-       /* udpate capability */
+       /* update capability */
        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
        update_capinfo(padapter, caps);
        if (caps&cap_IBSS) {/* adhoc master */
@@ -6765,7 +6765,7 @@ void start_clnt_join(struct adapter *padapter)
        /* update wireless mode */
        update_wireless_mode(padapter);
 
-       /* udpate capability */
+       /* update capability */
        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
        update_capinfo(padapter, caps);
        if (caps&cap_ESS) {
@@ -7378,7 +7378,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
        /* turn on dynamic functions */
        Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
 
-       /*  update IOT-releated issue */
+       /*  update IOT-related issue */
        update_IOT_info(padapter);
 
        rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
@@ -7386,7 +7386,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
        /* BCN interval */
        rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
 
-       /* udpate capability */
+       /* update capability */
        update_capinfo(padapter, pmlmeinfo->capability);
 
        /* WMM, Update EDCA param */
index 99c06c45a1c0f762fa81665115d840cdfbbc6ca4..2e02b2063c20ced683b7dc2f5d1c91d9c1fcb06e 100644 (file)
@@ -407,7 +407,7 @@ s32 mp_start_test(struct adapter *padapter)
                goto end_of_mp_start_test;
        }
 
-       /* 3 3. join psudo AdHoc */
+       /* 3 3. join pseudo AdHoc */
        tgt_network->join_res = 1;
        tgt_network->aid = 1;
        psta->aid = 1;
@@ -443,7 +443,7 @@ void mp_stop_test(struct adapter *padapter)
                if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
                        goto end_of_mp_stop_test;
 
-               /* 3 1. disconnect psudo AdHoc */
+               /* 3 1. disconnect pseudo AdHoc */
                rtw_indicate_disconnect(padapter);
 
                /* 3 2. clear psta used in mp test mode. */
index 491d6af2e24d2ed43906964d99e05251883d155b..f6583734aefa37709e0b56144f6575b26a5765ab 100644 (file)
@@ -515,7 +515,7 @@ inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
 /*
 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
 * @adapter: pointer to struct adapter structure
-* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
+* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
 * Return _SUCCESS or _FAIL
 */
 
index 0c8b338dc6d3dbc0cb2e30d89aceba433079e7af..636ec553ae83680cc4daea367bca0b13d5fbc506 100644 (file)
@@ -1123,7 +1123,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
                                if (psta->sleepq_len == 0) {
                                        pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-                                       /* upate BCN for TIM IE */
+                                       /* update BCN for TIM IE */
                                        /* update_BCNTIM(padapter); */
                                        update_beacon(padapter, _TIM_IE_, NULL, false);
                                }
@@ -1141,7 +1141,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
 
                                        pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-                                       /* upate BCN for TIM IE */
+                                       /* update BCN for TIM IE */
                                        /* update_BCNTIM(padapter); */
                                        update_beacon(padapter, _TIM_IE_, NULL, false);
                                }
@@ -2236,13 +2236,13 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS)
        } else {
                if (recvpriv->signal_strength_data.update_req == 0) {/*  update_req is clear, means we got rx */
                        avg_signal_strength = recvpriv->signal_strength_data.avg_val;
-                       /*  after avg_vals are accquired, we can re-stat the signal values */
+                       /*  after avg_vals are acquired, we can re-stat the signal values */
                        recvpriv->signal_strength_data.update_req = 1;
                }
 
                if (recvpriv->signal_qual_data.update_req == 0) {/*  update_req is clear, means we got rx */
                        avg_signal_qual = recvpriv->signal_qual_data.avg_val;
-                       /*  after avg_vals are accquired, we can re-stat the signal values */
+                       /*  after avg_vals are acquired, we can re-stat the signal values */
                        recvpriv->signal_qual_data.update_req = 1;
                }
 
index f64b9795a712f6fd7103a7bfe7020bdb2fd6e7f9..3dd90599fd4be2b54e98cf824dbfc5959ccd171e 100644 (file)
@@ -1050,7 +1050,7 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
        }
 
        if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
-               DBG_88E("%s(): enctyp is not match , return FAIL\n", __func__);
+               DBG_88E("%s(): encryption protocol is not match , return FAIL\n", __func__);
                goto _mismatch;
        }
 
index b0e9798da75a1c107695fa0e40176466e4cca263..8d4265fb486dcb2f7db71ab2be8233baea97db39 100644 (file)
@@ -1950,7 +1950,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
                        pstapriv->tim_bitmap |= BIT(0);/*  */
                        pstapriv->sta_dz_bitmap |= BIT(0);
 
-                       update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
+                       update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after update bcn */
 
                        ret = true;
                }
@@ -2000,7 +2000,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
                                pstapriv->tim_bitmap |= BIT(psta->aid);
 
                                if (psta->sleepq_len == 1) {
-                                       /* upate BCN for TIM IE */
+                                       /* update BCN for TIM IE */
                                        update_beacon(padapter, _TIM_IE_, NULL, false);
                                }
                        }
@@ -2269,7 +2269,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
                if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {
                        pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-                       /* upate BCN for TIM IE */
+                       /* update BCN for TIM IE */
                        update_beacon(padapter, _TIM_IE_, NULL, false);
                }
        }
index f123a930c012c790b1b652b05ae536249d225e0a..b225d1c072109503e89b595fcf1fd3756651851f 100644 (file)
@@ -651,7 +651,7 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb)
 }
 
 static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
-                           void *accel_priv)
+                           void *accel_priv, select_queue_fallback_t fallback)
 {
        struct adapter  *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
index 6f3a609e86e6a62f305489bca4708bc61d9960e7..2e49cd583212a70dc3bf8bf1ed22eb5d12d0e068 100644 (file)
@@ -56,6 +56,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
        /****** 8188EUS ********/
        {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
+       {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
        {}      /* Terminating entry */
 };
 
index 356aec437963142546e89d48e79db5bb93ba346b..4b94653c50d9c5b3cd989bf78af12b8e10851b38 100644 (file)
 #include <linux/types.h>
 #include <linux/pci.h>
 
-static inline void NdisRawWritePortUlong(u32 port,  u32 val)
-{
-       outl(val, port);
-}
-
-static inline void NdisRawWritePortUchar(u32 port,  u8 val)
-{
-       outb(val, port);
-}
-
-static inline void NdisRawReadPortUchar(u32 port, u8 *pval)
-{
-       *pval = inb(port);
-}
-
-static inline void NdisRawReadPortUshort(u32 port, u16 *pval)
-{
-       *pval = inw(port);
-}
-
-static inline void NdisRawReadPortUlong(u32 port, u32 *pval)
-{
-       *pval = inl(port);
-}
-
 struct mp_adapter {
        u8              LinkCtrlReg;
 
@@ -70,33 +45,6 @@ struct mp_adapter {
        u8              PciBridgeLinkCtrlReg;
 };
 
-struct rt_pci_capab_header {
-       unsigned char   CapabilityID;
-       unsigned char   Next;
-};
-
-#define PCI_MAX_BRIDGE_NUMBER                          255
-#define PCI_MAX_DEVICES                                                32
-#define PCI_MAX_FUNCTION                                       8
-
-#define PCI_CONF_ADDRESS                                       0x0CF8
-#define PCI_CONF_DATA                                          0x0CFC
-
-#define        PCI_CLASS_BRIDGE_DEV                            0x06
-#define        PCI_SUBCLASS_BR_PCI_TO_PCI              0x04
-
-#define        U1DONTCARE                                              0xFF
-#define        U2DONTCARE                                              0xFFFF
-#define        U4DONTCARE                                              0xFFFFFFFF
-
-#define        INTEL_VENDOR_ID                                 0x8086
-#define        SIS_VENDOR_ID                                           0x1039
-#define        ATI_VENDOR_ID                                           0x1002
-#define        ATI_DEVICE_ID                                           0x7914
-#define        AMD_VENDOR_ID                                           0x1022
-
-#define PCI_CAPABILITY_ID_PCI_EXPRESS          0x10
-
 struct net_device;
 bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev);
 
index 6202358c2984fc0c5e1597783790df60b97835bd..498995d833e7287013fb9a8a13c49376248ab4b8 100644 (file)
@@ -609,7 +609,7 @@ static int r8192_wx_set_nick(struct net_device *dev,
        if (wrqu->data.length > IW_ESSID_MAX_SIZE)
                return -E2BIG;
        down(&priv->wx_sem);
-       wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
+       wrqu->data.length = min_t(size_t, wrqu->data.length, sizeof(priv->nick));
        memset(priv->nick, 0, sizeof(priv->nick));
        memcpy(priv->nick, extra, wrqu->data.length);
        up(&priv->wx_sem);
index da04f034e114167de790dd83ec546c4e04d725ae..fce9c3fb21703ebaf6dc3987331dce343e3203ca 100644 (file)
 #include "pci.h"
 
 /*
- *NOTICE!!!: This file will be very big, we hsould
- *keep it clear under follwing roles:
+ *NOTICE!!!: This file will be very big, we should
+ *keep it clear under following roles:
  *
- *This file include follwing part, so, if you add new
+ *This file include following part, so, if you add new
  *functions into this file, please check which part it
  *should includes. or check if you should add new part
  *for this file:
@@ -662,7 +662,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 
        if (rtlpriv->dm.b_useramask) {
                tcb_desc->ratr_index = ratr_index;
-               /* TODO we will differentiate adhoc and station futrue  */
+               /* TODO we will differentiate adhoc and station future  */
                if (mac->opmode == NL80211_IFTYPE_STATION ||
                        mac->opmode == NL80211_IFTYPE_MESH_POINT) {
                        tcb_desc->mac_id = 0;
@@ -772,10 +772,10 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
                        tcb_desc->disable_ratefallback = 1;
                } else {
                        /*
-                        *because hw will nerver use hw_rate
+                        *because hw will never use hw_rate
                         *when tcb_desc->use_driver_rate = false
                         *so we never set highest N rate here,
-                        *and N rate will all be controled by FW
+                        *and N rate will all be controlled by FW
                         *when tcb_desc->use_driver_rate = false
                         */
                        if (sta && (sta->ht_cap.ht_supported)) {
@@ -1671,7 +1671,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len)
                (memcmp(mac->bssid, ap4_2, 3) == 0) ||
                (memcmp(mac->bssid, ap4_3, 3) == 0) ||
                vendor == PEER_RAL) {
-               RT_TRACE(COMP_MAC80211, DBG_LOUD, ("=>ral findn\n"));
+               RT_TRACE(COMP_MAC80211, DBG_LOUD, ("=>ral find\n"));
                vendor = PEER_RAL;
        } else if (memcmp(mac->bssid, ap6_1, 3) == 0 ||
                vendor == PEER_CISCO) {
index b30f17ae0215348b088a34d30689b465a354900d..5a54bb10698ca3d3c271bd9140c879f5335b8d7a 100644 (file)
@@ -1653,7 +1653,7 @@ halbtc8812a1ant_TdmaDurationAdjustForAcl(
        }
        else
        {
-               //accquire the BT TRx retry count from BT_Info byte2
+               //acquire the BT TRx retry count from BT_Info byte2
                retry_count = coex_sta->bt_retry_cnt;
                bt_info_ext = coex_sta->bt_info_ext;
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retry_count = %d\n", retry_count));
index e619923ef0ab6bcb3a3f0ab4834f966ef363a3a6..8e4293a35872b824a7d8d1eec877fcfe8408d750 100644 (file)
@@ -629,7 +629,7 @@ halbtc8723a1ant_TdmaDurationAdjust(
        }
        else
        {
-               //accquire the BT TRx retry count from BT_Info byte2
+               //acquire the BT TRx retry count from BT_Info byte2
                retryCount = pCoexSta->btRetryCnt;
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], retryCount = %d\n", retryCount));
                result = 0;
index 973d0ea82cb8051886def4b4434de1ad6ffa6164..1b04530d46bc6a0b0178382bdafbaaf8a84ce872 100644 (file)
@@ -1721,7 +1721,7 @@ halbtc8192e1ant_TdmaDurationAdjustForAcl(
        }
        else
        {
-               //accquire the BT TRx retry count from BT_Info byte2
+               //acquire the BT TRx retry count from BT_Info byte2
                retryCount = pCoexSta->btRetryCnt;
                btInfoExt = pCoexSta->btInfoExt;
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
index 44ec78562e2da1e9ce2d10bdf6f4fb9124a0d268..115908928ae4293c5cfd36bc5fbb7ac71accd2a7 100644 (file)
@@ -1803,7 +1803,7 @@ void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist,
                result = 0;
                wait_cnt = 0;
        } else {
-               /* accquire the BT TRx retry count from BT_Info byte2 */
+               /* acquire the BT TRx retry count from BT_Info byte2 */
                retry_cnt = coex_sta->bt_retry_cnt;
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
                          "[BTCoex], retry_cnt = %d\n", retry_cnt);
index 180d6f12e7b5d03d761635395e5f22aa10d0805d..3f5c4fd2e73fa82dfc3b7ce6fff7fab1203fe41b 100644 (file)
@@ -1687,7 +1687,7 @@ halbtc8723a2ant_TdmaDurationAdjust(
        }
        else
        {
-               //accquire the BT TRx retry count from BT_Info byte2
+               //acquire the BT TRx retry count from BT_Info byte2
                retryCount = pCoexSta->btRetryCnt;
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], up=%d, dn=%d, m=%d, n=%d, WaitCount=%d\n", 
index 3414ba78cc43e3340472ca88b54e5fb3f0fdd35d..9677943fc20dfd4ec10d742376ad053c84f790b7 100644 (file)
@@ -1950,7 +1950,7 @@ void halbtc8723b1ant_tdma_duration_adjust_for_acl(struct btc_coexist *btcoexist,
                result = 0;
                wait_count = 0;
        } else {
-               /*accquire the BT TRx retry count from BT_Info byte2 */
+               /*acquire the BT TRx retry count from BT_Info byte2 */
                retry_count = coex_sta->bt_retry_cnt;
                bt_info_ext = coex_sta->bt_info_ext;
                result = 0;
index 83b1b42183336b35ee1c6f720319905d9623cb5e..d337bd0b3c1bc350773fc0c856e1ea3b63450103 100644 (file)
@@ -1830,7 +1830,7 @@ void halbtc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist,
                result = 0;
                wait_count = 0;
        } else {
-               /*accquire the BT TRx retry count from BT_Info byte2*/
+               /*acquire the BT TRx retry count from BT_Info byte2*/
                retryCount = coex_sta->bt_retry_cnt;
                BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
                          "[BTCoex], retryCount = %d\n", retryCount);
index 40de6089039e2c717f1015c68cceb73f1900be9d..ff3139b6da656f2f985b2c1498fa16508c2030b2 100644 (file)
@@ -373,7 +373,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
                        /* sleep here is must, or we may recv the beacon and
                         * cause mac80211 into wrong ps state, this will cause
                         * power save nullfunc send fail, and further cause
-                        * pkt loss, So sleep must quickly but not immediatly
+                        * pkt loss, So sleep must quickly but not immediately
                         * because that will cause nullfunc send by mac80211
                         * fail, and cause pkt loss, we have tested that 5mA
                         * is worked very well */
@@ -1200,8 +1200,8 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                key_type = AESCMAC_ENCRYPTION;
                RT_TRACE(COMP_SEC, DBG_DMESG, ("alg:CMAC\n"));
                RT_TRACE(COMP_SEC, DBG_DMESG,
-                               ("HW don't support CMAC encrypiton, "
-                               "use software CMAC encrypiton\n"));
+                               ("HW don't support CMAC encryption, "
+                               "use software CMAC encryption\n"));
                err = -EOPNOTSUPP;
                goto out_unlock;
        default:
@@ -1235,8 +1235,8 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                key_type = AESCMAC_ENCRYPTION;
                RT_TRACE(COMP_SEC, DBG_DMESG, ("alg:CMAC\n"));
                RT_TRACE(COMP_SEC, DBG_DMESG,
-                        ("HW don't support CMAC encrypiton, "
-                         "use software CMAC encrypiton\n"));
+                        ("HW don't support CMAC encryption, "
+                         "use software CMAC encryption\n"));
                err = -EOPNOTSUPP;
                goto out_unlock;
        default:
@@ -1411,7 +1411,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
 }
 
 /* this function is called by mac80211 to flush tx buffer
- * before switch channle or power save, or tx buffer packet
+ * before switch channel or power save, or tx buffer packet
  * maybe send after offchannel or rf sleep, this may cause
  * dis-association by AP */
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
index 4b247db2861d67ea023f02653b48625b2a48a864..f0c74e9239fddf3672b9e36acf56398d5794fcaa 100644 (file)
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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 as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
index cb051223c68420e896ee314e62918718886f197e..8a6c794bda41c502c7f59928bb35156fc17e646d 100644 (file)
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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 as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -985,4 +985,4 @@ void rtl_proc_remove_topdir(void)
 {
        if (proc_topdir)
                remove_proc_entry("rtlwifi", init_net.proc_net);
-}
\ No newline at end of file
+}
index 5eb6251b89da782851a88ecbbf871a14c61d7d99..6c0a553e98b71e723257390b7ad63bb18684dfcd 100644 (file)
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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 as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -44,7 +44,7 @@
 #define DBG_EMERG                      0
 
 /*
- *Abnormal, rare, or unexpeted cases.
+ *Abnormal, rare, or unexpected cases.
  *For example, Packet/IO Ctl canceled,
  *device suprisely unremoved and so on.
  */
@@ -54,7 +54,7 @@
  *Normal case driver developer should
  *open, we can see link status like
  *assoc/AddBA/DHCP/adapter start and
- *so on basic and useful infromations.
+ *so on basic and useful informations.
  */
 #define DBG_DMESG                      3
 
index 74c19ecc95a9e510dff8a904f91438cac4a86fed..250aae1ce6314a405ecb3217d5757deab2465fae 100644 (file)
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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 as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -149,7 +149,7 @@ u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address)
                return 0xFF;
 
 }
-//EXPORT_SYMBOL(efuse_read_1byte);
+/* EXPORT_SYMBOL(efuse_read_1byte); */
 
 void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
 {
@@ -517,7 +517,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
                        rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
 }
-//EXPORT_SYMBOL(rtl_efuse_shadow_map_update);
+/* EXPORT_SYMBOL(rtl_efuse_shadow_map_update); */
 
 void efuse_force_write_vendor_Id(struct ieee80211_hw *hw)
 {
@@ -628,7 +628,7 @@ int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data)
        }
        return bresult;
 }
-//EXPORT_SYMBOL(efuse_one_byte_read);
+/* EXPORT_SYMBOL(efuse_one_byte_read); */
 
 static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data)
 {
@@ -1120,16 +1120,16 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
                {
                        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69);
 
-                       // 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid
+                       /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */
                        tmpV16 = rtl_read_word(rtlpriv,
                                               rtlpriv->cfg->maps[SYS_ISO_CTRL]);
 
                        printk("SYS_ISO_CTRL=%04x.\n",tmpV16);
                        if( ! (tmpV16 & PWC_EV12V ) ){
                                tmpV16 |= PWC_EV12V ;
-                                //PlatformEFIOWrite2Byte(pAdapter,REG_SYS_ISO_CTRL,tmpV16);
+                                /* PlatformEFIOWrite2Byte(pAdapter,REG_SYS_ISO_CTRL,tmpV16); */
                        }
-                       // Reset: 0x0000h[28], default valid
+                       /* Reset: 0x0000h[28], default valid */
                        tmpV16 = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[SYS_FUNC_EN]);
                        printk("SYS_FUNC_EN=%04x.\n",tmpV16);
                        if( !(tmpV16 & FEN_ELDR) ){
@@ -1137,7 +1137,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
                                rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16);
                        }
 
-                       // Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid
+                       /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
                        tmpV16 = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[SYS_CLK] );
                        printk("SYS_CLK=%04x.\n",tmpV16);
                        if( (!(tmpV16 & LOADER_CLK_EN) )  ||(!(tmpV16 & ANA8M) ) )
@@ -1148,7 +1148,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
 
                        if(bwrite == true)
                        {
-                               // Enable LDO 2.5V before read/write action
+                               /* Enable LDO 2.5V before read/write action */
                                tempval = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3);
                                printk("EFUSE_TEST=%04x.\n",tmpV16);
                                tempval &= ~(BIT(3) | BIT(4) |BIT(5) | BIT(6));
@@ -1161,7 +1161,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
                {
                        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x00);
                        if(bwrite == true){
-                               // Disable LDO 2.5V after read/write action
+                               /* Disable LDO 2.5V after read/write action */
                                tempval = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3);
                                rtl_write_byte(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3, (tempval & 0x7F));
                        }
index 618a3cb4a0c04124c5c373d5b6fafad5333c7a24..a562aa60d5955bf3a2d15c4383379e85e5fff1d9 100644 (file)
@@ -583,7 +583,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
                (rtlpriv->buddy_priv &&
                 rtlpriv->buddy_priv->easy_concurrent_ctl.bswitch_in_process)))
                return;
-       /* we juse use em for BE/BK/VI/VO */
+       /* we just use em for BE/BK/VI/VO */
        for (tid = 7; tid >= 0; tid--) {
                u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)];
                struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
@@ -672,7 +672,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
                }
 
                /* for sw LPS, just after NULL skb send out, we can
-                * sure AP kown we are sleeped, our we should not let
+                * sure AP known we are slept, our we should not let
                 * rf to sleep*/
                fc = rtl_get_fc(skb);
                if (ieee80211_is_nullfunc(fc)) {
@@ -772,7 +772,7 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
        return 1;
 }
 
-/* inorder to receive 8K AMSDU we have set skb to
+/* In order to receive 8K AMSDU we have set skb to
  * 9100bytes in init rx ring, but if this packet is
  * not a AMSDU, this so big packet will be sent to
  * TCP/IP directly, this cause big packet ping fail
@@ -783,7 +783,7 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
 /* but some platform will fail when alloc skb sometimes.
  * in this condition, we will send the old skb to
  * mac80211 directly, this will not cause any other
- * issues, but only be losted by TCP/IP */
+ * issues, but only be lost by TCP/IP */
 static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
        struct sk_buff *skb, struct ieee80211_rx_status rx_status)
 {
@@ -1029,7 +1029,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
        rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
 
 
-       /*Shared IRQ or HW disappared */
+       /*Shared IRQ or HW disappeared */
        if (!inta || inta == 0xffff)
                goto done;
        /*<1> beacon related */
@@ -1936,7 +1936,7 @@ void rtl_pci_stop(struct ieee80211_hw *hw)
        u8 RFInProgressTimeOut = 0;
 
        /*
-        *should before disable interrrupt&adapter
+        *should before disable interrupt&adapter
         *and will do it immediately.
         */
        set_hal_stop(rtlhal);
@@ -2293,7 +2293,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
        /*
         *init dbgp flags before all
         *other functions, because we will
-        *use it in other funtions like
+        *use it in other functions like
         *RT_TRACE/RT_PRINT/RTL_PRINT_DATA
         *you can not use these macro
         *before this
@@ -2428,13 +2428,13 @@ fail1:
        return -ENODEV;
 
 }
-//EXPORT_SYMBOL(rtl_pci_probe);
+/* EXPORT_SYMBOL(rtl_pci_probe); */
 
 struct ieee80211_hw *rtl_pci_get_hw_pointer(void)
 {
        return hw_export;
 }
-//EXPORT_SYMBOL(rtl_pci_get_hw_pointer);
+/* EXPORT_SYMBOL(rtl_pci_get_hw_pointer); */
 
 void rtl_pci_disconnect(struct pci_dev *pdev)
 {
@@ -2491,7 +2491,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 
        ieee80211_free_hw(hw);
 }
-//EXPORT_SYMBOL(rtl_pci_disconnect);
+/* EXPORT_SYMBOL(rtl_pci_disconnect); */
 
 /***************************************
 kernel pci power state define:
@@ -2519,7 +2519,7 @@ int rtl_pci_suspend(struct device *dev)
 
        return 0;
 }
-//EXPORT_SYMBOL(rtl_pci_suspend);
+/* EXPORT_SYMBOL(rtl_pci_suspend); */
 
 int rtl_pci_resume(struct device *dev)
 {
@@ -2532,7 +2532,7 @@ int rtl_pci_resume(struct device *dev)
 
        return 0;
 }
-//EXPORT_SYMBOL(rtl_pci_resume);
+/* EXPORT_SYMBOL(rtl_pci_resume); */
 
 struct rtl_intf_ops rtl_pci_ops = {
        .read_efuse_byte = read_efuse_byte,
index 9f206550a657ca5488be0d067e2bfff4ceb7bc81..06eaa521e0ebbef6cc9a2512af729a06a9a43a1e 100644 (file)
@@ -148,11 +148,11 @@ struct rtl_pci_capabilities_header {
   * RX wifi info == RX descriptor in old flow */
 struct rtl_tx_buffer_desc {
 #if (RTL8192EE_SEG_NUM == 2)
-       u32 dword[2*(DMA_IS_64BIT + 1)*8]; //seg = 8
+       u32 dword[2*(DMA_IS_64BIT + 1)*8]; /* seg = 8 */
 #elif (RTL8192EE_SEG_NUM == 1)
-       u32 dword[2*(DMA_IS_64BIT + 1)*4]; //seg = 4
+       u32 dword[2*(DMA_IS_64BIT + 1)*4]; /* seg = 4 */
 #elif (RTL8192EE_SEG_NUM == 0)
-       u32 dword[2*(DMA_IS_64BIT + 1)*2]; //seg = 2
+       u32 dword[2*(DMA_IS_64BIT + 1)*2]; /* seg = 2 */
 #endif
 } __packed;
 
@@ -187,7 +187,7 @@ struct rtl8192_tx_ring {
 };
 
 struct rtl8192_rx_ring {
-       struct rtl_rx_desc *desc;/*for old trx flow, not uesd in new trx*/
+       struct rtl_rx_desc *desc;/*for old trx flow, not used in new trx*/
        /*dma matches either 'desc' or 'buffer_desc'*/
        dma_addr_t dma;
        unsigned int idx;
index f12ffa83c58d60b51632d5496ee7c0a617fe6b09..7876442417f4b87136a9439d566f74089e319403 100644 (file)
@@ -257,7 +257,7 @@ void rtl_ips_nic_off_wq_callback(void *data)
                 *Do not enter IPS in the following conditions:
                 *(1) RF is already OFF or Sleep
                 *(2) b_swrf_processing (indicates the IPS is still under going)
-                *(3) Connectted (only disconnected can trigger IPS)
+                *(3) Connected (only disconnected can trigger IPS)
                 *(4) IBSS (send Beacon)
                 *(5) AP mode (send Beacon)
                 *(6) monitor mode (rcv packet)
index d89f15cb808971dd3d5c73005c5c241ef9cc9374..0a4b3984b7ef280fcd156feb25f651cf7237a12c 100644 (file)
@@ -243,7 +243,7 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
        }
 
        /*
-        *If a country IE has been recieved check its rule for this
+        *If a country IE has been received check its rule for this
         *channel first before enabling active scan. The passive scan
         *would have been enforced by the initial processing of our
         *custom regulatory domain.
@@ -455,7 +455,7 @@ int rtl_regd_init(struct ieee80211_hw *hw,
 
        if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
                RT_TRACE(COMP_REGD, DBG_DMESG,
-                        (KERN_DEBUG "rtl: EEPROM indicates invalid contry code"
+                        (KERN_DEBUG "rtl: EEPROM indicates invalid country code"
                          "world wide 13 should be used\n"));
 
                rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
index 8634206b892986b39bb406de189997414a7a5c0e..e0efcd281dfe59bc148633ad1db7df34eacaa26f 100644 (file)
@@ -731,7 +731,7 @@ void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
                rtl_dm_dig->min_undecorated_pwdb_for_dm =
                    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
                RT_TRACE(COMP_BB_POWERSAVING, DBG_LOUD,
-                        ("AP Ext Port or disconnet PWDB = 0x%x \n",
+                        ("AP Ext Port or disconnect PWDB = 0x%x \n",
                          rtl_dm_dig->min_undecorated_pwdb_for_dm));
        }
        RT_TRACE(COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n",
@@ -925,7 +925,7 @@ static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
 
        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
                RT_TRACE(COMP_DIG, DBG_LOUD,
-                       ("rtl8821ae_dm_dig(): Abnornally false alarm case. \n"));
+                       ("rtl8821ae_dm_dig(): Abnormally false alarm case. \n"));
 
                if (dm_digtable.large_fa_hit != 3)
                        dm_digtable.large_fa_hit++;
@@ -1087,7 +1087,7 @@ static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
        else
                falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
 
-       /*reset OFDM FA coutner*/
+       /*reset OFDM FA counter*/
        rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
        rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
        /* reset CCK FA counter*/
@@ -1316,7 +1316,7 @@ u8 rtl8812ae_hw_rate_to_mrate(
 /*-----------------------------------------------------------------------------
  * Function:   odm_TxPwrTrackSetPwr88E()
  *
- * Overview:   88E change all channel tx power accordign to flag.
+ * Overview:   88E change all channel tx power according to flag.
  *                             OFDM & CCK are all different.
  *
  * Input:              NONE
@@ -1537,7 +1537,7 @@ void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
                                        rtldm->modify_txagc_flag_path_b = false;
 
                                        RT_TRACE(COMP_POWER_TRACKING, DBG_LOUD,
-                                               ("******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE \n"));
+                                               ("******Path_B dm_Odm->Modify_TxAGC_Flag = FALSE \n"));
                                }
                        }
                }
@@ -1654,7 +1654,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter
 
        if (delta > 0 && rtldm->txpower_track_control)
        {
-               /*"delta" here is used to record the absolute value of differrence.*/
+               /*"delta" here is used to record the absolute value of difference.*/
                delta = thermal_value > rtlefuse->eeprom_thermalmeter ? \
                        (thermal_value - rtlefuse->eeprom_thermalmeter) : \
                        (rtlefuse->eeprom_thermalmeter - thermal_value);
@@ -1976,7 +1976,7 @@ void rtl8821ae_phy_lccalibrate(
 /*-----------------------------------------------------------------------------
  * Function:   odm_TxPwrTrackSetPwr88E()
  *
- * Overview:   88E change all channel tx power accordign to flag.
+ * Overview:   88E change all channel tx power according to flag.
  *                             OFDM & CCK are all different.
  *
  * Input:              NONE
@@ -2159,7 +2159,7 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter
        u8 *delta_swing_table_idx_tup_b;
        u8 *delta_swing_table_idx_tdown_b;
 
-       /*2. Initilization ( 7 steps in total )*/
+       /*2. Initialization ( 7 steps in total )*/
        rtl8821ae_get_delta_swing_table(hw, (u8**)&delta_swing_table_idx_tup_a,
                                                                        (u8**)&delta_swing_table_idx_tdown_a,
                                                                          (u8**)&delta_swing_table_idx_tup_b,
@@ -2244,7 +2244,7 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter
 
        if (delta > 0 && rtldm->txpower_track_control)
        {
-               /*"delta" here is used to record the absolute value of differrence.*/
+               /*"delta" here is used to record the absolute value of difference.*/
                delta = thermal_value > rtlefuse->eeprom_thermalmeter ? \
                        (thermal_value - rtlefuse->eeprom_thermalmeter) : \
                        (rtlefuse->eeprom_thermalmeter - thermal_value);
@@ -2613,11 +2613,11 @@ static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
        RT_TRACE(COMP_TURBO, DBG_LOUD,
                ("rtl8821ae_dm_check_edca_turbo=====>"));
        RT_TRACE(COMP_TURBO, DBG_LOUD,
-               ("Orginial BE PARAM: 0x%x\n",
+               ("Original BE PARAM: 0x%x\n",
                rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N)));
 
        /*===============================
-       list paramter for different platform
+       list parameter for different platform
        ===============================*/
        b_last_is_cur_rdl_state = rtlpriv->dm.bis_cur_rdlstate;
        pb_is_cur_rdl_state = &( rtlpriv->dm.bis_cur_rdlstate);
@@ -2963,7 +2963,7 @@ void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
                        "Crystal cap = 0x%x, Crystal cap offset = %d\n",
                        rtldm->crystal_cap, adjust_xtal));
 
-               /*3.Adjudt Crystal Cap.*/
+               /*3.Adjust Crystal Cap.*/
                if (adjust_xtal != 0){
                        rtldm->is_freeze = 0;
                        rtldm->crystal_cap += adjust_xtal;
index 4083cab926a342210485e071ace41670ba1dec19..46eb4125d18f6a639f2666513005e91e108a2b9e 100644 (file)
@@ -164,7 +164,7 @@ static int _rtl8821ae_fw_free_to_go(struct ieee80211_hw *hw)
 
        if (counter >= FW_8821AE_POLLING_TIMEOUT_COUNT) {
                RT_TRACE(COMP_ERR, DBG_LOUD,
-                        ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+                        ("chksum report fail ! REG_MCUFWDL:0x%08x .\n",
                          value32));
                goto exit;
        }
@@ -368,7 +368,7 @@ static void _rtl8821ae_fill_h2c_command(struct ieee80211_hw *hw,
                                wait_h2c_limmit--;
                                if (wait_h2c_limmit == 0) {
                                        RT_TRACE(COMP_CMD, DBG_LOUD,
-                                                ("Wating too long for FW read "
+                                                ("Waiting too long for FW read "
                                                  "clear HMEBox(%d)!\n", boxnum));
                                        break;
                                }
@@ -378,7 +378,7 @@ static void _rtl8821ae_fill_h2c_command(struct ieee80211_hw *hw,
                                isfw_read = _rtl8821ae_check_fw_read_last_h2c(hw, boxnum);
                                u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
                                RT_TRACE(COMP_CMD, DBG_LOUD,
-                                        ("Wating for FW read clear HMEBox(%d)!!! "
+                                        ("Waiting for FW read clear HMEBox(%d)!!! "
                                          "0x130 = %2x\n", boxnum, u1b_tmp));
                        }
                }
@@ -1179,7 +1179,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
                         ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
 }
 
-/*Shoud check FW support p2p or not.*/
+/*Should check FW support p2p or not.*/
 void rtl8821ae_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
 {
        u8 u1_ctwindow_period[1] ={ ctwindow};
index 799cc6f95cc159a4ca2dfbff76b6a1df06d9500a..b365f82f481c98f4615b951bcbc188f2083a04c7 100644 (file)
@@ -142,7 +142,7 @@ void rtl8821ae_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw);
 long rtl8821ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw);
 void rtl8821ae_dm_bt_balance(struct ieee80211_hw *hw,
                        bool b_balance_on, u8 ms0, u8 ms1);
-void rtl8821ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 tyep);
+void rtl8821ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type);
 void rtl8821ae_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type);
 u8 rtl8821ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
                                                u8      level_num, u8   rssi_thresh, u8 rssi_thresh1);
index 79386ee142f9d272626a414f20cd4b1bd83a2504..6898868ce6e7b0d4a1c9448188300c8385af5bee 100644 (file)
@@ -157,7 +157,7 @@ bool rtl8821ae_dm_bt_is_same_coexist_state(struct ieee80211_hw *hw)
                &&(rtlpcipriv->btcoexist.previous_state_h
                == rtlpcipriv->btcoexist.current_state_h)) {
                RT_TRACE(COMP_BT_COEXIST, DBG_DMESG,
-                               ("[DM][BT], Coexist state do not chang!!\n"));
+                               ("[DM][BT], Coexist state do not change!!\n"));
                return true;
        } else {
                RT_TRACE(COMP_BT_COEXIST, DBG_DMESG,
@@ -902,7 +902,7 @@ void rtl8821ae_dm_bt_set_bt_dm(struct ieee80211_hw *hw, struct btdm_8821ae *p_bt
 
        /*
         * Note:
-        * We should add delay for making sure sw DacSwing can be set sucessfully.
+        * We should add delay for making sure sw DacSwing can be set successfully.
         * because of that rtl8821ae_dm_bt_set_fw_2_ant_hid() and rtl8821ae_dm_bt_set_fw_tdma_ctrl()
         * will overwrite the reg 0x880.
        */
index d3e9b93400bffd8c4b95ca880ca8e09f1fb0d633..1b8583b689d42990aadb0585b4e13ffb0d0dfca5 100644 (file)
@@ -1017,7 +1017,7 @@ static void _rtl8821ae_hw_configure(struct ieee80211_hw *hw)
        /* ARFB table 12 for 11ac 24G 1SS */
        rtl_write_dword(rtlpriv, REG_ARFR3, 0x00000015);
        rtl_write_dword(rtlpriv, REG_ARFR3 + 4, 0xffcff000);
-       /* 0x420[7] = 0 , enable retry AMPDU in new AMPD not singal MPDU. */
+       /* 0x420[7] = 0 , enable retry AMPDU in new AMPD not signal MPDU. */
        rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00);
        rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70);
 
@@ -1407,7 +1407,7 @@ int rtl8821ae_hw_init(struct ieee80211_hw *hw)
        rtl8821ae_phy_mac_config(hw);
        /* because last function modify RCR, so we update
         * rcr var here, or TP will unstable for receive_config
-        * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+        * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
         * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252
        rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
        rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
@@ -1563,7 +1563,7 @@ static enum version_8821ae _rtl8821ae_read_chip_version(struct ieee80211_hw *hw)
                        break;
                default:
                        RT_TRACE(COMP_INIT, DBG_LOUD,
-                               ("Chip Version ID: Unknow (0x%X).\n", version));
+                               ("Chip Version ID: Unknown (0x%X).\n", version));
                        break;
        }
 
@@ -2372,7 +2372,7 @@ static void _rtl8812ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_
        if (rtlefuse->eeprom_channelplan == 0xff)
                rtlefuse->eeprom_channelplan = 0x7F;
 
-       /* set channel paln to world wide 13 */
+       /* set channel plan to world wide 13 */
        //rtlefuse->channel_plan = (u8) rtlefuse->eeprom_channelplan;
 
        /*parse xtal*/
@@ -2535,7 +2535,7 @@ static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_
        if (rtlefuse->eeprom_channelplan == 0xff)
                rtlefuse->eeprom_channelplan = 0x7F;
 
-       /* set channel paln to world wide 13 */
+       /* set channel plan to world wide 13 */
        //rtlefuse->channel_plan = (u8) rtlefuse->eeprom_channelplan;
 
        /*parse xtal*/
index d02fca38a2b2e31b981dc4e08087a381d96b35ed..c66129087a6716a4974daf2ab84245f11d7e5223 100644 (file)
@@ -86,7 +86,7 @@ void rtl8812ae_fixspur(
                        /* 0x8AC[11:10] = 2'b10*/
 
 
-               /* <20120914, Kordan> A workarould to resolve
+               /* <20120914, Kordan> A workaround to resolve
                2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)*/
                if (band_width == HT_CHANNEL_WIDTH_20 &&
                        (channel == 13 || channel == 14)) {
@@ -107,7 +107,7 @@ void rtl8812ae_fixspur(
        }
        else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
        {
-               /* <20120914, Kordan> A workarould to resolve
+               /* <20120914, Kordan> A workaround to resolve
                2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)*/
                if (band_width == HT_CHANNEL_WIDTH_20 &&
                        (channel == 13 || channel == 14))
index a932d8c9d45d124b83dec84e2b89b58d29f311ed..a80bf739940a1846b80b0e1659ff8391d7dc055c 100644 (file)
@@ -30,7 +30,7 @@
 #ifndef __RTL8821AE_PHY_H__
 #define __RTL8821AE_PHY_H__
 
-/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+/*It must always set to 4, otherwise read efuse table sequence will be wrong.*/
 #define MAX_TX_COUNT   4
 #define        TX_1S                   0
 #define        TX_2S                   1
index 8b39c042fa93eb45eb86a1c25da150fecb45c463..480a6bb6d76b79f1df409f84c359b837b5d62ffb 100644 (file)
@@ -81,7 +81,7 @@
        {0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* 0x47[7:0] = 00 gpio mode */     \
        {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* suspend option all off */       \
        {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, BIT7},/*0x14[7] = 1 turn on ZCD */    \
-       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 trun on ZCD */    \
+       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 turn on ZCD */    \
        {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, BIT4},/*0x23[4] = 1 hpon LDO sleep mode */    \
        {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x02, 0},/*0x8[1] = 0 ANA clk =500k */      \
        {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3, BIT3}, /*0x04[11] = 2b'11 enable WL suspend for PCIe*/
@@ -91,7 +91,7 @@
        /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/                                                         \
        {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3, 0}, /*0x04[11] = 2b'01enable WL suspend*/   \
        {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, 0},/*0x23[4] = 0 hpon LDO sleep mode leave */ \
-       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 trun off ZCD */      \
+       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 turn off ZCD */      \
        {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, 0},/*0x14[7] = 0 turn off ZCD */      \
        {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio0~7 input mode */        \
        {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio11 input mode, gpio10~8 input mode */
        {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0xff},/* gpio0~7 output mode */       \
        {0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* 0x47[7:0] = 00 gpio mode */     \
        {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, BIT7},/*0x14[7] = 1 turn on ZCD */    \
-       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 trun on ZCD */    \
+       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 turn on ZCD */    \
        {0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/*0x12[0] = 0 force PFM mode */    \
        {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, BIT4},/*0x23[4] = 1 hpon LDO sleep mode */    \
        {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x02, 0},/*0x8[1] = 0 ANA clk =500k */      \
        /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/                       \
        {0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0, BIT0},/*0x12[0] = 1 force PWM mode */ \
        {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, 0},/*0x14[7] = 0 turn off ZCD */      \
-       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 trun off ZCD */      \
+       {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 turn off ZCD */      \
        {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, 0},/*0x23[4] = 0 hpon LDO leave sleep mode */ \
        {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio0~7 input mode */        \
        {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio11 input mode, gpio10~8 input mode */ \
@@ -204,7 +204,7 @@ extern struct wlan_pwr_cfg  rtl8812_leave_lps_flow[RTL8812_TRANS_LPS_TO_ACT_STEP
        4: LPS--Low Power State
        5: SUS--Suspend
 
-       The transision from different states are defined below
+       The transition from different states are defined below
        TRANS_CARDEMU_TO_ACT
        TRANS_ACT_TO_CARDEMU
        TRANS_CARDEMU_TO_SUS
index 710bc015251c72c949e5660c2ad6b6e462bcb5aa..ff18871877707bd6d61b029d63a915ce14461c47 100644 (file)
@@ -82,7 +82,7 @@ bool rtl_hal_pwrseqcmdparsing (struct rtl_priv* rtlpriv, u8 cut_version,
                                        value = value | (GET_PWR_CFG_VALUE(pwr_cfg_cmd)
                                                        & GET_PWR_CFG_MASK(pwr_cfg_cmd));
 
-                                       /*Write the value back to sytem register*/
+                                       /*Write the value back to system register*/
                                        rtl_write_byte(rtlpriv, offset, value);
                                }
                                break;
index 09c5f00d2603c284175cb7f977b40b2cc9dd2685..beffb4243b1e11e6831e4dc627fb2d19d226dca0 100644 (file)
 #define        IMR_BCNDMAINT3                  BIT(23)         /* Beacon DMA Interrupt 3               */
 #define        IMR_BCNDMAINT2                  BIT(22)         /* Beacon DMA Interrupt 2               */
 #define        IMR_BCNDMAINT1                  BIT(21)         /* Beacon DMA Interrupt 1               */
-#define        IMR_BCNDOK7                             BIT(20)         /* Beacon Queue DMA OK Interrup 7 */
-#define        IMR_BCNDOK6                             BIT(19)         /* Beacon Queue DMA OK Interrup 6 */
-#define        IMR_BCNDOK5                             BIT(18)         /* Beacon Queue DMA OK Interrup 5 */
-#define        IMR_BCNDOK4                             BIT(17)         /* Beacon Queue DMA OK Interrup 4 */
-#define        IMR_BCNDOK3                             BIT(16)         /* Beacon Queue DMA OK Interrup 3 */
-#define        IMR_BCNDOK2                             BIT(15)         /* Beacon Queue DMA OK Interrup 2 */
-#define        IMR_BCNDOK1                             BIT(14)         /* Beacon Queue DMA OK Interrup 1 */
+#define        IMR_BCNDOK7                             BIT(20)         /* Beacon Queue DMA OK Interrupt 7 */
+#define        IMR_BCNDOK6                             BIT(19)         /* Beacon Queue DMA OK Interrupt 6 */
+#define        IMR_BCNDOK5                             BIT(18)         /* Beacon Queue DMA OK Interrupt 5 */
+#define        IMR_BCNDOK4                             BIT(17)         /* Beacon Queue DMA OK Interrupt 4 */
+#define        IMR_BCNDOK3                             BIT(16)         /* Beacon Queue DMA OK Interrupt 3 */
+#define        IMR_BCNDOK2                             BIT(15)         /* Beacon Queue DMA OK Interrupt 2 */
+#define        IMR_BCNDOK1                             BIT(14)         /* Beacon Queue DMA OK Interrupt 1 */
 #define        IMR_ATIMEND_E           BIT(13)         /* ATIM Window End Extension for Win7 */
 #define        IMR_TXERR                               BIT(11)         /* Tx Error Flag Interrupt Status, write 1 clear. */
 #define        IMR_RXERR                               BIT(10)         /* Rx Error Flag INT Status, Write 1 clear */
 #define        HWSET_MAX_SIZE                          512
 #define   EFUSE_MAX_SECTION                    64
 #define   EFUSE_REAL_CONTENT_LEN                       256
-#define        EFUSE_OOB_PROTECT_BYTES         18      /* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/
+#define        EFUSE_OOB_PROTECT_BYTES         18      /* PG data exclude header, dummy 7 bytes from CP test and reserved 1byte.*/
 
 
 #define        EEPROM_DEFAULT_TSSI                                     0x0
 #define        ROFDM0_TXCOEFF5                         0xcb4
 #define        ROFDM0_TXCOEFF6                         0xcb8
 
-/*Path_A RFE cotrol */
+/*Path_A RFE control */
 #define        RA_RFE_CTRL_8812                                0xcb8
 /*Path_B RFE control*/
 #define        RB_RFE_CTRL_8812                                0xeb8
 #define                WOL_REASON_DEAUTH                       BIT(3)
 #define                WOL_REASON_FW_DISCONNECT        BIT(4)
 
-#define                RA_RFE_PINMUX   0xcb0  /* Path_A RFE cotrol pinmux*/
+#define                RA_RFE_PINMUX   0xcb0  /* Path_A RFE control pinmux*/
 #define                RB_RFE_PINMUX   0xeb0 /* Path_B RFE control pinmux*/
 
 #define                RA_RFE_INV 0xcb4
 #define                RB_RFE_INV 0xeb4
 
 /* RXIQC */
-#define                RA_RXIQC_AB     0xc10  /*RxIQ imblance matrix coeff. A & B*/
-#define                RA_RXIQC_CD     0xc14  /*RxIQ imblance matrix coeff. C & D*/
+#define                RA_RXIQC_AB     0xc10  /*RxIQ imbalance matrix coeff. A & B*/
+#define                RA_RXIQC_CD     0xc14  /*RxIQ imbalance matrix coeff. C & D*/
 #define                RA_TXSCALE              0xc1c  /* Pah_A TX scaling factor*/
 #define                RB_TXSCALE              0xe1c  /* Path_B TX scaling factor*/
-#define                RB_RXIQC_AB     0xe10  /*RxIQ imblance matrix coeff. A & B*/
-#define                RB_RXIQC_CD     0xe14  /*RxIQ imblance matrix coeff. C & D*/
+#define                RB_RXIQC_AB     0xe10  /*RxIQ imbalance matrix coeff. A & B*/
+#define                RB_RXIQC_CD     0xe14  /*RxIQ imbalance matrix coeff. C & D*/
 #define                RXIQC_AC                0x02ff  /*bit mask for IQC matrix element A & C*/
 #define                RXIQC_BD                0x02ff0000 /*bit mask for IQC matrix element A & C*/
 
index 85a3474fc099a8174d59b5a8ecd02851393e3dad..a8d1755697701321ed0db379df4e43946b3aabf4 100644 (file)
@@ -57,9 +57,9 @@ void rtl8821ae_init_aspm_vars(struct ieee80211_hw *hw)
         * 0 - Disable ASPM,
         * 1 - Enable ASPM without Clock Req,
         * 2 - Enable ASPM with Clock Req,
-        * 3 - Alwyas Enable ASPM with Clock Req,
+        * 3 - Always Enable ASPM with Clock Req,
         * 4 - Always Enable ASPM without Clock Req.
-        * set defult to RTL8192CE:3 RTL8192E:2
+        * set default to RTL8192CE:3 RTL8192E:2
         * */
        rtlpci->const_pci_aspm = 3;
 
index f82ed5143b3e628865841c0762cfa5d3b54a8232..5f3246454e3ee778a7f091c97c6d1129512cbd48 100644 (file)
@@ -244,7 +244,7 @@ static void _rtl8821ae_query_rxphystatus(struct ieee80211_hw *hw,
                cck_agc_rpt = cck_buf->cck_agc_rpt;
 
                /* (1)Hardware does not provide RSSI for CCK */
-               /* (2)PWDB, Average PWDB cacluated by
+               /* (2)PWDB, Average PWDB calculated by
                 * hardware (for rate adaptive) */
                if (ppsc->rfpwr_state == ERFON)
                        cck_highpwr = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
@@ -363,7 +363,7 @@ static void _rtl8821ae_query_rxphystatus(struct ieee80211_hw *hw,
                                pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
                }
 
-               /* (2)PWDB, Average PWDB cacluated by
+               /* (2)PWDB, Average PWDB calculated by
                 * hardware (for rate adaptive) */
                rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 
@@ -603,7 +603,7 @@ bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw,
 
        /* hw will set status->decrypted true, if it finds the
         * frame is open data frame or mgmt frame. */
-       /* So hw will not decryption robust managment frame
+       /* So hw will not decryption robust management frame
         * for IEEE80211w but still set status->decrypted
         * true, so here we should set it back to undecrypted
         * for IEEE80211w frame, and mac80211 sw will help
index 3b5b2e7fc35ae1629870f6c938d88be4afa4d32f..17a9d9f8781d53b95688cff21a654e95183d91e1 100644 (file)
@@ -76,7 +76,7 @@
 #define RTL_SLOT_TIME_20               20
 
 /*related with tcp/ip. */
-/*if_ehther.h*/
+/*if_ether.h*/
 #define ETH_P_PAE                      0x888E  /*Port Access Entity
                                                 *(IEEE 802.1X) */
 #define ETH_P_IP                       0x0800  /*Internet Protocol packet */
 #define MAX_NUM_RATES                  264
 
 /*for 88E use*/
-/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+/*It must always set to 4, otherwise read efuse table sequence will be wrong.*/
 #define MAX_TX_COUNT                   4
 #define        MAX_RF_PATH                     4
 #define        MAX_CHNL_GROUP_24G              6
@@ -435,7 +435,7 @@ enum ht_channel_width {
        HT_CHANNEL_WIDTH_80 = 2,
 };
 
-/* Ref: 802.11i sepc D10.0 7.3.2.25.1
+/* Ref: 802.11i spec D10.0 7.3.2.25.1
 Cipher Suites Encryption Algorithms */
 enum rt_enc_alg {
        NO_ENCRYPTION = 0,
@@ -499,14 +499,14 @@ enum rtl_var_map {
        RTL_IMR_BCNDMAINT3,     /*Beacon DMA Interrupt 3 */
        RTL_IMR_BCNDMAINT2,     /*Beacon DMA Interrupt 2 */
        RTL_IMR_BCNDMAINT1,     /*Beacon DMA Interrupt 1 */
-       RTL_IMR_BCNDOK8,        /*Beacon Queue DMA OK Interrup 8 */
-       RTL_IMR_BCNDOK7,        /*Beacon Queue DMA OK Interrup 7 */
-       RTL_IMR_BCNDOK6,        /*Beacon Queue DMA OK Interrup 6 */
-       RTL_IMR_BCNDOK5,        /*Beacon Queue DMA OK Interrup 5 */
-       RTL_IMR_BCNDOK4,        /*Beacon Queue DMA OK Interrup 4 */
-       RTL_IMR_BCNDOK3,        /*Beacon Queue DMA OK Interrup 3 */
-       RTL_IMR_BCNDOK2,        /*Beacon Queue DMA OK Interrup 2 */
-       RTL_IMR_BCNDOK1,        /*Beacon Queue DMA OK Interrup 1 */
+       RTL_IMR_BCNDOK8,        /*Beacon Queue DMA OK Interrupt 8 */
+       RTL_IMR_BCNDOK7,        /*Beacon Queue DMA OK Interrupt 7 */
+       RTL_IMR_BCNDOK6,        /*Beacon Queue DMA OK Interrupt 6 */
+       RTL_IMR_BCNDOK5,        /*Beacon Queue DMA OK Interrupt 5 */
+       RTL_IMR_BCNDOK4,        /*Beacon Queue DMA OK Interrupt 4 */
+       RTL_IMR_BCNDOK3,        /*Beacon Queue DMA OK Interrupt 3 */
+       RTL_IMR_BCNDOK2,        /*Beacon Queue DMA OK Interrupt 2 */
+       RTL_IMR_BCNDOK1,        /*Beacon Queue DMA OK Interrupt 1 */
        RTL_IMR_TIMEOUT2,       /*Timeout interrupt 2 */
        RTL_IMR_TIMEOUT1,       /*Timeout interrupt 1 */
        RTL_IMR_TXFOVW,         /*Transmit FIFO Overflow */
@@ -515,10 +515,10 @@ enum rtl_var_map {
        RTL_IMR_RXFOVW,         /*Receive FIFO Overflow */
        RTL_IMR_RDU,            /*Receive Descriptor Unavailable */
        RTL_IMR_ATIMEND,        /*For 92C,ATIM Window End Interrupt */
-       RTL_IMR_BDOK,           /*Beacon Queue DMA OK Interrup */
+       RTL_IMR_BDOK,           /*Beacon Queue DMA OK Interrupt */
        RTL_IMR_HIGHDOK,        /*High Queue DMA OK Interrupt */
        RTL_IMR_COMDOK,         /*Command Queue DMA OK Interrupt*/
-       RTL_IMR_TBDOK,          /*Transmit Beacon OK interrup */
+       RTL_IMR_TBDOK,          /*Transmit Beacon OK interrupt */
        RTL_IMR_MGNTDOK,        /*Management Queue DMA OK Interrupt */
        RTL_IMR_TBDER,          /*For 92C,Transmit Beacon Error Interrupt */
        RTL_IMR_BKDOK,          /*AC_BK DMA OK Interrupt */
@@ -1256,7 +1256,7 @@ struct rtl_security {
        bool use_defaultkey;
        /*Encryption Algorithm for Unicast Packet */
        enum rt_enc_alg pairwise_enc_algorithm;
-       /*Encryption Algorithm for Brocast/Multicast */
+       /*Encryption Algorithm for Broadcast/Multicast */
        enum rt_enc_alg group_enc_algorithm;
        /*Cam Entry Bitmap */
        u32 hwsec_cam_bitmap;
@@ -1691,7 +1691,7 @@ struct rtl_stats {
 };
 
 struct rt_link_detect {
-       /* count for raoming */
+       /* count for roaming */
        u32 bcn_rx_inperiod;
        u32 roam_times;
 
@@ -2089,7 +2089,7 @@ struct rtl_priv {
 
        /*
         *hal_cfg : for diff cards
-        *intf_ops : for diff interrface usb/pcie
+        *intf_ops : for diff interface usb/pcie
         */
        struct rtl_hal_cfg *cfg;
        struct rtl_intf_ops *intf_ops;
@@ -2107,7 +2107,7 @@ struct rtl_priv {
        /*for bt coexist use*/
        struct rtl_bt_coexist btcoexist;
 
-       /* seperate 92ee from other ICs,
+       /* separate 92ee from other ICs,
          * 92ee use new trx flow. */
        bool use_new_trx_flow;
        /*This must be the last item so
@@ -2385,7 +2385,7 @@ Set subfield of little-endian 4-byte value to specified value.    */
 #define        RT_RF_PS_LEVEL_ALWAYS_ASPM      BIT(6)
 /* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/
 #define        RT_PS_LEVEL_ASPM                BIT(7)
-/*When LPS is on, disable 2R if no packet is received or transmittd.*/
+/*When LPS is on, disable 2R if no packet is received or transmitted.*/
 #define        RT_RF_LPS_DISALBE_2R            BIT(30)
 #define        RT_RF_LPS_LEVEL_ASPM            BIT(31) /*LPS with ASPM */
 #define        RT_IN_PS_LEVEL(ppsc, _ps_flg)           \
index edf979f18a6c983c411a73a7cb05b419ee7b956f..d22916a4b9d8d131dd64805a981324ab66ee5838 100644 (file)
@@ -259,7 +259,7 @@ static int ms_read_bytes(struct rtsx_chip *chip,
                MS_TRANSFER_END, MS_TRANSFER_END);
 
        for (i = 0; i < data_len - 1; i++)
-              rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+               rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
 
        if (data_len % 2)
                rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig
deleted file mode 100644 (file)
index 245e784..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-config SB105X
-       tristate "SystemBase PCI Multiport UART"
-       select SERIAL_CORE
-       depends on PCI && X86 && TTY && BROKEN
-       help
-         A driver for the SystemBase Multi-2/PCI serial card
-
-         To compile this driver a module, choose M here: the module
-         will be called "sb105x".
diff --git a/drivers/staging/sb105x/Makefile b/drivers/staging/sb105x/Makefile
deleted file mode 100644 (file)
index b1bf377..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_SB105X) +=        sb105x.o
-
-sb105x-y :=  sb_pci_mp.o
diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h
deleted file mode 100644 (file)
index 276c1bb..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-
-/*
- * SB105X_UART.h
- *
- * Copyright (C) 2008 systembase
- *
- * UART registers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef UART_SB105X_H
-#define UART_SB105X_H
-
-/*
- * option register
- */
-
-/* Device Information Register */
-#define MP_OPTR_DIR0           0x04    /* port0 ~ port8 */
-#define MP_OPTR_DIR1           0x05    /* port8 ~ port15 */
-#define MP_OPTR_DIR2           0x06    /* port16 ~ port23 */
-#define MP_OPTR_DIR3           0x07    /* port24 ~ port31 */
-
-#define DIR_UART_16C550        0
-#define DIR_UART_16C1050       1
-#define DIR_UART_16C1050A      2
-
-#define        DIR_CLK_1843200         0x0             /* input clock 1843200 Hz */
-#define        DIR_CLK_3686400         0x1             /* input clock 3686400 Hz */
-#define        DIR_CLK_7372800         0x2             /* input clock 7372800 Hz */
-#define        DIR_CLK_14745600        0x3             /* input clock 14745600 Hz */
-#define        DIR_CLK_29491200        0x4             /* input clock 29491200 Hz */
-#define        DIR_CLK_58985400        0x5             /* input clock 58985400 Hz */
-
-/* Interface Information Register */
-#define MP_OPTR_IIR0           0x08    /* port0 ~ port8 */
-#define MP_OPTR_IIR1           0x09    /* port8 ~ port15 */
-#define MP_OPTR_IIR2           0x0A    /* port16 ~ port23 */
-#define MP_OPTR_IIR3           0x0B    /* port24 ~ port31 */
-
-#define IIR_RS232              0x00            /* RS232 type */
-#define IIR_RS422              0x10            /* RS422 type */
-#define IIR_RS485              0x20            /* RS485 type */
-#define IIR_TYPE_MASK          0x30
-
-/* Interrupt Mask Register */
-#define MP_OPTR_IMR0           0x0C    /* port0 ~ port8 */
-#define MP_OPTR_IMR1           0x0D    /* port8 ~ port15 */
-#define MP_OPTR_IMR2           0x0E    /* port16 ~ port23 */
-#define MP_OPTR_IMR3           0x0F    /* port24 ~ port31 */
-
-/* Interrupt Poll Register */
-#define MP_OPTR_IPR0           0x10    /* port0 ~ port8 */
-#define MP_OPTR_IPR1           0x11    /* port8 ~ port15 */
-#define MP_OPTR_IPR2           0x12    /* port16 ~ port23 */
-#define MP_OPTR_IPR3           0x13    /* port24 ~ port31 */
-
-/* General Purpose Output Control Register */
-#define MP_OPTR_GPOCR          0x20
-
-/* General Purpose Output Data Register */
-#define MP_OPTR_GPODR          0x21
-
-/* Parallel Additional Function Register */
-#define MP_OPTR_PAFR           0x23
-
-/*
- * systembase 16c105x UART register
- */
-
-#define PAGE_0 0
-#define PAGE_1 1
-#define PAGE_2 2
-#define PAGE_3 3
-#define PAGE_4 4
-
-/*
- *  ******************************************************************
- *  * DLAB=0                  ===============       Page 0 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_RX              0       /* In:  Receive buffer */
-#define SB105X_TX              0       /* Out: Transmit buffer */
-
-#define SB105X_IER             1       /* Out: Interrupt Enable Register */
-
-#define SB105X_IER_CTSI                0x80    /* CTS# Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_RTSI                0x40    /* RTS# Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_XOI         0x20    /* Xoff Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_SME         0x10    /* Sleep Mode Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_MSI         0x08    /* Enable Modem status interrupt */
-#define SB105X_IER_RLSI                0x04    /* Enable receiver line status interrupt */
-#define SB105X_IER_THRI                0x02    /* Enable Transmitter holding register int. */
-#define SB105X_IER_RDI         0x01    /* Enable receiver data interrupt */
-
-#define SB105X_ISR             2       /* In:  Interrupt ID Register */
-
-#define SB105X_ISR_NOINT       0x01    /* No interrupts pending */
-#define SB105X_ISR_RLSI                0x06    /* Receiver line status interrupt (Priority = 1)*/
-#define SB105X_ISR_RDAI                0x0c    /* Receive Data Available interrupt */
-#define SB105X_ISR_CTII                0x04    /* Character Timeout Indication interrupt */
-#define SB105X_ISR_THRI                0x02    /* Transmitter holding register empty */
-#define SB105X_ISR_MSI         0x00    /* Modem status interrupt */
-#define SB105X_ISR_RXCI                0x10    /* Receive Xoff or Special Character interrupt */
-#define SB105X_ISR_RCSI                0x20    /* RTS#, CTS# status interrupt during Auto RTS/CTS flow control */
-
-#define SB105X_FCR             2       /* Out: FIFO Control Register */
-
-#define SB105X_FCR_FEN         0x01    /* FIFO Enable */
-#define SB105X_FCR_RXFR                0x02    /* RX FIFO Reset */
-#define SB105X_FCR_TXFR                0x04    /* TX FIFO Reset */
-#define SB105X_FCR_DMS         0x08    /* DMA Mode Select */
-
-#define SB105X_FCR_RTR08       0x00  /* Receive Trigger Level set at 8 */
-#define SB105X_FCR_RTR16       0x40  /* Receive Trigger Level set at 16 */
-#define SB105X_FCR_RTR56       0x80  /* Receive Trigger Level set at 56 */
-#define SB105X_FCR_RTR60       0xc0  /* Receive Trigger Level set at 60 */
-#define SB105X_FCR_TTR08       0x00  /* Transmit Trigger Level set at 8 */
-#define SB105X_FCR_TTR16       0x10  /* Transmit Trigger Level set at 16 */
-#define SB105X_FCR_TTR32       0x20  /* Transmit Trigger Level set at 32 */
-#define SB105X_FCR_TTR56       0x30  /* Transmit Trigger Level set at 56 */
-
-#define SB105X_LCR             3       /* Out: Line Control Register */
-/*
- *  * Note: if the word length is 5 bits (SB105X_LCR_WLEN5), then setting 
- *  * SB105X_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
- */
-#define SB105X_LCR_DLAB        0x80  /* Divisor Latch Enable */
-#define SB105X_LCR_SBC         0x40  /* Break Enable*/
-#define SB105X_LCR_SPAR        0x20  /* Set Stick parity */
-#define SB105X_LCR_EPAR        0x10  /* Even parity select */
-#define SB105X_LCR_PAREN       0x08  /* Parity Enable */
-#define SB105X_LCR_STOP        0x04  /* Stop bits: 0->1 bit, 1->2 bits, 1 and SB105X_LCR_WLEN5 -> 1.5 bit */
-#define SB105X_LCR_WLEN5       0x00  /* Wordlength: 5 bits */
-#define SB105X_LCR_WLEN6       0x01  /* Wordlength: 6 bits */
-#define SB105X_LCR_WLEN7       0x02  /* Wordlength: 7 bits */
-#define SB105X_LCR_WLEN8       0x03  /* Wordlength: 8 bits */
-
-#define SB105X_LCR_BF          0xBF
-
-#define SB105X_MCR             4       /* Out: Modem Control Register */
-#define SB105X_MCR_CPS         0x80  /* Clock Prescaler Select */
-#define SB105X_MCR_P2S         0x40  /* Page 2 Select /Xoff Re-Transmit Access Enable */
-#define SB105X_MCR_XOA         0x20  /* Xon Any Enable */
-#define SB105X_MCR_ILB         0x10  /* Internal Loopback Enable */
-#define SB105X_MCR_OUT2                0x08  /* Out2/Interrupt Output Enable*/
-#define SB105X_MCR_OUT1                0x04  /* Out1/Interrupt Output Enable */
-#define SB105X_MCR_RTS         0x02  /* RTS# Output */
-#define SB105X_MCR_DTR         0x01  /* DTR# Output */
-
-#define SB105X_LSR             5       /* In:  Line Status Register */
-#define SB105X_LSR_RFEI        0x80  /* Receive FIFO data error Indicator */
-#define SB105X_LSR_TEMI        0x40  /* THR and TSR Empty Indicator */
-#define SB105X_LSR_THRE                0x20  /* THR Empty Indicator */
-#define SB105X_LSR_BII         0x10  /* Break interrupt indicator */
-#define SB105X_LSR_FEI         0x08  /* Frame error indicator */
-#define SB105X_LSR_PEI         0x04  /* Parity error indicator */
-#define SB105X_LSR_OEI         0x02  /* Overrun error indicator */
-#define SB105X_LSR_RDRI                0x01  /* Receive data ready Indicator*/
-
-#define SB105X_MSR             6       /* In:  Modem Status Register */
-#define SB105X_MSR_DCD         0x80  /* Data Carrier Detect */
-#define SB105X_MSR_RI          0x40  /* Ring Indicator */
-#define SB105X_MSR_DSR         0x20  /* Data Set Ready */
-#define SB105X_MSR_CTS         0x10  /* Clear to Send */
-#define SB105X_MSR_DDCD                0x08  /* Delta DCD */
-#define SB105X_MSR_DRI         0x04  /* Delta ring indicator */
-#define SB105X_MSR_DDSR                0x02  /* Delta DSR */
-#define SB105X_MSR_DCTS                0x01  /* Delta CTS */
-
-#define SB105XA_MDR            6       /* Out: Multi Drop mode Register */
-#define SB105XA_MDR_NPS                0x08  /* 9th Bit Polarity Select */
-#define SB105XA_MDR_AME                0x02  /* Auto Multi-drop Enable */
-#define SB105XA_MDR_MDE                0x01  /* Multi Drop Enable */
-
-#define SB105X_SPR             7       /* I/O: Scratch Register */
-
-/*
- * DLAB=1
- */
-#define SB105X_DLL             0       /* Out: Divisor Latch Low */
-#define SB105X_DLM             1       /* Out: Divisor Latch High */
-
-/*
- *  ******************************************************************
- *  * DLAB(LCR[7]) = 0 , MCR[6] = 1  =============  Page 2 Registers *
- *  ******************************************************************
- */
-#define SB105X_GICR            1       /* Global Interrupt Control Register */
-#define SB105X_GICR_GIM        0x01  /* Global Interrupt Mask */
-
-#define SB105X_GISR            2       /* Global Interrupt Status Register */
-#define SB105X_GISR_MGICR0     0x80  /* Mirror the content of GICR[0] */
-#define SB105X_GISR_CS3IS      0x08  /* SB105X of CS3# Interrupt Status */
-#define SB105X_GISR_CS2IS      0x04  /* SB105X of CS2# Interrupt Status */
-#define SB105X_GISR_CS1IS      0x02  /* SB105X of CS1# Interrupt Status */
-#define SB105X_GISR_CS0IS      0x01  /* SB105X of CS0# Interrupt Status */
-
-#define SB105X_TFCR            5       /* Transmit FIFO Count Register */
-
-#define SB105X_RFCR            6       /* Receive FIFO Count Register */
-
-#define        SB105X_FSR              7       /* Flow Control Status Register */
-#define SB105X_FSR_THFS        0x20  /* Transmit Hardware Flow Control Status */
-#define SB105X_FSR_TSFS        0x10  /* Transmit Software Flow Control Status */
-#define SB105X_FSR_RHFS        0x02  /* Receive Hardware Flow Control Status */
-#define SB105X_FSR_RSFS        0x01  /* Receive Software Flow Control Status */
-
-/*
- *  ******************************************************************
- *  * LCR = 0xBF, PSR[0] = 0       =============    Page 3 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_PSR             0       /* Page Select Register */
-#define SB105X_PSR_P3KEY       0xA4 /* Page 3 Select Key */
-#define SB105X_PSR_P4KEY       0xA5 /* Page 5 Select Key */
-
-#define SB105X_ATR             1       /* Auto Toggle Control Register */
-#define SB105X_ATR_RPS         0x80  /* RXEN Polarity Select */
-#define SB105X_ATR_RCMS        0x40  /* RXEN Control Mode Select */
-#define SB105X_ATR_TPS         0x20  /* TXEN Polarity Select */
-#define SB105X_ATR_TCMS        0x10  /* TXEN Control Mode Select */
-#define SB105X_ATR_ATDIS       0x00  /* Auto Toggle is disabled */
-#define SB105X_ATR_ART         0x01  /* RTS#/TXEN pin operates as TXEN */
-#define SB105X_ATR_ADT         0x02  /* DTR#/TXEN pin operates as TXEN */
-#define SB105X_ATR_A80         0x03  /* only in 80 pin use */
-
-#define SB105X_EFR             2       /* (Auto) Enhanced Feature Register */
-#define SB105X_EFR_ACTS        0x80  /* Auto-CTS Flow Control Enable */
-#define SB105X_EFR_ARTS        0x40  /* Auto-RTS Flow Control Enable */
-#define SB105X_EFR_SCD         0x20  /* Special Character Detect */
-#define SB105X_EFR_EFBEN       0x10  /* Enhanced Function Bits Enable */
-
-#define SB105X_XON1            4       /* Xon1 Character Register */
-#define SB105X_XON2            5       /* Xon2 Character Register */
-#define SB105X_XOFF1           6       /* Xoff1 Character Register */
-#define SB105X_XOFF2           7       /* Xoff2 Character Register */
-
-/*
- *  ******************************************************************
- *  * LCR = 0xBF, PSR[0] = 1       ============     Page 4 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_AFR             1       /* Additional Feature Register */
-#define SB105X_AFR_GIPS        0x20  /* Global Interrupt Polarity Select */
-#define SB105X_AFR_GIEN        0x10  /* Global Interrupt Enable */
-#define SB105X_AFR_AFEN        0x01  /* 256-byte FIFO Enable */
-
-#define SB105X_XRCR            2       /* Xoff Re-transmit Count Register */
-#define SB105X_XRCR_NRC1       0x00  /* Transmits Xoff Character whenever the number of received data is 1 during XOFF status */
-#define SB105X_XRCR_NRC4       0x01  /* Transmits Xoff Character whenever the number of received data is 4 during XOFF status */
-#define SB105X_XRCR_NRC8       0x02  /* Transmits Xoff Character whenever the number of received data is 8 during XOFF status */
-#define SB105X_XRCR_NRC16      0x03  /* Transmits Xoff Character whenever the number of received data is 16 during XOFF status */
-
-#define SB105X_TTR             4       /* Transmit FIFO Trigger Level Register */
-#define SB105X_RTR             5       /* Receive FIFO Trigger Level Register */
-#define SB105X_FUR             6       /* Flow Control Upper Threshold Register */
-#define SB105X_FLR             7       /* Flow Control Lower Threshold Register */
-
-
-/* page 0 */
-
-#define SB105X_GET_CHAR(port)  inb((port)->iobase + SB105X_RX)
-#define SB105X_GET_IER(port)   inb((port)->iobase + SB105X_IER)
-#define SB105X_GET_ISR(port)   inb((port)->iobase + SB105X_ISR)
-#define SB105X_GET_LCR(port)   inb((port)->iobase + SB105X_LCR)
-#define SB105X_GET_MCR(port)   inb((port)->iobase + SB105X_MCR)
-#define SB105X_GET_LSR(port)   inb((port)->iobase + SB105X_LSR)
-#define SB105X_GET_MSR(port)   inb((port)->iobase + SB105X_MSR)
-#define SB105X_GET_SPR(port)   inb((port)->iobase + SB105X_SPR)
-
-#define SB105X_PUT_CHAR(port,v)        outb((v),(port)->iobase + SB105X_TX )
-#define SB105X_PUT_IER(port,v) outb((v),(port)->iobase + SB105X_IER )
-#define SB105X_PUT_FCR(port,v) outb((v),(port)->iobase + SB105X_FCR )
-#define SB105X_PUT_LCR(port,v) outb((v),(port)->iobase + SB105X_LCR )
-#define SB105X_PUT_MCR(port,v) outb((v),(port)->iobase + SB105X_MCR )
-#define SB105X_PUT_SPR(port,v) outb((v),(port)->iobase + SB105X_SPR )
-
-
-/* page 1 */
-#define SB105X_GET_REG(port,reg)       inb((port)->iobase + (reg))
-#define SB105X_PUT_REG(port,reg,v)     outb((v),(port)->iobase + (reg))
-
-/* page 2 */
-
-#define SB105X_PUT_PSR(port,v) outb((v),(port)->iobase + SB105X_PSR )
-
-#endif 
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
deleted file mode 100644 (file)
index c9d6ee3..0000000
+++ /dev/null
@@ -1,3189 +0,0 @@
-#include "sb_pci_mp.h"
-#include <linux/module.h>
-#include <linux/parport.h>
-
-extern struct parport *parport_pc_probe_port(unsigned long base_lo,
-               unsigned long base_hi,
-               int irq, int dma,
-               struct device *dev,
-               int irqflags);
-
-static struct mp_device_t mp_devs[MAX_MP_DEV];
-static int mp_nrpcibrds = sizeof(mp_pciboards)/sizeof(mppcibrd_t);
-static int NR_BOARD=0;
-static int NR_PORTS=0;
-static struct mp_port multi_ports[MAX_MP_PORT];
-static struct irq_info irq_lists[NR_IRQS];
-
-static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset);
-static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value);
-static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset);
-static int sb1054_get_register(struct sb_uart_port *port, int page, int reg);
-static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int value);
-static void SendATCommand(struct mp_port *mtpt);
-static int set_deep_fifo(struct sb_uart_port *port, int status);
-static int get_deep_fifo(struct sb_uart_port *port);
-static int get_device_type(int arg);
-static int set_auto_rts(struct sb_uart_port *port, int status);
-static void mp_stop(struct tty_struct *tty);
-static void __mp_start(struct tty_struct *tty);
-static void mp_start(struct tty_struct *tty);
-static void mp_tasklet_action(unsigned long data);
-static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear);
-static int mp_startup(struct sb_uart_state *state, int init_hw);
-static void mp_shutdown(struct sb_uart_state *state);
-static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios);
-
-static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c);
-static int mp_put_char(struct tty_struct *tty, unsigned char ch);
-
-static void mp_put_chars(struct tty_struct *tty);
-static int mp_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int mp_write_room(struct tty_struct *tty);
-static int mp_chars_in_buffer(struct tty_struct *tty);
-static void mp_flush_buffer(struct tty_struct *tty);
-static void mp_send_xchar(struct tty_struct *tty, char ch);
-static void mp_throttle(struct tty_struct *tty);
-static void mp_unthrottle(struct tty_struct *tty);
-static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo);
-static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo);
-static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value);
-
-static int mp_tiocmget(struct tty_struct *tty);
-static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-static int mp_break_ctl(struct tty_struct *tty, int break_state);
-static int mp_do_autoconfig(struct sb_uart_state *state);
-static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg);
-static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt);
-static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios);
-static void mp_close(struct tty_struct *tty, struct file *filp);
-static void mp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void mp_hangup(struct tty_struct *tty);
-static void mp_update_termios(struct sb_uart_state *state);
-static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state);
-static struct sb_uart_state *uart_get(struct uart_driver *drv, int line);
-static int mp_open(struct tty_struct *tty, struct file *filp);
-static const char *mp_type(struct sb_uart_port *port);
-static void mp_change_pm(struct sb_uart_state *state, int pm_state);
-static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port);
-static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port);
-static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state);
-static int mp_register_driver(struct uart_driver *drv);
-static void mp_unregister_driver(struct uart_driver *drv);
-static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port);
-static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port);
-static void autoconfig(struct mp_port *mtpt, unsigned int probeflags);
-static void autoconfig_irq(struct mp_port *mtpt);
-static void multi_stop_tx(struct sb_uart_port *port);
-static void multi_start_tx(struct sb_uart_port *port);
-static void multi_stop_rx(struct sb_uart_port *port);
-static void multi_enable_ms(struct sb_uart_port *port);
-static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status );
-static _INLINE_ void transmit_chars(struct mp_port *mtpt);
-static _INLINE_ void check_modem_status(struct mp_port *mtpt);
-static inline void multi_handle_port(struct mp_port *mtpt);
-static irqreturn_t multi_interrupt(int irq, void *dev_id);
-static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt);
-static int serial_link_irq_chain(struct mp_port *mtpt);
-static void serial_unlink_irq_chain(struct mp_port *mtpt);
-static void multi_timeout(unsigned long data);
-static unsigned int multi_tx_empty(struct sb_uart_port *port);
-static unsigned int multi_get_mctrl(struct sb_uart_port *port);
-static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl);
-static void multi_break_ctl(struct sb_uart_port *port, int break_state);
-static int multi_startup(struct sb_uart_port *port);
-static void multi_shutdown(struct sb_uart_port *port);
-static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud);
-static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old);
-static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate);
-static void multi_release_std_resource(struct mp_port *mtpt);
-static void multi_release_port(struct sb_uart_port *port);
-static int multi_request_port(struct sb_uart_port *port);
-static void multi_config_port(struct sb_uart_port *port, int flags);
-static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser);
-static const char *multi_type(struct sb_uart_port *port);
-static void __init multi_init_ports(void);
-static void __init multi_register_ports(struct uart_driver *drv);
-static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd);
-
-static int deep[256];
-static int deep_count;
-static int fcr_arr[256];
-static int fcr_count;
-static int ttr[256];
-static int ttr_count;
-static int rtr[256];
-static int rtr_count;
-
-module_param_array(deep,int,&deep_count,0);
-module_param_array(fcr_arr,int,&fcr_count,0);
-module_param_array(ttr,int,&ttr_count,0);
-module_param_array(rtr,int,&rtr_count,0);
-
-static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset)
-{
-       return inb(mtpt->port.iobase + offset);
-}
-
-static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value)
-{
-       outb(value, mtpt->port.iobase + offset);
-}
-
-static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset)
-{
-       return inb(mtpt->option_base_addr + offset);
-}
-
-static int sb1053a_get_interface(struct mp_port *mtpt, int port_num)
-{
-       unsigned long option_base_addr = mtpt->option_base_addr;
-       unsigned int  interface = 0;
-
-       switch (port_num)
-       {
-               case 0:
-               case 1:
-                       /* set GPO[1:0] = 00 */
-                       outb(0x00, option_base_addr + MP_OPTR_GPODR);
-                       break;
-               case 2:
-               case 3:
-                       /* set GPO[1:0] = 01 */
-                       outb(0x01, option_base_addr + MP_OPTR_GPODR);
-                       break;
-               case 4:
-               case 5:
-                       /* set GPO[1:0] = 10 */
-                       outb(0x02, option_base_addr + MP_OPTR_GPODR);
-                       break;
-               default:
-                       break;
-       }
-
-       port_num &= 0x1;
-
-       /* get interface */
-       interface = inb(option_base_addr + MP_OPTR_IIR0 + port_num);
-
-       /* set GPO[1:0] = 11 */
-       outb(0x03, option_base_addr + MP_OPTR_GPODR);
-
-       return (interface);
-}
-               
-static int sb1054_get_register(struct sb_uart_port *port, int page, int reg)
-{
-       int ret = 0;
-       unsigned int lcr = 0;
-       unsigned int mcr = 0;
-       unsigned int tmp = 0;
-
-       if( page <= 0)
-       {
-               printk(" page 0 can not use this function\n");
-               return -1;
-       }
-
-       switch(page)
-       {
-               case 1:
-                       lcr = SB105X_GET_LCR(port);
-                       tmp = lcr | SB105X_LCR_DLAB;
-                       SB105X_PUT_LCR(port, tmp);
-
-                       tmp = SB105X_GET_LCR(port);
-
-                       ret = SB105X_GET_REG(port,reg);
-                       SB105X_PUT_LCR(port,lcr);
-                       break;
-               case 2:
-                       mcr = SB105X_GET_MCR(port);
-                       tmp = mcr | SB105X_MCR_P2S;
-                       SB105X_PUT_MCR(port,tmp);
-
-                       ret = SB105X_GET_REG(port,reg);
-
-                       SB105X_PUT_MCR(port,mcr);
-                       break;
-               case 3:
-                       lcr = SB105X_GET_LCR(port);
-                       tmp = lcr | SB105X_LCR_BF;
-                       SB105X_PUT_LCR(port,tmp);
-                       SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P3KEY);
-
-                       ret = SB105X_GET_REG(port,reg);
-
-                       SB105X_PUT_LCR(port,lcr);
-                       break;
-               case 4:
-                       lcr = SB105X_GET_LCR(port);
-                       tmp = lcr | SB105X_LCR_BF;
-                       SB105X_PUT_LCR(port,tmp);
-                       SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P4KEY);
-
-                       ret = SB105X_GET_REG(port,reg);
-
-                       SB105X_PUT_LCR(port,lcr);
-                       break;
-               default:
-                       printk(" error invalid page number \n");
-                       return -1;
-       }
-
-       return ret;
-}
-
-static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int value)
-{  
-       int lcr = 0;
-       int mcr = 0;
-       int ret = 0;
-
-       if( page <= 0)
-       {
-               printk(" page 0 can not use this function\n");
-               return -1;
-       }
-       switch(page)
-       {
-               case 1:
-                       lcr = SB105X_GET_LCR(port);
-                       SB105X_PUT_LCR(port, lcr | SB105X_LCR_DLAB);
-
-                       SB105X_PUT_REG(port,reg,value);
-
-                       SB105X_PUT_LCR(port, lcr);
-                       ret = 1;
-                       break;
-               case 2:
-                       mcr = SB105X_GET_MCR(port);
-                       SB105X_PUT_MCR(port, mcr | SB105X_MCR_P2S);
-
-                       SB105X_PUT_REG(port,reg,value);
-
-                       SB105X_PUT_MCR(port, mcr);
-                       ret = 1;
-                       break;
-               case 3:
-                       lcr = SB105X_GET_LCR(port);
-                       SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
-                       SB105X_PUT_PSR(port, SB105X_PSR_P3KEY);
-
-                       SB105X_PUT_REG(port,reg,value);
-
-                       SB105X_PUT_LCR(port, lcr);
-                       ret = 1;
-                       break;
-               case 4:
-                       lcr = SB105X_GET_LCR(port);
-                       SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
-                       SB105X_PUT_PSR(port, SB105X_PSR_P4KEY);
-
-                       SB105X_PUT_REG(port,reg,value);
-
-                       SB105X_PUT_LCR(port, lcr);
-                       ret = 1;
-                       break;
-               default:
-                       printk(" error invalid page number \n");
-                       return -1;
-       }
-
-       return ret;
-}
-
-static int set_multidrop_mode(struct sb_uart_port *port, unsigned int mode)
-{
-       int mdr = SB105XA_MDR_NPS;
-
-       if (mode & MDMODE_ENABLE)
-       {
-               mdr |= SB105XA_MDR_MDE;
-       }
-
-       if (1) //(mode & MDMODE_AUTO)
-       {
-               int efr = 0;
-               mdr |= SB105XA_MDR_AME;
-               efr = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-               efr |= SB105X_EFR_SCD;
-               sb1054_set_register(port, PAGE_3, SB105X_EFR, efr);
-       }
-
-       sb1054_set_register(port, PAGE_1, SB105XA_MDR, mdr);
-       port->mdmode &= ~0x6;
-       port->mdmode |= mode;
-       printk("[%d] multidrop init: %x\n", port->line, port->mdmode);
-
-       return 0;
-}
-
-static int get_multidrop_addr(struct sb_uart_port *port)
-{
-       return sb1054_get_register(port, PAGE_3, SB105X_XOFF2);
-}
-
-static int set_multidrop_addr(struct sb_uart_port *port, unsigned int addr)
-{
-       sb1054_set_register(port, PAGE_3, SB105X_XOFF2, addr);
-
-       return 0;
-}
-
-static void SendATCommand(struct mp_port *mtpt)
-{
-       //                    a    t    cr   lf
-       unsigned char ch[] = {0x61,0x74,0x0d,0x0a,0x0};
-       unsigned char lineControl;
-       unsigned char i=0;
-       unsigned char Divisor = 0xc;
-
-       lineControl = serial_inp(mtpt,UART_LCR);
-       serial_outp(mtpt,UART_LCR,(lineControl | UART_LCR_DLAB));
-       serial_outp(mtpt,UART_DLL,(Divisor & 0xff));
-       serial_outp(mtpt,UART_DLM,(Divisor & 0xff00)>>8); //baudrate is 4800
-
-
-       serial_outp(mtpt,UART_LCR,lineControl); 
-       serial_outp(mtpt,UART_LCR,0x03); // N-8-1
-       serial_outp(mtpt,UART_FCR,7); 
-       serial_outp(mtpt,UART_MCR,0x3);
-       while(ch[i]){
-               while((serial_inp(mtpt,UART_LSR) & 0x60) !=0x60){
-                       ;
-               }
-               serial_outp(mtpt,0,ch[i++]);
-       }
-
-
-}// end of SendATCommand()
-
-static int set_deep_fifo(struct sb_uart_port *port, int status)
-{
-       int afr_status = 0;
-       afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-
-       if(status == ENABLE)
-       {
-               afr_status |= SB105X_AFR_AFEN;
-       }
-       else
-       {
-               afr_status &= ~SB105X_AFR_AFEN;
-       }
-               
-       sb1054_set_register(port,PAGE_4,SB105X_AFR,afr_status);
-       sb1054_set_register(port,PAGE_4,SB105X_TTR,ttr[port->line]); 
-       sb1054_set_register(port,PAGE_4,SB105X_RTR,rtr[port->line]); 
-       afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-               
-       return afr_status;
-}
-
-static int get_device_type(int arg)
-{
-       int ret;
-        ret = inb(mp_devs[arg].option_reg_addr+MP_OPTR_DIR0);
-        ret = (ret & 0xf0) >> 4;
-        switch (ret)
-        {
-               case DIR_UART_16C550:
-                    return PORT_16C55X;
-               case DIR_UART_16C1050:
-                    return PORT_16C105X;
-               case DIR_UART_16C1050A:
-               /*
-               if (mtpt->port.line < 2)
-               {
-                    return PORT_16C105XA;
-               }
-               else
-               {
-                   if (mtpt->device->device_id & 0x50)
-                   {
-                       return PORT_16C55X;
-                   }
-                   else
-                   {
-                       return PORT_16C105X;
-                   }
-               }*/
-               return PORT_16C105XA;
-               default:
-                    return PORT_UNKNOWN;
-        }
-
-}
-static int get_deep_fifo(struct sb_uart_port *port)
-{
-       int afr_status = 0;
-       afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-       return afr_status;
-}
-
-static int set_auto_rts(struct sb_uart_port *port, int status)
-{
-       int atr_status = 0;
-
-#if 0
-       int efr_status = 0;
-
-       efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-       if(status == ENABLE)
-               efr_status |= SB105X_EFR_ARTS;
-       else
-               efr_status &= ~SB105X_EFR_ARTS;
-       sb1054_set_register(port,PAGE_3,SB105X_EFR,efr_status);
-       efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-#endif
-               
-//ATR
-       atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
-       switch(status)
-       {
-               case RS422PTP:
-                       atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_A80);
-                       break;
-               case RS422MD:
-                       atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-                       break;
-               case RS485NE:
-                       atr_status = (SB105X_ATR_RCMS) | (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-                       break;
-               case RS485ECHO:
-                       atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-                       break;
-       }
-
-       sb1054_set_register(port,PAGE_3,SB105X_ATR,atr_status);
-       atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
-
-       return atr_status;
-}
-
-static void mp_stop(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-       unsigned long flags;
-
-       spin_lock_irqsave(&port->lock, flags);
-       port->ops->stop_tx(port);
-       spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void __mp_start(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-
-       if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
-                       !tty->stopped && !tty->hw_stopped)
-               port->ops->start_tx(port);
-}
-
-static void mp_start(struct tty_struct *tty)
-{
-       __mp_start(tty);
-}
-
-static void mp_tasklet_action(unsigned long data)
-{
-       struct sb_uart_state *state = (struct sb_uart_state *)data;
-       struct tty_struct *tty;
-
-       printk("tasklet is called!\n");
-       tty = state->info->tty;
-       tty_wakeup(tty);
-}
-
-static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear)
-{
-       unsigned int old;
-
-       old = port->mctrl;
-       port->mctrl = (old & ~clear) | set;
-       if (old != port->mctrl)
-               port->ops->set_mctrl(port, port->mctrl);
-}
-
-#define uart_set_mctrl(port,set)       mp_update_mctrl(port,set,0)
-#define uart_clear_mctrl(port,clear)   mp_update_mctrl(port,0,clear)
-
-static int mp_startup(struct sb_uart_state *state, int init_hw)
-{
-       struct sb_uart_info *info = state->info;
-       struct sb_uart_port *port = state->port;
-       unsigned long page;
-       int retval = 0;
-
-       if (info->flags & UIF_INITIALIZED)
-               return 0;
-
-       if (info->tty)
-               set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-       if (port->type == PORT_UNKNOWN)
-               return 0;
-
-       if (!info->xmit.buf) {
-               page = get_zeroed_page(GFP_KERNEL);
-               if (!page)
-                       return -ENOMEM;
-
-               info->xmit.buf = (unsigned char *) page;
-                       
-               uart_circ_clear(&info->xmit);
-       }
-
-       retval = port->ops->startup(port);
-       if (retval == 0) {
-               if (init_hw) {
-                       mp_change_speed(state, NULL);
-
-                       if (info->tty && (info->tty->termios.c_cflag & CBAUD))
-                               uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-               }
-
-               info->flags |= UIF_INITIALIZED;
-
-               if (info->tty)
-                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
-       }
-
-       if (retval && capable(CAP_SYS_ADMIN))
-               retval = 0;
-
-       return retval;
-}
-
-static void mp_shutdown(struct sb_uart_state *state)
-{
-       struct sb_uart_info *info = state->info;
-       struct sb_uart_port *port = state->port;
-
-       if (info->tty)
-               set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-       if (info->flags & UIF_INITIALIZED) {
-               info->flags &= ~UIF_INITIALIZED;
-
-               if (!info->tty || (info->tty->termios.c_cflag & HUPCL))
-                       uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-
-               wake_up_interruptible(&info->delta_msr_wait);
-
-               port->ops->shutdown(port);
-
-               synchronize_irq(port->irq);
-       }
-       tasklet_kill(&info->tlet);
-
-       if (info->xmit.buf) {
-               free_page((unsigned long)info->xmit.buf);
-               info->xmit.buf = NULL;
-       }
-}
-
-static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios)
-{
-       struct tty_struct *tty = state->info->tty;
-       struct sb_uart_port *port = state->port;
-
-       if (!tty || port->type == PORT_UNKNOWN)
-               return;
-
-       if (tty->termios.c_cflag & CRTSCTS)
-               state->info->flags |= UIF_CTS_FLOW;
-       else
-               state->info->flags &= ~UIF_CTS_FLOW;
-
-       if (tty->termios.c_cflag & CLOCAL)
-               state->info->flags &= ~UIF_CHECK_CD;
-       else
-               state->info->flags |= UIF_CHECK_CD;
-
-       port->ops->set_termios(port, &tty->termios, old_termios);
-}
-
-static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       if (!circ->buf)
-               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 int mp_put_char(struct tty_struct *tty, unsigned char ch)
-{
-       struct sb_uart_state *state = tty->driver_data;
-
-       return __mp_put_char(state->port, &state->info->xmit, ch);
-}
-
-static void mp_put_chars(struct tty_struct *tty)
-{
-       mp_start(tty);
-}
-
-static int mp_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port;
-       struct circ_buf *circ;
-       int c, ret = 0;
-
-       if (!state || !state->info) {
-               return -EL3HLT;
-       }
-
-       port = state->port;
-       circ = &state->info->xmit;
-
-       if (!circ->buf)
-               return 0;
-               
-       while (1) {
-               c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-               if (count < c)
-                       c = count;
-               if (c <= 0)
-                       break;
-       memcpy(circ->buf + circ->head, buf, c);
-
-               circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-               buf += c;
-               count -= c;
-               ret += c;
-       }
-       mp_start(tty);
-       return ret;
-}
-
-static int mp_write_room(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-
-       return uart_circ_chars_free(&state->info->xmit);
-}
-
-static int mp_chars_in_buffer(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-
-       return uart_circ_chars_pending(&state->info->xmit);
-}
-
-static void mp_flush_buffer(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port;
-       unsigned long flags;
-
-       if (!state || !state->info) {
-               return;
-       }
-
-       port = state->port;
-       spin_lock_irqsave(&port->lock, flags);
-       uart_circ_clear(&state->info->xmit);
-       spin_unlock_irqrestore(&port->lock, flags);
-       wake_up_interruptible(&tty->write_wait);
-       tty_wakeup(tty);
-}
-
-static void mp_send_xchar(struct tty_struct *tty, char ch)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-       unsigned long flags;
-
-       if (port->ops->send_xchar)
-               port->ops->send_xchar(port, ch);
-       else {
-               port->x_char = ch;
-               if (ch) {
-                       spin_lock_irqsave(&port->lock, flags);
-                       port->ops->start_tx(port);
-                       spin_unlock_irqrestore(&port->lock, flags);
-               }
-       }
-}
-
-static void mp_throttle(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-
-       if (I_IXOFF(tty))
-               mp_send_xchar(tty, STOP_CHAR(tty));
-
-       if (tty->termios.c_cflag & CRTSCTS)
-               uart_clear_mctrl(state->port, TIOCM_RTS);
-}
-
-static void mp_unthrottle(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-
-       if (I_IXOFF(tty)) {
-               if (port->x_char)
-                       port->x_char = 0;
-               else
-                       mp_send_xchar(tty, START_CHAR(tty));
-       }
-
-       if (tty->termios.c_cflag & CRTSCTS)
-               uart_set_mctrl(port, TIOCM_RTS);
-}
-
-static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo)
-{
-       struct sb_uart_port *port = state->port;
-       struct serial_struct tmp;
-
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.type            = port->type;
-       tmp.line            = port->line;
-       tmp.port            = port->iobase;
-       if (HIGH_BITS_OFFSET)
-               tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
-       tmp.irq             = port->irq;
-       tmp.flags           = port->flags;
-       tmp.xmit_fifo_size  = port->fifosize;
-       tmp.baud_base       = port->uartclk / 16;
-       tmp.close_delay     = state->close_delay;
-       tmp.closing_wait    = state->closing_wait == USF_CLOSING_WAIT_NONE ?
-               ASYNC_CLOSING_WAIT_NONE :
-               state->closing_wait;
-       tmp.custom_divisor  = port->custom_divisor;
-       tmp.hub6            = port->hub6;
-       tmp.io_type         = port->iotype;
-       tmp.iomem_reg_shift = port->regshift;
-       tmp.iomem_base      = (void *)port->mapbase;
-
-       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-               return -EFAULT;
-       return 0;
-}
-
-static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo)
-{
-       struct serial_struct new_serial;
-       struct sb_uart_port *port = state->port;
-       unsigned long new_port;
-       unsigned int change_irq, change_port, closing_wait;
-       unsigned int old_custom_divisor;
-       unsigned int old_flags, new_flags;
-       int retval = 0;
-
-       if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-               return -EFAULT;
-
-       new_port = new_serial.port;
-       if (HIGH_BITS_OFFSET)
-               new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-
-       new_serial.irq = irq_canonicalize(new_serial.irq);
-
-       closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
-               USF_CLOSING_WAIT_NONE : new_serial.closing_wait;
-       MP_STATE_LOCK(state);
-
-       change_irq  = new_serial.irq != port->irq;
-       change_port = new_port != port->iobase ||
-               (unsigned long)new_serial.iomem_base != port->mapbase ||
-               new_serial.hub6 != port->hub6 ||
-               new_serial.io_type != port->iotype ||
-               new_serial.iomem_reg_shift != port->regshift ||
-               new_serial.type != port->type;
-       old_flags = port->flags;
-       new_flags = new_serial.flags;
-       old_custom_divisor = port->custom_divisor;
-
-       if (!capable(CAP_SYS_ADMIN)) {
-               retval = -EPERM;
-               if (change_irq || change_port ||
-                               (new_serial.baud_base != port->uartclk / 16) ||
-                               (new_serial.close_delay != state->close_delay) ||
-                               (closing_wait != state->closing_wait) ||
-                               (new_serial.xmit_fifo_size != port->fifosize) ||
-                               (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
-                       goto exit;
-               port->flags = ((port->flags & ~UPF_USR_MASK) |
-                               (new_flags & UPF_USR_MASK));
-               port->custom_divisor = new_serial.custom_divisor;
-               goto check_and_exit;
-       }
-
-       if (port->ops->verify_port)
-               retval = port->ops->verify_port(port, &new_serial);
-
-       if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-                       (new_serial.baud_base < 9600))
-               retval = -EINVAL;
-
-       if (retval)
-               goto exit;
-
-       if (change_port || change_irq) {
-               retval = -EBUSY;
-
-               if (uart_users(state) > 1)
-                       goto exit;
-
-               mp_shutdown(state);
-       }
-
-       if (change_port) {
-               unsigned long old_iobase, old_mapbase;
-               unsigned int old_type, old_iotype, old_hub6, old_shift;
-
-               old_iobase = port->iobase;
-               old_mapbase = port->mapbase;
-               old_type = port->type;
-               old_hub6 = port->hub6;
-               old_iotype = port->iotype;
-               old_shift = port->regshift;
-
-               if (old_type != PORT_UNKNOWN)
-                       port->ops->release_port(port);
-
-               port->iobase = new_port;
-               port->type = new_serial.type;
-               port->hub6 = new_serial.hub6;
-               port->iotype = new_serial.io_type;
-               port->regshift = new_serial.iomem_reg_shift;
-               port->mapbase = (unsigned long)new_serial.iomem_base;
-
-               if (port->type != PORT_UNKNOWN) {
-                       retval = port->ops->request_port(port);
-               } else {
-                       retval = 0;
-               }
-
-               if (retval && old_type != PORT_UNKNOWN) {
-                       port->iobase = old_iobase;
-                       port->type = old_type;
-                       port->hub6 = old_hub6;
-                       port->iotype = old_iotype;
-                       port->regshift = old_shift;
-                       port->mapbase = old_mapbase;
-                       retval = port->ops->request_port(port);
-                       if (retval)
-                               port->type = PORT_UNKNOWN;
-
-                       retval = -EBUSY;
-               }
-       }
-
-       port->irq              = new_serial.irq;
-       port->uartclk          = new_serial.baud_base * 16;
-       port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
-               (new_flags & UPF_CHANGE_MASK);
-       port->custom_divisor   = new_serial.custom_divisor;
-       state->close_delay     = new_serial.close_delay;
-       state->closing_wait    = closing_wait;
-       port->fifosize         = new_serial.xmit_fifo_size;
-       if (state->info->tty)
-               state->info->tty->low_latency =
-                       (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-
-check_and_exit:
-       retval = 0;
-       if (port->type == PORT_UNKNOWN)
-               goto exit;
-       if (state->info->flags & UIF_INITIALIZED) {
-               if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
-                               old_custom_divisor != port->custom_divisor) {
-                       if (port->flags & UPF_SPD_MASK) {
-                               printk(KERN_NOTICE
-                                               "%s sets custom speed on ttyMP%d. This "
-                                               "is deprecated.\n", current->comm,
-                                               port->line);
-                       }
-                       mp_change_speed(state, NULL);
-               }
-       } else
-               retval = mp_startup(state, 1);
-exit:
-       MP_STATE_UNLOCK(state);
-       return retval;
-}
-
-
-static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value)
-{
-       struct sb_uart_port *port = state->port;
-       unsigned int result;
-
-       result = port->ops->tx_empty(port);
-
-       if (port->x_char ||
-                       ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
-                               !state->info->tty->stopped && !state->info->tty->hw_stopped))
-               result &= ~TIOCSER_TEMT;
-
-       return put_user(result, value);
-}
-
-static int mp_tiocmget(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-       int result = -EIO;
-
-       MP_STATE_LOCK(state);
-       if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-               result = port->mctrl;
-               spin_lock_irq(&port->lock);
-               result |= port->ops->get_mctrl(port);
-               spin_unlock_irq(&port->lock);
-       }
-       MP_STATE_UNLOCK(state);
-       return result;
-}
-
-static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-       int ret = -EIO;
-
-
-       MP_STATE_LOCK(state);
-       if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-               mp_update_mctrl(port, set, clear);
-               ret = 0;
-       }
-       MP_STATE_UNLOCK(state);
-
-       return ret;
-}
-
-static int mp_break_ctl(struct tty_struct *tty, int break_state)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-
-       MP_STATE_LOCK(state);
-
-       if (port->type != PORT_UNKNOWN)
-               port->ops->break_ctl(port, break_state);
-
-       MP_STATE_UNLOCK(state);
-       return 0;
-}
-
-static int mp_do_autoconfig(struct sb_uart_state *state)
-{
-       struct sb_uart_port *port = state->port;
-       int flags, ret;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       if (mutex_lock_interruptible(&state->mutex))
-               return -ERESTARTSYS;
-       ret = -EBUSY;
-       if (uart_users(state) == 1) {
-               mp_shutdown(state);
-
-               if (port->type != PORT_UNKNOWN)
-                       port->ops->release_port(port);
-
-               flags = UART_CONFIG_TYPE;
-               if (port->flags & UPF_AUTO_IRQ)
-                       flags |= UART_CONFIG_IRQ;
-
-               port->ops->config_port(port, flags);
-
-               ret = mp_startup(state, 1);
-       }
-       MP_STATE_UNLOCK(state);
-       return ret;
-}
-
-static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg)
-{
-       struct sb_uart_port *port = state->port;
-       DECLARE_WAITQUEUE(wait, current);
-       struct sb_uart_icount cprev, cnow;
-       int ret;
-
-       spin_lock_irq(&port->lock);
-       memcpy(&cprev, &port->icount, sizeof(struct sb_uart_icount));
-
-       port->ops->enable_ms(port);
-       spin_unlock_irq(&port->lock);
-
-       add_wait_queue(&state->info->delta_msr_wait, &wait);
-       for (;;) {
-               spin_lock_irq(&port->lock);
-               memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
-               spin_unlock_irq(&port->lock);
-
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               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))) {
-                       ret = 0;
-                       break;
-               }
-
-               schedule();
-
-               if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
-                       break;
-               }
-
-               cprev = cnow;
-       }
-
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&state->info->delta_msr_wait, &wait);
-
-       return ret;
-}
-
-static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt)
-{
-       struct serial_icounter_struct icount = {};
-       struct sb_uart_icount cnow;
-       struct sb_uart_port *port = state->port;
-
-       spin_lock_irq(&port->lock);
-       memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
-       spin_unlock_irq(&port->lock);
-
-       icount.cts         = cnow.cts;
-       icount.dsr         = cnow.dsr;
-       icount.rng         = cnow.rng;
-       icount.dcd         = cnow.dcd;
-       icount.rx          = cnow.rx;
-       icount.tx          = cnow.tx;
-       icount.frame       = cnow.frame;
-       icount.overrun     = cnow.overrun;
-       icount.parity      = cnow.parity;
-       icount.brk         = cnow.brk;
-       icount.buf_overrun = cnow.buf_overrun;
-
-       return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
-}
-
-static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct mp_port *info = (struct mp_port *)state->port;
-       int ret = -ENOIOCTLCMD;
-
-
-       switch (cmd) {
-               case TIOCSMULTIDROP:
-                       /* set multi-drop mode enable or disable, and default operation mode is H/W mode */
-                       if (info->port.type == PORT_16C105XA)
-                       {
-                               //arg &= ~0x6;
-                               //state->port->mdmode = 0;
-                               return set_multidrop_mode((struct sb_uart_port *)info, (unsigned int)arg);
-                       }
-                       ret = -ENOTSUPP;
-                       break;
-               case GETDEEPFIFO:
-                       ret = get_deep_fifo(state->port);
-                       return ret;
-               case SETDEEPFIFO:
-                       ret = set_deep_fifo(state->port,arg);
-                       deep[state->port->line] = arg;
-                       return ret;
-               case SETTTR:
-                       if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-                               ret = sb1054_set_register(state->port,PAGE_4,SB105X_TTR,arg);
-                               ttr[state->port->line] = arg;
-                       }
-                       return ret;
-               case SETRTR:
-                       if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-                               ret = sb1054_set_register(state->port,PAGE_4,SB105X_RTR,arg);
-                               rtr[state->port->line] = arg;
-                       }
-                       return ret;
-               case GETTTR:
-                       if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-                               ret = sb1054_get_register(state->port,PAGE_4,SB105X_TTR);
-                       }
-                       return ret;
-               case GETRTR:
-                       if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-                               ret = sb1054_get_register(state->port,PAGE_4,SB105X_RTR);
-                       }
-                       return ret;
-
-               case SETFCR:
-                       if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-                               ret = sb1054_set_register(state->port,PAGE_1,SB105X_FCR,arg);
-                       }
-                       else{
-                               serial_out(info,2,arg);
-                       }
-
-                       return ret;
-               case TIOCSMDADDR:
-                       /* set multi-drop address */
-                       if (info->port.type == PORT_16C105XA)
-                       {
-                               state->port->mdmode |= MDMODE_ADDR;
-                               return set_multidrop_addr((struct sb_uart_port *)info, (unsigned int)arg);
-                       }
-                       ret = -ENOTSUPP;
-                       break;
-
-               case TIOCGMDADDR:
-                       /* set multi-drop address */
-                       if ((info->port.type == PORT_16C105XA) && (state->port->mdmode & MDMODE_ADDR))
-                       {
-                               return get_multidrop_addr((struct sb_uart_port *)info);
-                       }
-                       ret = -ENOTSUPP;
-                       break;
-
-               case TIOCSENDADDR:
-                       /* send address in multi-drop mode */
-                       if ((info->port.type == PORT_16C105XA) 
-                                       && (state->port->mdmode & (MDMODE_ENABLE)))
-                       {
-                               if (mp_chars_in_buffer(tty) > 0)
-                               {
-                                       tty_wait_until_sent(tty, 0);
-                               }
-                               //while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
-                               //while (sb1054_get_register(state->port, PAGE_2, SB105X_TFCR) != 0);
-                               while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
-                               serial_out(info, UART_SCR, (int)arg);
-                       }
-                       break;
-
-               case TIOCGSERIAL:
-                       ret = mp_get_info(state, (struct serial_struct *)arg);
-                       break;
-
-               case TIOCSSERIAL:
-                       ret = mp_set_info(state, (struct serial_struct *)arg);
-                       break;
-
-               case TIOCSERCONFIG:
-                       ret = mp_do_autoconfig(state);
-                       break;
-
-               case TIOCSERGWILD: /* obsolete */
-               case TIOCSERSWILD: /* obsolete */
-                       ret = 0;
-                       break;
-                       /* for Multiport */
-               case TIOCGNUMOFPORT: /* Get number of ports */
-                       return NR_PORTS;
-               case TIOCGGETDEVID:
-                       return mp_devs[arg].device_id;
-               case TIOCGGETREV:
-                       return mp_devs[arg].revision;
-               case TIOCGGETNRPORTS:
-                       return mp_devs[arg].nr_ports;
-               case TIOCGGETBDNO:
-                       return NR_BOARD;
-               case TIOCGGETINTERFACE:
-                       if (mp_devs[arg].revision == 0xc0)
-                       {
-                               /* for SB16C1053APCI */
-                               return (sb1053a_get_interface(info, info->port.line));
-                       }
-                       else
-                       {
-                               return (inb(mp_devs[arg].option_reg_addr+MP_OPTR_IIR0+(state->port->line/8)));
-                       }
-               case TIOCGGETPORTTYPE:
-                       ret = get_device_type(arg);
-                       return ret;
-               case TIOCSMULTIECHO: /* set to multi-drop mode(RS422) or echo mode(RS485)*/
-                       outb( ( inb(info->interface_config_addr) & ~0x03 ) | 0x01 ,  
-                                       info->interface_config_addr);
-                       return 0;
-               case TIOCSPTPNOECHO: /* set to multi-drop mode(RS422) or echo mode(RS485) */
-                       outb( ( inb(info->interface_config_addr) & ~0x03 )  ,             
-                                       info->interface_config_addr);
-                       return 0;
-       }
-
-       if (ret != -ENOIOCTLCMD)
-               goto out;
-
-       if (tty->flags & (1 << TTY_IO_ERROR)) {
-               ret = -EIO;
-               goto out;
-       }
-
-       switch (cmd) {
-               case TIOCMIWAIT:
-                       ret = mp_wait_modem_status(state, arg);
-                       break;
-
-               case TIOCGICOUNT:
-                       ret = mp_get_count(state, (struct serial_icounter_struct *)arg);
-                       break;
-       }
-
-       if (ret != -ENOIOCTLCMD)
-               goto out;
-
-       MP_STATE_LOCK(state);
-       switch (cmd) {
-               case TIOCSERGETLSR: /* Get line status register */
-                       ret = mp_get_lsr_info(state, (unsigned int *)arg);
-                       break;
-
-               default: {
-                                       struct sb_uart_port *port = state->port;
-                                       if (port->ops->ioctl)
-                                               ret = port->ops->ioctl(port, cmd, arg);
-                                       break;
-                               }
-       }
-
-       MP_STATE_UNLOCK(state);
-out:
-       return ret;
-}
-
-static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       unsigned long flags;
-       unsigned int cflag = tty->termios.c_cflag;
-
-#define RELEVANT_IFLAG(iflag)  ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-       if ((cflag ^ old_termios->c_cflag) == 0 &&
-                       RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0)
-               return;
-
-       mp_change_speed(state, old_termios);
-
-       if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-               uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
-
-       if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-               unsigned int mask = TIOCM_DTR;
-               if (!(cflag & CRTSCTS) ||
-                               !test_bit(TTY_THROTTLED, &tty->flags))
-                       mask |= TIOCM_RTS;
-               uart_set_mctrl(state->port, mask);
-       }
-
-       if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-               spin_lock_irqsave(&state->port->lock, flags);
-               tty->hw_stopped = 0;
-               __mp_start(tty);
-               spin_unlock_irqrestore(&state->port->lock, flags);
-       }
-
-       if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
-               spin_lock_irqsave(&state->port->lock, flags);
-               if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) {
-                       tty->hw_stopped = 1;
-                       state->port->ops->stop_tx(state->port);
-               }
-               spin_unlock_irqrestore(&state->port->lock, flags);
-       }
-}
-
-static void mp_close(struct tty_struct *tty, struct file *filp)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port;
-
-       printk("mp_close!\n");
-       if (!state || !state->port)
-               return;
-
-       port = state->port;
-
-       printk("close1 %d\n", __LINE__);
-       MP_STATE_LOCK(state);
-
-       printk("close2 %d\n", __LINE__);
-       if (tty_hung_up_p(filp))
-               goto done;
-
-       printk("close3 %d\n", __LINE__);
-       if ((tty->count == 1) && (state->count != 1)) {
-               printk("mp_close: bad serial port count; tty->count is 1, "
-                               "state->count is %d\n", state->count);
-               state->count = 1;
-       }
-       printk("close4 %d\n", __LINE__);
-       if (--state->count < 0) {
-               printk("rs_close: bad serial port count for ttyMP%d: %d\n",
-                               port->line, state->count);
-               state->count = 0;
-       }
-       if (state->count)
-               goto done;
-
-       tty->closing = 1;
-
-       printk("close5 %d\n", __LINE__);
-       if (state->closing_wait != USF_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, state->closing_wait);
-
-       printk("close6 %d\n", __LINE__);
-       if (state->info->flags & UIF_INITIALIZED) {
-               unsigned long flags;
-               spin_lock_irqsave(&port->lock, flags);
-               port->ops->stop_rx(port);
-               spin_unlock_irqrestore(&port->lock, flags);
-               mp_wait_until_sent(tty, port->timeout);
-       }
-       printk("close7 %d\n", __LINE__);
-
-       mp_shutdown(state);
-       printk("close8 %d\n", __LINE__);
-       mp_flush_buffer(tty);
-       tty_ldisc_flush(tty);
-       tty->closing = 0;
-       state->info->tty = NULL;
-       if (state->info->blocked_open) 
-       {
-               if (state->close_delay)
-               {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(state->close_delay);
-               }
-       }
-       else
-       {
-               mp_change_pm(state, 3);
-       }
-       printk("close8 %d\n", __LINE__);
-
-       state->info->flags &= ~UIF_NORMAL_ACTIVE;
-       wake_up_interruptible(&state->info->open_wait);
-
-done:
-       printk("close done\n");
-       MP_STATE_UNLOCK(state);
-       module_put(THIS_MODULE);
-}
-
-static void mp_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-       struct sb_uart_state *state = tty->driver_data;
-       struct sb_uart_port *port = state->port;
-       unsigned long char_time, expire;
-
-       if (port->type == PORT_UNKNOWN || port->fifosize == 0)
-               return;
-
-       char_time = (port->timeout - HZ/50) / port->fifosize;
-       char_time = char_time / 5;
-       if (char_time == 0)
-               char_time = 1;
-       if (timeout && timeout < char_time)
-               char_time = timeout;
-
-       if (timeout == 0 || timeout > 2 * port->timeout)
-               timeout = 2 * port->timeout;
-
-       expire = jiffies + timeout;
-
-       while (!port->ops->tx_empty(port)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(char_time);
-               if (signal_pending(current))
-                       break;
-               if (time_after(jiffies, expire))
-                       break;
-       }
-       set_current_state(TASK_RUNNING); /* might not be needed */
-}
-
-static void mp_hangup(struct tty_struct *tty)
-{
-       struct sb_uart_state *state = tty->driver_data;
-
-       MP_STATE_LOCK(state);
-       if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
-               mp_flush_buffer(tty);
-               mp_shutdown(state);
-               state->count = 0;
-               state->info->flags &= ~UIF_NORMAL_ACTIVE;
-               state->info->tty = NULL;
-               wake_up_interruptible(&state->info->open_wait);
-               wake_up_interruptible(&state->info->delta_msr_wait);
-       }
-       MP_STATE_UNLOCK(state);
-}
-
-static void mp_update_termios(struct sb_uart_state *state)
-{
-       struct tty_struct *tty = state->info->tty;
-       struct sb_uart_port *port = state->port;
-
-       if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-               mp_change_speed(state, NULL);
-
-               if (tty->termios.c_cflag & CBAUD)
-                       uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-       }
-}
-
-static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       struct sb_uart_info *info = state->info;
-       struct sb_uart_port *port = state->port;
-       unsigned int mctrl;
-
-       info->blocked_open++;
-       state->count--;
-
-       add_wait_queue(&info->open_wait, &wait);
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               if (tty_hung_up_p(filp) || info->tty == NULL)
-                       break;
-
-               if (!(info->flags & UIF_INITIALIZED))
-                       break;
-
-               if ((filp->f_flags & O_NONBLOCK) ||
-                               (info->tty->termios.c_cflag & CLOCAL) ||
-                               (info->tty->flags & (1 << TTY_IO_ERROR))) {
-                       break;
-               }
-
-               if (info->tty->termios.c_cflag & CBAUD)
-                       uart_set_mctrl(port, TIOCM_DTR);
-
-               spin_lock_irq(&port->lock);
-               port->ops->enable_ms(port);
-               mctrl = port->ops->get_mctrl(port);
-               spin_unlock_irq(&port->lock);
-               if (mctrl & TIOCM_CAR)
-                       break;
-
-               MP_STATE_UNLOCK(state);
-               schedule();
-               MP_STATE_LOCK(state);
-
-               if (signal_pending(current))
-                       break;
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&info->open_wait, &wait);
-
-       state->count++;
-       info->blocked_open--;
-
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       if (!info->tty || tty_hung_up_p(filp))
-               return -EAGAIN;
-
-       return 0;
-}
-
-static struct sb_uart_state *uart_get(struct uart_driver *drv, int line)
-{
-       struct sb_uart_state *state;
-
-       MP_MUTEX_LOCK(mp_mutex);
-       state = drv->state + line;
-       if (mutex_lock_interruptible(&state->mutex)) {
-               state = ERR_PTR(-ERESTARTSYS);
-               goto out;
-       }
-       state->count++;
-       if (!state->port) {
-               state->count--;
-               MP_STATE_UNLOCK(state);
-               state = ERR_PTR(-ENXIO);
-               goto out;
-       }
-
-       if (!state->info) {
-               state->info = kmalloc(sizeof(struct sb_uart_info), GFP_KERNEL);
-               if (state->info) {
-                       memset(state->info, 0, sizeof(struct sb_uart_info));
-                       init_waitqueue_head(&state->info->open_wait);
-                       init_waitqueue_head(&state->info->delta_msr_wait);
-
-                       state->port->info = state->info;
-
-                       tasklet_init(&state->info->tlet, mp_tasklet_action,
-                                       (unsigned long)state);
-               } else {
-                       state->count--;
-                       MP_STATE_UNLOCK(state);
-                       state = ERR_PTR(-ENOMEM);
-               }
-       }
-
-out:
-       MP_MUTEX_UNLOCK(mp_mutex);
-       return state;
-}
-
-static int mp_open(struct tty_struct *tty, struct file *filp)
-{
-       struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
-       struct sb_uart_state *state;
-       int retval;
-       int  line = tty->index;
-       struct mp_port *mtpt;
-
-       retval = -ENODEV;
-       if (line >= tty->driver->num)
-               goto fail;
-
-       state = uart_get(drv, line);
-
-       if (IS_ERR(state)) {
-               retval = PTR_ERR(state);
-               goto fail;
-       }
-
-       mtpt  = (struct mp_port *)state->port;
-
-       tty->driver_data = state;
-       tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-       tty->alt_speed = 0;
-       state->info->tty = tty;
-
-       if (tty_hung_up_p(filp)) {
-               retval = -EAGAIN;
-               state->count--;
-               MP_STATE_UNLOCK(state);
-               goto fail;
-       }
-
-       if (state->count == 1)
-               mp_change_pm(state, 0);
-
-       retval = mp_startup(state, 0);
-
-       if (retval == 0)
-               retval = mp_block_til_ready(filp, state);
-       MP_STATE_UNLOCK(state);
-
-       if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) {
-               state->info->flags |= UIF_NORMAL_ACTIVE;
-
-               mp_update_termios(state);
-       }
-
-       uart_clear_mctrl(state->port, TIOCM_RTS);
-       try_module_get(THIS_MODULE);
-fail:
-       return retval;
-}
-
-
-static const char *mp_type(struct sb_uart_port *port)
-{
-       const char *str = NULL;
-
-       if (port->ops->type)
-               str = port->ops->type(port);
-
-       if (!str)
-               str = "unknown";
-
-       return str;
-}
-
-static void mp_change_pm(struct sb_uart_state *state, int pm_state)
-{
-       struct sb_uart_port *port = state->port;
-       if (port->ops->pm)
-               port->ops->pm(port, pm_state, state->pm_state);
-       state->pm_state = pm_state;
-}
-
-static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-       char address[64];
-
-       switch (port->iotype) {
-               case UPIO_PORT:
-                       snprintf(address, sizeof(address),"I/O 0x%x", port->iobase);
-                       break;
-               case UPIO_HUB6:
-                       snprintf(address, sizeof(address),"I/O 0x%x offset 0x%x", port->iobase, port->hub6);
-                       break;
-               case UPIO_MEM:
-                       snprintf(address, sizeof(address),"MMIO 0x%lx", port->mapbase);
-                       break;
-               default:
-                       snprintf(address, sizeof(address),"*unknown*" );
-                       strlcpy(address, "*unknown*", sizeof(address));
-                       break;
-       }
-
-       printk( "%s%d at %s (irq = %d) is a %s\n",
-                       drv->dev_name, port->line, address, port->irq, mp_type(port));
-
-}
-
-static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port)
-{
-       unsigned int flags;
-
-
-       if (!port->iobase && !port->mapbase && !port->membase)
-       {
-               DPRINTK("%s error \n",__FUNCTION__);
-               return;
-       }
-       flags = UART_CONFIG_TYPE;
-       if (port->flags & UPF_AUTO_IRQ)
-               flags |= UART_CONFIG_IRQ;
-       if (port->flags & UPF_BOOT_AUTOCONF) {
-               port->type = PORT_UNKNOWN;
-               port->ops->config_port(port, flags);
-       }
-
-       if (port->type != PORT_UNKNOWN) {
-               unsigned long flags;
-
-               mp_report_port(drv, port);
-
-               spin_lock_irqsave(&port->lock, flags);
-               port->ops->set_mctrl(port, 0);
-               spin_unlock_irqrestore(&port->lock, flags);
-
-               mp_change_pm(state, 3);
-       }
-}
-
-static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state)
-{
-       struct sb_uart_port *port = state->port;
-       struct sb_uart_info *info = state->info;
-
-       if (info && info->tty)
-               tty_hangup(info->tty);
-
-       MP_STATE_LOCK(state);
-
-       state->info = NULL;
-
-       if (port->type != PORT_UNKNOWN)
-               port->ops->release_port(port);
-
-       port->type = PORT_UNKNOWN;
-
-       if (info) {
-               tasklet_kill(&info->tlet);
-               kfree(info);
-       }
-
-       MP_STATE_UNLOCK(state);
-}
-static struct tty_operations mp_ops = {
-       .open           = mp_open,
-       .close          = mp_close,
-       .write          = mp_write,
-       .put_char       = mp_put_char,
-       .flush_chars    = mp_put_chars,
-       .write_room     = mp_write_room,
-       .chars_in_buffer= mp_chars_in_buffer,
-       .flush_buffer   = mp_flush_buffer,
-       .ioctl          = mp_ioctl,
-       .throttle       = mp_throttle,
-       .unthrottle     = mp_unthrottle,
-       .send_xchar     = mp_send_xchar,
-       .set_termios    = mp_set_termios,
-       .stop           = mp_stop,
-       .start          = mp_start,
-       .hangup         = mp_hangup,
-       .break_ctl      = mp_break_ctl,
-       .wait_until_sent= mp_wait_until_sent,
-#ifdef CONFIG_PROC_FS
-       .proc_fops      = NULL,
-#endif
-       .tiocmget       = mp_tiocmget,
-       .tiocmset       = mp_tiocmset,
-};
-
-static int mp_register_driver(struct uart_driver *drv)
-{
-       struct tty_driver *normal = NULL;
-       int i, retval;
-
-       drv->state = kmalloc(sizeof(struct sb_uart_state) * drv->nr, GFP_KERNEL);
-       retval = -ENOMEM;
-       if (!drv->state)
-       {
-               printk("SB PCI Error: Kernel memory allocation error!\n");
-               goto out;
-       }
-       memset(drv->state, 0, sizeof(struct sb_uart_state) * drv->nr);
-
-       normal = alloc_tty_driver(drv->nr);
-       if (!normal)
-       {
-               printk("SB PCI Error: tty allocation error!\n");
-               goto out;
-       }
-
-       drv->tty_driver = normal;
-
-       normal->owner           = drv->owner;
-       normal->magic           = TTY_DRIVER_MAGIC;
-       normal->driver_name     = drv->driver_name;
-       normal->name            = drv->dev_name;
-       normal->major           = drv->major;
-       normal->minor_start     = drv->minor;
-
-       normal->num             = MAX_MP_PORT ; 
-
-       normal->type            = TTY_DRIVER_TYPE_SERIAL;
-       normal->subtype         = SERIAL_TYPE_NORMAL;
-       normal->init_termios    = tty_std_termios;
-       normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       normal->flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-       normal->driver_state    = drv;
-
-       tty_set_operations(normal, &mp_ops);
-
-for (i = 0; i < drv->nr; i++) {
-       struct sb_uart_state *state = drv->state + i;
-
-       state->close_delay     = 500;   
-       state->closing_wait    = 30000; 
-
-       mutex_init(&state->mutex);
-       }
-
-       retval = tty_register_driver(normal);
-out:
-       if (retval < 0) {
-               printk("Register tty driver Fail!\n");
-               put_tty_driver(normal);
-               kfree(drv->state);
-       }
-
-       return retval;
-}
-
-void mp_unregister_driver(struct uart_driver *drv)
-{
-    struct tty_driver *normal = NULL;
-
-    normal = drv->tty_driver;
-
-    if (!normal)
-    {
-        return;
-    }
-
-    tty_unregister_driver(normal);
-    put_tty_driver(normal);
-    drv->tty_driver = NULL;
-
-
-    kfree(drv->state);
-
-}
-
-static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-       struct sb_uart_state *state;
-       int ret = 0;
-
-
-       if (port->line >= drv->nr)
-               return -EINVAL;
-
-       state = drv->state + port->line;
-
-       MP_MUTEX_LOCK(mp_mutex);
-       if (state->port) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       state->port = port;
-
-       spin_lock_init(&port->lock);
-       port->cons = drv->cons;
-       port->info = state->info;
-
-       mp_configure_port(drv, state, port);
-
-       tty_register_device(drv->tty_driver, port->line, port->dev);
-
-out:
-       MP_MUTEX_UNLOCK(mp_mutex);
-
-
-       return ret;
-}
-
-static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-       struct sb_uart_state *state = drv->state + port->line;
-
-       if (state->port != port)
-               printk(KERN_ALERT "Removing wrong port: %p != %p\n",
-                               state->port, port);
-
-       MP_MUTEX_LOCK(mp_mutex);
-
-       tty_unregister_device(drv->tty_driver, port->line);
-
-       mp_unconfigure_port(drv, state);
-       state->port = NULL;
-       MP_MUTEX_UNLOCK(mp_mutex);
-
-       return 0;
-}
-
-static void autoconfig(struct mp_port *mtpt, unsigned int probeflags)
-{
-       unsigned char status1, scratch, scratch2, scratch3;
-       unsigned char save_lcr, save_mcr;
-       unsigned long flags;
-
-       unsigned char u_type;
-       unsigned char b_ret = 0;
-
-       if (!mtpt->port.iobase && !mtpt->port.mapbase && !mtpt->port.membase)
-               return;
-
-       DEBUG_AUTOCONF("ttyMP%d: autoconf (0x%04x, 0x%p): ",
-                       mtpt->port.line, mtpt->port.iobase, mtpt->port.membase);
-
-       spin_lock_irqsave(&mtpt->port.lock, flags);
-
-       if (!(mtpt->port.flags & UPF_BUGGY_UART)) {
-               scratch = serial_inp(mtpt, UART_IER);
-               serial_outp(mtpt, UART_IER, 0);
-#ifdef __i386__
-               outb(0xff, 0x080);
-#endif
-               scratch2 = serial_inp(mtpt, UART_IER) & 0x0f;
-               serial_outp(mtpt, UART_IER, 0x0F);
-#ifdef __i386__
-               outb(0, 0x080);
-#endif
-               scratch3 = serial_inp(mtpt, UART_IER) & 0x0F;
-               serial_outp(mtpt, UART_IER, scratch);
-               if (scratch2 != 0 || scratch3 != 0x0F) {
-                       DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-                                       scratch2, scratch3);
-                       goto out;
-               }
-       }
-
-       save_mcr = serial_in(mtpt, UART_MCR);
-       save_lcr = serial_in(mtpt, UART_LCR);
-
-       if (!(mtpt->port.flags & UPF_SKIP_TEST)) {
-               serial_outp(mtpt, UART_MCR, UART_MCR_LOOP | 0x0A);
-               status1 = serial_inp(mtpt, UART_MSR) & 0xF0;
-               serial_outp(mtpt, UART_MCR, save_mcr);
-               if (status1 != 0x90) {
-                       DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-                                       status1);
-                       goto out;
-               }
-       }
-
-       serial_outp(mtpt, UART_LCR, 0xBF);
-       serial_outp(mtpt, UART_EFR, 0);
-       serial_outp(mtpt, UART_LCR, 0);
-
-       serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-       scratch = serial_in(mtpt, UART_IIR) >> 6;
-
-       DEBUG_AUTOCONF("iir=%d ", scratch);
-       if(mtpt->device->nr_ports >= 8)
-               b_ret = read_option_register(mtpt,(MP_OPTR_DIR0 + ((mtpt->port.line)/8)));
-       else    
-               b_ret = read_option_register(mtpt,MP_OPTR_DIR0);
-       u_type = (b_ret & 0xf0) >> 4;
-       if(mtpt->port.type == PORT_UNKNOWN )
-       {
-               switch (u_type)
-               {
-                       case DIR_UART_16C550:
-                               mtpt->port.type = PORT_16C55X;
-                               break;
-                       case DIR_UART_16C1050:
-                               mtpt->port.type = PORT_16C105X;
-                               break;
-                       case DIR_UART_16C1050A:
-                               if (mtpt->port.line < 2)
-                               {
-                                       mtpt->port.type = PORT_16C105XA;
-                               }
-                               else
-                               {
-                                       if (mtpt->device->device_id & 0x50)
-                                       {
-                                               mtpt->port.type = PORT_16C55X;
-                                       }
-                                       else
-                                       {
-                                               mtpt->port.type = PORT_16C105X;
-                                       }
-                               }
-                               break;
-                       default:        
-                               mtpt->port.type = PORT_UNKNOWN;
-                               break;
-               }
-       }
-
-       if(mtpt->port.type == PORT_UNKNOWN )
-       {
-printk("unknow2\n");
-               switch (scratch) {
-                       case 0:
-                       case 1:
-                               mtpt->port.type = PORT_UNKNOWN;
-                               break;
-                       case 2:
-                       case 3:
-                               mtpt->port.type = PORT_16C55X;
-                               break;
-               }
-       }
-
-       serial_outp(mtpt, UART_LCR, save_lcr);
-
-       mtpt->port.fifosize = uart_config[mtpt->port.type].dfl_xmit_fifo_size;
-       mtpt->capabilities = uart_config[mtpt->port.type].flags;
-
-       if (mtpt->port.type == PORT_UNKNOWN)
-               goto out;
-       serial_outp(mtpt, UART_MCR, save_mcr);
-       serial_outp(mtpt, UART_FCR, (UART_FCR_ENABLE_FIFO |
-                               UART_FCR_CLEAR_RCVR |
-                               UART_FCR_CLEAR_XMIT));
-       serial_outp(mtpt, UART_FCR, 0);
-       (void)serial_in(mtpt, UART_RX);
-       serial_outp(mtpt, UART_IER, 0);
-
-out:
-       spin_unlock_irqrestore(&mtpt->port.lock, flags);
-       DEBUG_AUTOCONF("type=%s\n", uart_config[mtpt->port.type].name);
-}
-
-static void autoconfig_irq(struct mp_port *mtpt)
-{
-       unsigned char save_mcr, save_ier;
-       unsigned long irqs;
-       int irq;
-
-       /* forget possible initially masked and pending IRQ */
-       probe_irq_off(probe_irq_on());
-       save_mcr = serial_inp(mtpt, UART_MCR);
-       save_ier = serial_inp(mtpt, UART_IER);
-       serial_outp(mtpt, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
-       irqs = probe_irq_on();
-       serial_outp(mtpt, UART_MCR, 0);
-       serial_outp(mtpt, UART_MCR,
-               UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-
-       serial_outp(mtpt, UART_IER, 0x0f);    /* enable all intrs */
-       (void)serial_inp(mtpt, UART_LSR);
-       (void)serial_inp(mtpt, UART_RX);
-       (void)serial_inp(mtpt, UART_IIR);
-       (void)serial_inp(mtpt, UART_MSR);
-       serial_outp(mtpt, UART_TX, 0xFF);
-       irq = probe_irq_off(irqs);
-
-       serial_outp(mtpt, UART_MCR, save_mcr);
-       serial_outp(mtpt, UART_IER, save_ier);
-
-       mtpt->port.irq = (irq > 0) ? irq : 0;
-}
-
-static void multi_stop_tx(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-
-       if (mtpt->ier & UART_IER_THRI) {
-               mtpt->ier &= ~UART_IER_THRI;
-               serial_out(mtpt, UART_IER, mtpt->ier);
-       }
-
-       tasklet_schedule(&port->info->tlet);
-}
-
-static void multi_start_tx(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-
-       if (!(mtpt->ier & UART_IER_THRI)) {
-               mtpt->ier |= UART_IER_THRI;
-               serial_out(mtpt, UART_IER, mtpt->ier);
-       }
-}
-
-static void multi_stop_rx(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-
-       mtpt->ier &= ~UART_IER_RLSI;
-       mtpt->port.read_status_mask &= ~UART_LSR_DR;
-       serial_out(mtpt, UART_IER, mtpt->ier);
-}
-
-static void multi_enable_ms(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-
-       mtpt->ier |= UART_IER_MSI;
-       serial_out(mtpt, UART_IER, mtpt->ier);
-}
-
-
-static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status )
-{
-       struct tty_struct *tty = mtpt->port.info->tty;
-       unsigned char lsr = *status;
-       int max_count = 256;
-       unsigned char ch;
-       char flag;
-
-       //lsr &= mtpt->port.read_status_mask;
-
-       do {
-               if ((lsr & UART_LSR_PE) && (mtpt->port.mdmode & MDMODE_ENABLE))
-               {
-                       ch = serial_inp(mtpt, UART_RX);
-               }
-               else if (lsr & UART_LSR_SPECIAL) 
-               {
-                       flag = 0;
-                       ch = serial_inp(mtpt, UART_RX);
-
-                       if (lsr & UART_LSR_BI) 
-                       {
-
-                               mtpt->port.icount.brk++;
-                               flag = TTY_BREAK;
-
-                               if (sb_uart_handle_break(&mtpt->port))
-                                       goto ignore_char;
-                       } 
-                       if (lsr & UART_LSR_PE)
-                       {
-                               mtpt->port.icount.parity++;
-                               flag = TTY_PARITY;
-                       }
-                       if (lsr & UART_LSR_FE)
-                       {
-                               mtpt->port.icount.frame++;
-                               flag = TTY_FRAME;
-                       }
-                       if (lsr & UART_LSR_OE)
-                       {
-                               mtpt->port.icount.overrun++;
-                               flag = TTY_OVERRUN;
-                       }
-                       tty_insert_flip_char(tty, ch, flag);
-               }
-               else
-               {
-                       ch = serial_inp(mtpt, UART_RX);
-                       tty_insert_flip_char(tty, ch, 0);
-               }
-ignore_char:
-               lsr = serial_inp(mtpt, UART_LSR);
-       } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
-
-       tty_flip_buffer_push(tty);
-}
-
-
-
-
-static _INLINE_ void transmit_chars(struct mp_port *mtpt)
-{
-       struct circ_buf *xmit = &mtpt->port.info->xmit;
-       int count;
-
-       if (mtpt->port.x_char) {
-               serial_outp(mtpt, UART_TX, mtpt->port.x_char);
-               mtpt->port.icount.tx++;
-               mtpt->port.x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&mtpt->port)) {
-               multi_stop_tx(&mtpt->port);
-               return;
-       }
-
-       count = uart_circ_chars_pending(xmit);
-
-       if(count > mtpt->port.fifosize)
-       {
-               count = mtpt->port.fifosize;
-       }
-
-       printk("[%d] mdmode: %x\n", mtpt->port.line, mtpt->port.mdmode);
-       do {
-#if 0
-               /* check multi-drop mode */
-               if ((mtpt->port.mdmode & (MDMODE_ENABLE | MDMODE_ADDR)) == (MDMODE_ENABLE | MDMODE_ADDR))
-               {
-                       printk("send address\n");
-                       /* send multi-drop address */
-                       serial_out(mtpt, UART_SCR, xmit->buf[xmit->tail]);
-               }
-               else
-#endif
-               {
-                       serial_out(mtpt, UART_TX, xmit->buf[xmit->tail]);
-               }
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               mtpt->port.icount.tx++;
-       } while (--count > 0);
-}
-
-
-
-static _INLINE_ void check_modem_status(struct mp_port *mtpt)
-{
-       int status;
-
-       status = serial_in(mtpt, UART_MSR);
-
-       if ((status & UART_MSR_ANY_DELTA) == 0)
-               return;
-
-       if (status & UART_MSR_TERI)
-               mtpt->port.icount.rng++;
-       if (status & UART_MSR_DDSR)
-               mtpt->port.icount.dsr++;
-       if (status & UART_MSR_DDCD)
-               sb_uart_handle_dcd_change(&mtpt->port, status & UART_MSR_DCD);
-       if (status & UART_MSR_DCTS)
-               sb_uart_handle_cts_change(&mtpt->port, status & UART_MSR_CTS);
-
-       wake_up_interruptible(&mtpt->port.info->delta_msr_wait);
-}
-
-static inline void multi_handle_port(struct mp_port *mtpt)
-{
-       unsigned int status = serial_inp(mtpt, UART_LSR);
-
-       //printk("lsr: %x\n", status);
-
-       if ((status & UART_LSR_DR) || (status & UART_LSR_SPECIAL))
-               receive_chars(mtpt, &status);
-       check_modem_status(mtpt);
-       if (status & UART_LSR_THRE)
-       {
-               if ((mtpt->port.type == PORT_16C105X)
-                       || (mtpt->port.type == PORT_16C105XA))
-                       transmit_chars(mtpt);
-               else
-               {
-                       if (mtpt->interface >= RS485NE)
-                               uart_set_mctrl(&mtpt->port, TIOCM_RTS);
-                       
-                       transmit_chars(mtpt);
-
-
-                       if (mtpt->interface >= RS485NE)
-                       {
-                               while((status=serial_in(mtpt,UART_LSR) &0x60)!=0x60);
-                               uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
-                       }
-               }
-       }
-}
-
-
-
-static irqreturn_t multi_interrupt(int irq, void *dev_id)
-{
-       struct irq_info *iinfo = dev_id;
-       struct list_head *lhead, *end = NULL;
-       int pass_counter = 0;
-
-
-       spin_lock(&iinfo->lock);
-
-       lhead = iinfo->head;
-       do {
-               struct mp_port *mtpt;
-               unsigned int iir;
-
-               mtpt = list_entry(lhead, struct mp_port, list);
-               
-               iir = serial_in(mtpt, UART_IIR);
-               printk("interrupt! port %d, iir 0x%x\n", mtpt->port.line, iir); //wlee
-               if (!(iir & UART_IIR_NO_INT)) 
-               {
-                       printk("interrupt handle\n");
-                       spin_lock(&mtpt->port.lock);
-                       multi_handle_port(mtpt);
-                       spin_unlock(&mtpt->port.lock);
-
-                       end = NULL;
-               } else if (end == NULL)
-                       end = lhead;
-
-               lhead = lhead->next;
-               if (lhead == iinfo->head && pass_counter++ > PASS_LIMIT) 
-               {
-                       printk(KERN_ERR "multi: too much work for "
-                                       "irq%d\n", irq);
-                       printk( "multi: too much work for "
-                                       "irq%d\n", irq);
-                       break;
-               }
-       } while (lhead != end);
-
-       spin_unlock(&iinfo->lock);
-
-
-        return IRQ_HANDLED;
-}
-
-static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt)
-{
-       spin_lock_irq(&i->lock);
-
-       if (!list_empty(i->head)) {
-               if (i->head == &mtpt->list)
-                       i->head = i->head->next;
-               list_del(&mtpt->list);
-       } else {
-               i->head = NULL;
-       }
-
-       spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct mp_port *mtpt)
-{
-       struct irq_info *i = irq_lists + mtpt->port.irq;
-       int ret, irq_flags = mtpt->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-       spin_lock_irq(&i->lock);
-
-       if (i->head) {
-               list_add(&mtpt->list, i->head);
-               spin_unlock_irq(&i->lock);
-
-               ret = 0;
-       } else {
-               INIT_LIST_HEAD(&mtpt->list);
-               i->head = &mtpt->list;
-               spin_unlock_irq(&i->lock);
-
-               ret = request_irq(mtpt->port.irq, multi_interrupt,
-                               irq_flags, "serial", i);
-               if (ret < 0)
-                       serial_do_unlink(i, mtpt);
-       }
-
-       return ret;
-}
-
-
-
-
-static void serial_unlink_irq_chain(struct mp_port *mtpt)
-{
-       struct irq_info *i = irq_lists + mtpt->port.irq;
-
-       if (list_empty(i->head))
-       {
-               free_irq(mtpt->port.irq, i);
-       }
-       serial_do_unlink(i, mtpt);
-}
-
-static void multi_timeout(unsigned long data)
-{
-       struct mp_port *mtpt = (struct mp_port *)data;
-
-
-       spin_lock(&mtpt->port.lock);
-       multi_handle_port(mtpt);
-       spin_unlock(&mtpt->port.lock);
-
-       mod_timer(&mtpt->timer, jiffies+1 );
-}
-
-static unsigned int multi_tx_empty(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned long flags;
-       unsigned int ret;
-
-       spin_lock_irqsave(&mtpt->port.lock, flags);
-       ret = serial_in(mtpt, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-       spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-       return ret;
-}
-
-
-static unsigned int multi_get_mctrl(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned char status;
-       unsigned int ret;
-
-       status = serial_in(mtpt, UART_MSR);
-
-       ret = 0;
-       if (status & UART_MSR_DCD)
-               ret |= TIOCM_CAR;
-       if (status & UART_MSR_RI)
-               ret |= TIOCM_RNG;
-       if (status & UART_MSR_DSR)
-               ret |= TIOCM_DSR;
-       if (status & UART_MSR_CTS)
-               ret |= TIOCM_CTS;
-       return ret;
-}
-
-static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned char mcr = 0;
-
-       mctrl &= 0xff;
-
-       if (mctrl & TIOCM_RTS)
-               mcr |= UART_MCR_RTS;
-       if (mctrl & TIOCM_DTR)
-               mcr |= UART_MCR_DTR;
-       if (mctrl & TIOCM_OUT1)
-               mcr |= UART_MCR_OUT1;
-       if (mctrl & TIOCM_OUT2)
-               mcr |= UART_MCR_OUT2;
-       if (mctrl & TIOCM_LOOP)
-               mcr |= UART_MCR_LOOP;
-
-
-       serial_out(mtpt, UART_MCR, mcr);
-}
-
-
-static void multi_break_ctl(struct sb_uart_port *port, int break_state)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned long flags;
-
-       spin_lock_irqsave(&mtpt->port.lock, flags);
-       if (break_state == -1)
-               mtpt->lcr |= UART_LCR_SBC;
-       else
-               mtpt->lcr &= ~UART_LCR_SBC;
-       serial_out(mtpt, UART_LCR, mtpt->lcr);
-       spin_unlock_irqrestore(&mtpt->port.lock, flags);
-}
-
-
-
-static int multi_startup(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned long flags;
-       int retval;
-
-       mtpt->capabilities = uart_config[mtpt->port.type].flags;
-       mtpt->mcr = 0;
-
-       if (mtpt->capabilities & UART_CLEAR_FIFO) {
-               serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-               serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
-                               UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-               serial_outp(mtpt, UART_FCR, 0);
-       }
-
-       (void) serial_inp(mtpt, UART_LSR);
-       (void) serial_inp(mtpt, UART_RX);
-       (void) serial_inp(mtpt, UART_IIR);
-       (void) serial_inp(mtpt, UART_MSR);
-       //test-wlee 9-bit disable
-       serial_outp(mtpt, UART_MSR, 0);
-
-
-       if (!(mtpt->port.flags & UPF_BUGGY_UART) &&
-                       (serial_inp(mtpt, UART_LSR) == 0xff)) {
-               printk("ttyS%d: LSR safety check engaged!\n", mtpt->port.line);
-               //return -ENODEV;
-       }
-
-       if ((!is_real_interrupt(mtpt->port.irq)) || (mtpt->poll_type==TYPE_POLL)) {
-               unsigned int timeout = mtpt->port.timeout;
-
-               timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
-               mtpt->timer.data = (unsigned long)mtpt;
-               mod_timer(&mtpt->timer, jiffies + timeout);
-       } 
-       else 
-       {
-               retval = serial_link_irq_chain(mtpt);
-               if (retval)
-                       return retval;
-       }
-
-       serial_outp(mtpt, UART_LCR, UART_LCR_WLEN8);
-
-       spin_lock_irqsave(&mtpt->port.lock, flags);
-       if ((is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_INTERRUPT))
-               mtpt->port.mctrl |= TIOCM_OUT2;
-
-       multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-       spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-       
-       mtpt->ier = UART_IER_RLSI | UART_IER_RDI;
-       serial_outp(mtpt, UART_IER, mtpt->ier);
-
-       (void) serial_inp(mtpt, UART_LSR);
-       (void) serial_inp(mtpt, UART_RX);
-       (void) serial_inp(mtpt, UART_IIR);
-       (void) serial_inp(mtpt, UART_MSR);
-
-       return 0;
-}
-
-
-
-static void multi_shutdown(struct sb_uart_port *port)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned long flags;
-
-
-       mtpt->ier = 0;
-       serial_outp(mtpt, UART_IER, 0);
-
-       spin_lock_irqsave(&mtpt->port.lock, flags);
-       mtpt->port.mctrl &= ~TIOCM_OUT2;
-
-       multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-       spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-       serial_out(mtpt, UART_LCR, serial_inp(mtpt, UART_LCR) & ~UART_LCR_SBC);
-       serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
-                       UART_FCR_CLEAR_RCVR |
-                       UART_FCR_CLEAR_XMIT);
-       serial_outp(mtpt, UART_FCR, 0);
-
-
-       (void) serial_in(mtpt, UART_RX);
-
-       if ((!is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_POLL))
-       {
-               del_timer_sync(&mtpt->timer);
-       }
-       else
-       {
-               serial_unlink_irq_chain(mtpt);
-       }
-}
-
-
-
-static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud)
-{
-       unsigned int quot;
-
-       if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-                       baud == (port->uartclk/4))
-               quot = 0x8001;
-       else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-                       baud == (port->uartclk/8))
-               quot = 0x8002;
-       else
-               quot = sb_uart_get_divisor(port, baud);
-
-       return quot;
-}
-
-
-
-
-static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       unsigned char cval, fcr = 0;
-       unsigned long flags;
-       unsigned int baud, quot;
-
-       switch (termios->c_cflag & CSIZE) {
-               case CS5:
-                       cval = 0x00;
-                       break;
-               case CS6:
-                       cval = 0x01;
-                       break;
-               case CS7:
-                       cval = 0x02;
-                       break;
-               default:
-               case CS8:
-                       cval = 0x03;
-                       break;
-       }
-
-       if (termios->c_cflag & CSTOPB)
-               cval |= 0x04;
-       if (termios->c_cflag & PARENB)
-               cval |= UART_LCR_PARITY;
-       if (!(termios->c_cflag & PARODD))
-               cval |= UART_LCR_EPAR;
-
-#ifdef CMSPAR
-       if (termios->c_cflag & CMSPAR)
-               cval |= UART_LCR_SPAR;
-#endif
-
-       baud = sb_uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-       quot = multi_get_divisor(port, baud);
-
-       if (mtpt->capabilities & UART_USE_FIFO) {
-               //if (baud < 2400)
-               //      fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-               //else
-               //      fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
-
-               //      fcr = UART_FCR_ENABLE_FIFO | 0x90;
-                       fcr = fcr_arr[mtpt->port.line];
-       }
-
-       spin_lock_irqsave(&mtpt->port.lock, flags);
-
-       sb_uart_update_timeout(port, termios->c_cflag, baud);
-
-       mtpt->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-       if (termios->c_iflag & INPCK)
-               mtpt->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-       if (termios->c_iflag & (BRKINT | PARMRK))
-               mtpt->port.read_status_mask |= UART_LSR_BI;
-
-       mtpt->port.ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               mtpt->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-       if (termios->c_iflag & IGNBRK) {
-               mtpt->port.ignore_status_mask |= UART_LSR_BI;
-               if (termios->c_iflag & IGNPAR)
-                       mtpt->port.ignore_status_mask |= UART_LSR_OE;
-       }
-
-       if ((termios->c_cflag & CREAD) == 0)
-               mtpt->port.ignore_status_mask |= UART_LSR_DR;
-
-       mtpt->ier &= ~UART_IER_MSI;
-       if (UART_ENABLE_MS(&mtpt->port, termios->c_cflag))
-               mtpt->ier |= UART_IER_MSI;
-
-       serial_out(mtpt, UART_IER, mtpt->ier);
-
-       if (mtpt->capabilities & UART_STARTECH) {
-               serial_outp(mtpt, UART_LCR, 0xBF);
-               serial_outp(mtpt, UART_EFR,
-                               termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
-       }
-
-       serial_outp(mtpt, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
-
-       serial_outp(mtpt, UART_DLL, quot & 0xff);     /* LS of divisor */
-       serial_outp(mtpt, UART_DLM, quot >> 8);       /* MS of divisor */
-
-       serial_outp(mtpt, UART_LCR, cval);        /* reset DLAB */
-       mtpt->lcr = cval;                 /* Save LCR */
-
-       if (fcr & UART_FCR_ENABLE_FIFO) {
-               /* emulated UARTs (Lucent Venus 167x) need two steps */
-               serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-       }
-
-       serial_outp(mtpt, UART_FCR, fcr);     /* set fcr */
-
-
-       if ((mtpt->port.type == PORT_16C105X)
-               || (mtpt->port.type == PORT_16C105XA))
-       {
-               if(deep[mtpt->port.line]!=0)
-                       set_deep_fifo(port, ENABLE);
-
-               if (mtpt->interface != RS232)
-                       set_auto_rts(port,mtpt->interface);
-
-       }
-       else
-       {
-               if (mtpt->interface >= RS485NE)
-               {
-                       uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
-               }
-       }
-
-       if(mtpt->device->device_id == PCI_DEVICE_ID_MP4M)
-       {
-               SendATCommand(mtpt);
-               printk("SendATCommand\n");
-       }       
-       multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-       spin_unlock_irqrestore(&mtpt->port.lock, flags);
-}
-
-static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       if (state) {
-               if (mtpt->capabilities & UART_STARTECH) {
-                       serial_outp(mtpt, UART_LCR, 0xBF);
-                       serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
-                       serial_outp(mtpt, UART_LCR, 0);
-                       serial_outp(mtpt, UART_IER, UART_IERX_SLEEP);
-                       serial_outp(mtpt, UART_LCR, 0xBF);
-                       serial_outp(mtpt, UART_EFR, 0);
-                       serial_outp(mtpt, UART_LCR, 0);
-               }
-
-               if (mtpt->pm)
-                       mtpt->pm(port, state, oldstate);
-       } 
-       else 
-       {
-               if (mtpt->capabilities & UART_STARTECH) {
-                       serial_outp(mtpt, UART_LCR, 0xBF);
-                       serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
-                       serial_outp(mtpt, UART_LCR, 0);
-                       serial_outp(mtpt, UART_IER, 0);
-                       serial_outp(mtpt, UART_LCR, 0xBF);
-                       serial_outp(mtpt, UART_EFR, 0);
-                       serial_outp(mtpt, UART_LCR, 0);
-               }
-
-               if (mtpt->pm)
-                       mtpt->pm(port, state, oldstate);
-       }
-}
-
-static void multi_release_std_resource(struct mp_port *mtpt)
-{
-       unsigned int size = 8 << mtpt->port.regshift;
-
-       switch (mtpt->port.iotype) {
-               case UPIO_MEM:
-                       if (!mtpt->port.mapbase)
-                               break;
-
-                       if (mtpt->port.flags & UPF_IOREMAP) {
-                               iounmap(mtpt->port.membase);
-                               mtpt->port.membase = NULL;
-                       }
-
-                       release_mem_region(mtpt->port.mapbase, size);
-                       break;
-
-               case UPIO_HUB6:
-               case UPIO_PORT:
-                       release_region(mtpt->port.iobase,size);
-                       break;
-       }
-}
-
-static void multi_release_port(struct sb_uart_port *port)
-{
-}
-
-static int multi_request_port(struct sb_uart_port *port)
-{
-       return 0;
-}
-
-static void multi_config_port(struct sb_uart_port *port, int flags)
-{
-       struct mp_port *mtpt = (struct mp_port *)port;
-       int probeflags = PROBE_ANY;
-
-       if (flags & UART_CONFIG_TYPE)
-               autoconfig(mtpt, probeflags);
-       if (mtpt->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-               autoconfig_irq(mtpt);
-
-       if (mtpt->port.type == PORT_UNKNOWN)
-               multi_release_std_resource(mtpt);
-}
-
-static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser)
-{
-       if (ser->irq >= NR_IRQS || ser->irq < 0 ||
-                       ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-                       ser->type == PORT_STARTECH)
-               return -EINVAL;
-       return 0;
-}
-
-static const char *multi_type(struct sb_uart_port *port)
-{
-       int type = port->type;
-
-       if (type >= ARRAY_SIZE(uart_config))
-               type = 0;
-       return uart_config[type].name;
-}
-
-static struct sb_uart_ops multi_pops = {
-       .tx_empty   = multi_tx_empty,
-       .set_mctrl  = multi_set_mctrl,
-       .get_mctrl  = multi_get_mctrl,
-       .stop_tx    = multi_stop_tx,
-       .start_tx   = multi_start_tx,
-       .stop_rx    = multi_stop_rx,
-       .enable_ms  = multi_enable_ms,
-       .break_ctl  = multi_break_ctl,
-       .startup    = multi_startup,
-       .shutdown   = multi_shutdown,
-       .set_termios    = multi_set_termios,
-       .pm             = multi_pm,
-       .type           = multi_type,
-       .release_port   = multi_release_port,
-       .request_port   = multi_request_port,
-       .config_port    = multi_config_port,
-       .verify_port    = multi_verify_port,
-};
-
-static struct uart_driver multi_reg = {
-       .owner          = THIS_MODULE,
-       .driver_name    = "goldel_tulip",
-       .dev_name       = "ttyMP",
-       .major          = SB_TTY_MP_MAJOR,
-       .minor          = 0,
-       .nr             = MAX_MP_PORT, 
-       .cons           = NULL,
-};
-
-static void __init multi_init_ports(void)
-{
-       struct mp_port *mtpt;
-       static int first = 1;
-       int i,j,k;
-       unsigned char osc;
-       unsigned char b_ret = 0;
-       static struct mp_device_t *sbdev; 
-
-       if (!first)
-               return;
-       first = 0;
-
-       mtpt = multi_ports; 
-
-       for (k=0;k<NR_BOARD;k++)
-       {
-               sbdev = &mp_devs[k];
-
-               for (i = 0; i < sbdev->nr_ports; i++, mtpt++) 
-               {
-                       mtpt->device            = sbdev;
-                       mtpt->port.iobase   = sbdev->uart_access_addr + 8*i;
-                       mtpt->port.irq      = sbdev->irq;
-                       if ( ((sbdev->device_id == PCI_DEVICE_ID_MP4)&&(sbdev->revision==0x91)))
-                               mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i;
-                       else if (sbdev->revision == 0xc0)
-                               mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + (i & 0x1);
-                       else
-                               mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i/8;
-
-                       mtpt->option_base_addr = sbdev->option_reg_addr;
-
-                       mtpt->poll_type = sbdev->poll_type;
-
-                       mtpt->port.uartclk  = BASE_BAUD * 16;
-
-                       /* get input clock information */
-                       osc = inb(sbdev->option_reg_addr + MP_OPTR_DIR0 + i/8) & 0x0F;
-                       if (osc==0x0f)
-                               osc = 0;
-                       for(j=0;j<osc;j++)
-                               mtpt->port.uartclk *= 2;
-                       mtpt->port.flags    |= STD_COM_FLAGS | UPF_SHARE_IRQ ;
-                       mtpt->port.iotype   = UPIO_PORT;
-                       mtpt->port.ops      = &multi_pops;
-
-                       if (sbdev->revision == 0xc0)
-                       {
-                               /* for SB16C1053APCI */
-                               b_ret = sb1053a_get_interface(mtpt, i);
-                       }
-                       else
-                       {
-                               b_ret = read_option_register(mtpt,(MP_OPTR_IIR0 + i/8));
-                               printk("IIR_RET = %x\n",b_ret);
-                       }
-
-                       /* default to RS232 */
-                       mtpt->interface = RS232;
-                       if (IIR_RS422 == (b_ret & IIR_TYPE_MASK))
-                               mtpt->interface = RS422PTP;
-                       if (IIR_RS485 == (b_ret & IIR_TYPE_MASK))
-                               mtpt->interface = RS485NE;
-               }
-       }
-}
-
-static void __init multi_register_ports(struct uart_driver *drv)
-{
-       int i;
-
-       multi_init_ports();
-
-       for (i = 0; i < NR_PORTS; i++) {
-               struct mp_port *mtpt = &multi_ports[i];
-
-               mtpt->port.line = i;
-               mtpt->port.ops = &multi_pops;
-               init_timer(&mtpt->timer);
-               mtpt->timer.function = multi_timeout;
-               mp_add_one_port(drv, &mtpt->port);
-       }
-}
-
-/**
- * pci_remap_base - remap BAR value of pci device
- *
- * PARAMETERS
- *  pcidev  - pci_dev structure address
- *  offset  - BAR offset PCI_BASE_ADDRESS_0 ~ PCI_BASE_ADDRESS_4
- *  address - address to be changed BAR value
- *  size       - size of address space 
- *
- * RETURNS
- *  If this function performs successful, it returns 0. Otherwise, It returns -1.
- */
-static int pci_remap_base(struct pci_dev *pcidev, unsigned int offset, 
-               unsigned int address, unsigned int size) 
-{
-#if 0
-       struct resource *root;
-       unsigned index = (offset - 0x10) >> 2;
-#endif
-
-       pci_write_config_dword(pcidev, offset, address);
-#if 0
-       root = pcidev->resource[index].parent;
-       release_resource(&pcidev->resource[index]);
-       address &= ~0x1;
-       pcidev->resource[index].start = address;
-       pcidev->resource[index].end       = address + size - 1;
-
-       if (request_resource(root, &pcidev->resource[index]) != NULL)
-       {
-               printk(KERN_ERR "pci remap conflict!! 0x%x\n", address);
-               return (-1);
-       }
-#endif
-
-       return (0);
-}
-
-static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
-{
-       static struct mp_device_t *sbdev = mp_devs;
-       unsigned long addr = 0;
-       int j;
-       struct resource *ret = NULL;
-
-       sbdev->device_id = brd.device_id;
-       pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &(sbdev->revision));
-       sbdev->name = brd.name;
-       sbdev->uart_access_addr = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-
-       /* check revision. The SB16C1053APCI's option i/o address is BAR4 */
-       if (sbdev->revision == 0xc0)
-       {
-               /* SB16C1053APCI */
-               sbdev->option_reg_addr = pcidev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
-       }
-       else
-       {
-               sbdev->option_reg_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-       }
-#if 1  
-       if (sbdev->revision == 0xc0)
-       {
-               outb(0x00, sbdev->option_reg_addr + MP_OPTR_GPOCR);
-               inb(sbdev->option_reg_addr + MP_OPTR_GPOCR);
-               outb(0x83, sbdev->option_reg_addr + MP_OPTR_GPOCR);
-       }
-#endif
-
-       sbdev->irq = pcidev->irq;
-
-       if ((brd.device_id & 0x0800) || !(brd.device_id &0xff00))
-       {
-               sbdev->poll_type = TYPE_INTERRUPT;
-       }
-       else
-       {
-               sbdev->poll_type = TYPE_POLL;
-       }
-
-       /* codes which is specific to each board*/
-       switch(brd.device_id){
-               case PCI_DEVICE_ID_MP1 :
-               case PCIE_DEVICE_ID_MP1 :
-               case PCIE_DEVICE_ID_MP1E :
-               case PCIE_DEVICE_ID_GT_MP1 :
-                       sbdev->nr_ports = 1;
-                       break;
-               case PCI_DEVICE_ID_MP2 :
-               case PCIE_DEVICE_ID_MP2 :
-               case PCIE_DEVICE_ID_GT_MP2 :
-               case PCIE_DEVICE_ID_MP2B :
-               case PCIE_DEVICE_ID_MP2E :
-                       sbdev->nr_ports = 2;
-
-                       /* serial base address remap */
-                       if (sbdev->revision == 0xc0)
-                       {
-                               int prev_port_addr = 0;
-
-                               pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-                       }
-                       break;
-               case PCI_DEVICE_ID_MP4 :
-               case PCI_DEVICE_ID_MP4A :
-               case PCIE_DEVICE_ID_MP4 :
-               case PCI_DEVICE_ID_GT_MP4 :
-               case PCI_DEVICE_ID_GT_MP4A :
-               case PCIE_DEVICE_ID_GT_MP4 :
-               case PCI_DEVICE_ID_MP4M :
-               case PCIE_DEVICE_ID_MP4B :
-                       sbdev->nr_ports = 4;
-
-                       if(sbdev->revision == 0x91){
-                               sbdev->reserved_addr[0] = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-                               outb(0x03 , sbdev->reserved_addr[0] + 0x01);
-                               outb(0x03 , sbdev->reserved_addr[0] + 0x02);
-                               outb(0x01 , sbdev->reserved_addr[0] + 0x20);
-                               outb(0x00 , sbdev->reserved_addr[0] + 0x21);
-                               request_region(sbdev->reserved_addr[0], 32, sbdev->name);
-                               sbdev->uart_access_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-                               sbdev->option_reg_addr = pcidev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
-                       }
-
-                       /* SB16C1053APCI */
-                       if (sbdev->revision == 0xc0)
-                       {
-                               int prev_port_addr = 0;
-
-                               pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 8);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 24, 8);
-                       }
-                       break;
-               case PCI_DEVICE_ID_MP6 :
-               case PCI_DEVICE_ID_MP6A :
-               case PCI_DEVICE_ID_GT_MP6 :
-               case PCI_DEVICE_ID_GT_MP6A :
-                       sbdev->nr_ports = 6;
-
-                       /* SB16C1053APCI */
-                       if (sbdev->revision == 0xc0)
-                       {
-                               int prev_port_addr = 0;
-
-                               pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 16);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 32, 16);
-                       }
-                       break;
-               case PCI_DEVICE_ID_MP8 :
-               case PCIE_DEVICE_ID_MP8 :
-               case PCI_DEVICE_ID_GT_MP8 :
-               case PCIE_DEVICE_ID_GT_MP8 :
-               case PCIE_DEVICE_ID_MP8B :
-                       sbdev->nr_ports = 8;
-                       break;
-               case PCI_DEVICE_ID_MP32 :
-               case PCIE_DEVICE_ID_MP32 :
-               case PCI_DEVICE_ID_GT_MP32 :
-               case PCIE_DEVICE_ID_GT_MP32 :
-                       {
-                               int portnum_hex=0;
-                               portnum_hex = inb(sbdev->option_reg_addr);
-                               sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
-                       }
-                       break;
-#ifdef CONFIG_PARPORT_PC
-               case PCI_DEVICE_ID_MP2S1P :
-                       sbdev->nr_ports = 2;
-
-                       /* SB16C1053APCI */
-                       if (sbdev->revision == 0xc0)
-                       {
-                               int prev_port_addr = 0;
-
-                               pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-                               pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-                       }
-
-                       /* add PC compatible parallel port */
-                       parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
-                       break;
-               case PCI_DEVICE_ID_MP1P :
-                       /* add PC compatible parallel port */
-                       parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
-                       break;
-#endif
-       }
-
-       ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
-
-       if (sbdev->revision == 0xc0)
-       {
-               ret = request_region(sbdev->option_reg_addr, 0x40, sbdev->name);
-       }
-       else
-       {
-               ret = request_region(sbdev->option_reg_addr, 0x20, sbdev->name);
-       }
-
-
-       NR_BOARD++;
-       NR_PORTS += sbdev->nr_ports;
-
-       /* Enable PCI interrupt */
-       addr = sbdev->option_reg_addr + MP_OPTR_IMR0;
-       for(j=0; j < (sbdev->nr_ports/8)+1; j++)
-       {
-               if (sbdev->poll_type == TYPE_INTERRUPT)
-               {
-                       outb(0xff,addr +j);
-               }
-       }
-       sbdev++;
-
-       return 0;
-}
-
-static int __init multi_init(void)
-{
-       int ret, i;
-       struct pci_dev  *dev = NULL;
-
-       if(fcr_count==0)
-       {
-               for(i=0;i<256;i++)
-               {
-                       fcr_arr[i] = 0x01;
-                       
-               }
-       }
-       if(deep_count==0)
-       {
-               for(i=0;i<256;i++)
-               {
-                       deep[i] = 1;
-                       
-               }
-       }
-       if(rtr_count==0)
-        {
-                for(i=0;i<256;i++)
-                {
-                        rtr[i] = 0x10;
-                }
-        }
-       if(ttr_count==0)
-        {
-                for(i=0;i<256;i++)
-                {
-                        ttr[i] = 0x38;
-                }
-        }
-
-
-printk("MULTI INIT\n");
-       for( i=0; i< mp_nrpcibrds; i++)
-       {
-
-               while( (dev = pci_get_device(mp_pciboards[i].vendor_id, mp_pciboards[i].device_id, dev) ) )
-
-               {
-printk("FOUND~~~\n");
-//     Cent OS bug fix
-//                     if (mp_pciboards[i].device_id & 0x0800)
-                       {
-                               int status;
-                               pci_disable_device(dev);
-                               status = pci_enable_device(dev);
-            
-                               if (status != 0)
-                               { 
-                                               printk("Multiport Board Enable Fail !\n\n");
-                                               status = -ENXIO;
-                                       return status;
-                               }
-                       }
-
-                       init_mp_dev(dev, mp_pciboards[i]);      
-               }
-       }
-
-       for (i = 0; i < NR_IRQS; i++)
-               spin_lock_init(&irq_lists[i].lock);
-
-       ret = mp_register_driver(&multi_reg);
-
-       if (ret >= 0)
-               multi_register_ports(&multi_reg);
-
-       return ret;
-}
-
-static void __exit multi_exit(void)
-{
-       int i;
-
-       for (i = 0; i < NR_PORTS; i++)
-               mp_remove_one_port(&multi_reg, &multi_ports[i].port);
-
-       mp_unregister_driver(&multi_reg);
-}
-
-module_init(multi_init);
-module_exit(multi_exit);
-
-MODULE_DESCRIPTION("SystemBase Multiport PCI/PCIe CORE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sb105x/sb_pci_mp.h b/drivers/staging/sb105x/sb_pci_mp.h
deleted file mode 100644 (file)
index 80ae4ab..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/tty_driver.h>
-#include <linux/pci.h>
-#include <linux/circ_buf.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/serial.h>
-#include <linux/interrupt.h>
-
-
-#include <linux/parport.h>
-#include <linux/ctype.h>
-#include <linux/poll.h>
-
-
-#define MP_TERMIOS  ktermios
-
-#include "sb_mp_register.h"
-#include "sb_ser_core.h"
-
-#define DRIVER_VERSION  "1.1"
-#define DRIVER_DATE     "2012/01/05"
-#define DRIVER_AUTHOR  "SYSTEMBASE<tech@sysbas.com>"
-#define DRIVER_DESC  "SystemBase PCI/PCIe Multiport Core"
-
-#define SB_TTY_MP_MAJOR                        54
-#define PCI_VENDOR_ID_MULTIPORT                0x14A1
-
-#define PCI_DEVICE_ID_MP1              0x4d01
-#define PCI_DEVICE_ID_MP2              0x4d02
-#define PCI_DEVICE_ID_MP4              0x4d04
-#define PCI_DEVICE_ID_MP4A             0x4d54
-#define PCI_DEVICE_ID_MP6              0x4d06
-#define PCI_DEVICE_ID_MP6A             0x4d56
-#define PCI_DEVICE_ID_MP8              0x4d08
-#define PCI_DEVICE_ID_MP32             0x4d32
-/* Parallel port */
-#define PCI_DEVICE_ID_MP1P             0x4301
-#define PCI_DEVICE_ID_MP2S1P           0x4303
-
-#define PCIE_DEVICE_ID_MP1             0x4501
-#define PCIE_DEVICE_ID_MP2             0x4502
-#define PCIE_DEVICE_ID_MP4             0x4504
-#define PCIE_DEVICE_ID_MP8             0x4508
-#define PCIE_DEVICE_ID_MP32            0x4532
-
-#define PCIE_DEVICE_ID_MP1E            0x4e01
-#define PCIE_DEVICE_ID_MP2E            0x4e02
-#define PCIE_DEVICE_ID_MP2B            0x4b02
-#define PCIE_DEVICE_ID_MP4B            0x4b04
-#define PCIE_DEVICE_ID_MP8B            0x4b08
-
-#define PCI_DEVICE_ID_GT_MP4           0x0004
-#define PCI_DEVICE_ID_GT_MP4A          0x0054
-#define PCI_DEVICE_ID_GT_MP6           0x0006
-#define PCI_DEVICE_ID_GT_MP6A          0x0056
-#define PCI_DEVICE_ID_GT_MP8           0x0008
-#define PCI_DEVICE_ID_GT_MP32          0x0032
-
-#define PCIE_DEVICE_ID_GT_MP1          0x1501
-#define PCIE_DEVICE_ID_GT_MP2          0x1502
-#define PCIE_DEVICE_ID_GT_MP4          0x1504
-#define PCIE_DEVICE_ID_GT_MP8          0x1508
-#define PCIE_DEVICE_ID_GT_MP32         0x1532
-
-#define PCI_DEVICE_ID_MP4M             0x4604  //modem
-
-#define MAX_MP_DEV  8
-#define BD_MAX_PORT 32         /* Max serial port in one board */
-#define MAX_MP_PORT 256 /* Max serial port in one PC */
-
-#define PORT_16C105XA  3
-#define PORT_16C105X   2
-#define PORT_16C55X            1
-
-#define ENABLE         1
-#define DISABLE                0
-
-/* ioctls */
-#define TIOCGNUMOFPORT         0x545F
-#define TIOCSMULTIECHO         0x5440
-#define TIOCSPTPNOECHO         0x5441
-
-#define TIOCGOPTIONREG         0x5461
-#define TIOCGDISABLEIRQ                0x5462
-#define TIOCGENABLEIRQ         0x5463
-#define TIOCGSOFTRESET         0x5464
-#define TIOCGSOFTRESETR                0x5465
-#define TIOCGREGINFO           0x5466
-#define TIOCGGETLSR            0x5467
-#define TIOCGGETDEVID          0x5468
-#define TIOCGGETBDNO           0x5469
-#define TIOCGGETINTERFACE      0x546A
-#define TIOCGGETREV            0x546B
-#define TIOCGGETNRPORTS                0x546C
-#define TIOCGGETPORTTYPE       0x546D
-#define GETDEEPFIFO            0x54AA
-#define SETDEEPFIFO            0x54AB
-#define SETFCR                 0x54BA
-#define SETTTR                 0x54B1
-#define SETRTR                 0x54B2
-#define GETTTR                 0x54B3
-#define GETRTR                 0x54B4
-
-/* multi-drop mode related ioctl commands */
-#define TIOCSMULTIDROP         0x5470
-#define TIOCSMDADDR            0x5471
-#define TIOCGMDADDR            0x5472
-#define TIOCSENDADDR           0x5473
-
-
-/* serial interface */
-#define RS232          1 
-#define RS422PTP       2
-#define RS422MD                3
-#define RS485NE                4
-#define RS485ECHO      5
-
-#define serial_inp(up, offset)      serial_in(up, offset)
-#define serial_outp(up, offset, value)  serial_out(up, offset, value)
-       
-#define PASS_LIMIT  256
-#define is_real_interrupt(irq)  ((irq) != 0)
-
-#define PROBE_ANY   (~0)
-
-static DEFINE_MUTEX(mp_mutex);
-#define MP_MUTEX_LOCK(x) mutex_lock(&(x)) 
-#define MP_MUTEX_UNLOCK(x) mutex_unlock(&(x)) 
-#define MP_STATE_LOCK(x) mutex_lock(&((x)->mutex)) 
-#define MP_STATE_UNLOCK(x) mutex_unlock(&((x)->mutex)) 
-        
-
-#define UART_LSR_SPECIAL    0x1E
-        
-#define HIGH_BITS_OFFSET        ((sizeof(long)-sizeof(int))*8)
-#define uart_users(state)       ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
-
-
-//#define MP_DEBUG 1
-#undef MP_DEBUG
-
-#ifdef MP_DEBUG
-#define DPRINTK(x...)   printk(x)
-#else
-#define DPRINTK(x...)   do { } while (0)
-#endif
-
-#ifdef MP_DEBUG
-#define DEBUG_AUTOCONF(fmt...)  printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...)  do { } while (0)
-#endif
-
-#ifdef MP_DEBUG
-#define DEBUG_INTR(fmt...)  printk(fmt)
-#else
-#define DEBUG_INTR(fmt...)  do { } while (0)
-#endif
-
-#if defined(__i386__) && defined(CONFIG_M486)
-#define SERIAL_INLINE
-#endif
-#ifdef SERIAL_INLINE
-#define _INLINE_ inline
-#else
-#define _INLINE_
-#endif
-
-#define TYPE_POLL      1
-#define TYPE_INTERRUPT 2
-
-
-struct mp_device_t {
-        unsigned short  device_id;
-        unsigned char   revision;
-        char            *name;
-        unsigned long   uart_access_addr;
-        unsigned long   option_reg_addr;
-        unsigned long   reserved_addr[4];
-        int             irq;
-        int             nr_ports;
-        int             poll_type;
-};
-
-typedef struct mppcibrd {
-        char            *name;
-        unsigned short  vendor_id;
-        unsigned short  device_id;
-} mppcibrd_t;
-
-static mppcibrd_t mp_pciboards[] = {
-
-        { "Multi-1 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1} ,
-        { "Multi-2 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2} ,
-        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4} ,
-        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4A} ,
-        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6} ,
-        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6A} ,
-        { "Multi-8 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP8} ,
-        { "Multi-32 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP32} ,
-
-        { "Multi-1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1P} ,
-        { "Multi-2S1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2S1P} ,
-
-        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4} ,
-        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4A} ,
-        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6} ,
-        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6A} ,
-        { "Multi-8(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP8} ,
-        { "Multi-32(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP32} ,
-
-        { "Multi-1 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1} ,
-        { "Multi-2 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2} ,
-        { "Multi-4 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4} ,
-        { "Multi-8 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8} ,
-        { "Multi-32 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP32} ,
-
-        { "Multi-1 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1E} ,
-        { "Multi-2 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2E} ,
-        { "Multi-2 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2B} ,
-        { "Multi-4 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4B} ,
-        { "Multi-8 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8B} ,
-
-        { "Multi-1(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP1} ,
-        { "Multi-2(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP2} ,
-        { "Multi-4(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP4} ,
-        { "Multi-8(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP8} ,
-        { "Multi-32(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP32} ,
-
-        { "Multi-4M PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4M} ,
-};
-
-struct mp_port {
-        struct sb_uart_port port;
-
-        struct timer_list   timer;      /* "no irq" timer */
-        struct list_head    list;       /* ports on this IRQ */
-        unsigned int        capabilities;   /* port capabilities */
-        unsigned short      rev;
-        unsigned char       acr;
-        unsigned char       ier;
-        unsigned char       lcr;
-        unsigned char       mcr;
-        unsigned char       mcr_mask;   /* mask of user bits */
-        unsigned char       mcr_force;  /* mask of forced bits */
-        unsigned char       lsr_break_flag;
-
-        void            (*pm)(struct sb_uart_port *port,
-                        unsigned int state, unsigned int old);
-        struct mp_device_t *device;
-        unsigned long   interface_config_addr;
-        unsigned long   option_base_addr;
-        unsigned char   interface;
-        unsigned char   poll_type;
-};
-
-struct irq_info {
-        spinlock_t      lock;
-        struct list_head    *head;
-};
-
-struct sb105x_uart_config {
-       char    *name;
-       int     dfl_xmit_fifo_size;
-       int     flags;
-};
-
-static const struct sb105x_uart_config uart_config[] = {
-        { "unknown",    1,  0 },
-        { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
-        { "SB16C1050",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-        { "SB16C1050A",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-};
-
-
-
diff --git a/drivers/staging/sb105x/sb_ser_core.h b/drivers/staging/sb105x/sb_ser_core.h
deleted file mode 100644 (file)
index c8fb991..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-#include <linux/wait.h>
-
-#define UART_CONFIG_TYPE       (1 << 0)
-#define UART_CONFIG_IRQ                (1 << 1)
-#define UPIO_PORT              (0)
-#define UPIO_HUB6              (1)
-#define UPIO_MEM               (2)
-#define UPIO_MEM32             (3)
-#define UPIO_AU                        (4)                     /* Au1x00 type IO */
-#define UPIO_TSI               (5)                     /* Tsi108/109 type IO */
-#define UPF_FOURPORT           (1 << 1)
-#define UPF_SAK                        (1 << 2)
-#define UPF_SPD_MASK           (0x1030)
-#define UPF_SPD_HI             (0x0010)
-#define UPF_SPD_VHI            (0x0020)
-#define UPF_SPD_CUST           (0x0030)
-#define UPF_SPD_SHI            (0x1000)
-#define UPF_SPD_WARP           (0x1010)
-#define UPF_SKIP_TEST          (1 << 6)
-#define UPF_AUTO_IRQ           (1 << 7)
-#define UPF_HARDPPS_CD         (1 << 11)
-#define UPF_LOW_LATENCY                (1 << 13)
-#define UPF_BUGGY_UART         (1 << 14)
-#define UPF_MAGIC_MULTIPLIER   (1 << 16)
-#define UPF_CONS_FLOW          (1 << 23)
-#define UPF_SHARE_IRQ          (1 << 24)
-#define UPF_BOOT_AUTOCONF      (1 << 28)
-#define UPF_DEAD               (1 << 30)
-#define UPF_IOREMAP            (1 << 31)
-#define UPF_CHANGE_MASK                (0x17fff)
-#define UPF_USR_MASK           (UPF_SPD_MASK|UPF_LOW_LATENCY)
-#define USF_CLOSING_WAIT_INF   (0)
-#define USF_CLOSING_WAIT_NONE  (~0U)
-
-#define UART_XMIT_SIZE PAGE_SIZE
-
-#define UIF_CHECK_CD           (1 << 25)
-#define UIF_CTS_FLOW           (1 << 26)
-#define UIF_NORMAL_ACTIVE      (1 << 29)
-#define UIF_INITIALIZED                (1 << 31)
-#define UIF_SUSPENDED          (1 << 30)
-
-#define WAKEUP_CHARS           256
-
-#define uart_circ_empty(circ)          ((circ)->head == (circ)->tail)
-#define uart_circ_clear(circ)          ((circ)->head = (circ)->tail = 0)
-
-#define uart_circ_chars_pending(circ)  \
-       (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define uart_circ_chars_free(circ)     \
-       (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define uart_tx_stopped(port)          \
-       ((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
-
-#define UART_ENABLE_MS(port,cflag)     ((port)->flags & UPF_HARDPPS_CD || \
-                                        (cflag) & CRTSCTS || \
-                                        !((cflag) & CLOCAL))
-
-
-struct sb_uart_port;
-struct sb_uart_info;
-struct serial_struct;
-struct device;
-
-struct sb_uart_ops {
-       unsigned int    (*tx_empty)(struct sb_uart_port *);
-       void            (*set_mctrl)(struct sb_uart_port *, unsigned int mctrl);
-       unsigned int    (*get_mctrl)(struct sb_uart_port *);
-       void            (*stop_tx)(struct sb_uart_port *);
-       void            (*start_tx)(struct sb_uart_port *);
-       void            (*send_xchar)(struct sb_uart_port *, char ch);
-       void            (*stop_rx)(struct sb_uart_port *);
-       void            (*enable_ms)(struct sb_uart_port *);
-       void            (*break_ctl)(struct sb_uart_port *, int ctl);
-       int             (*startup)(struct sb_uart_port *);
-       void            (*shutdown)(struct sb_uart_port *);
-       void            (*set_termios)(struct sb_uart_port *, struct MP_TERMIOS *new,
-                                      struct MP_TERMIOS *old);
-       void            (*pm)(struct sb_uart_port *, unsigned int state,
-                             unsigned int oldstate);
-       int             (*set_wake)(struct sb_uart_port *, unsigned int state);
-
-       const char *(*type)(struct sb_uart_port *);
-
-       void            (*release_port)(struct sb_uart_port *);
-
-       int             (*request_port)(struct sb_uart_port *);
-       void            (*config_port)(struct sb_uart_port *, int);
-       int             (*verify_port)(struct sb_uart_port *, struct serial_struct *);
-       int             (*ioctl)(struct sb_uart_port *, unsigned int, unsigned long);
-};
-
-
-struct sb_uart_icount {
-       __u32   cts;
-       __u32   dsr;
-       __u32   rng;
-       __u32   dcd;
-       __u32   rx;
-       __u32   tx;
-       __u32   frame;
-       __u32   overrun;
-       __u32   parity;
-       __u32   brk;
-       __u32   buf_overrun;
-};
-typedef unsigned int  upf_t;
-
-struct sb_uart_port {
-       spinlock_t              lock;                   /* port lock */
-       unsigned int            iobase;                 /* in/out[bwl] */
-       unsigned char __iomem   *membase;               /* read/write[bwl] */
-       unsigned int            irq;                    /* irq number */
-       unsigned int            uartclk;                /* base uart clock */
-       unsigned int            fifosize;               /* tx fifo size */
-       unsigned char           x_char;                 /* xon/xoff char */
-       unsigned char           regshift;               /* reg offset shift */
-       unsigned char           iotype;                 /* io access style */
-       unsigned char           unused1;
-
-
-       unsigned int            read_status_mask;       /* driver specific */
-       unsigned int            ignore_status_mask;     /* driver specific */
-       struct sb_uart_info     *info;                  /* pointer to parent info */
-       struct sb_uart_icount   icount;                 /* statistics */
-
-       struct console          *cons;                  /* struct console, if any */
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-       unsigned long           sysrq;                  /* sysrq timeout */
-#endif
-
-       upf_t                   flags;
-
-       unsigned int            mctrl;                  /* current modem ctrl settings */
-       unsigned int            timeout;                /* character-based timeout */
-       unsigned int            type;                   /* port type */
-       const struct sb_uart_ops        *ops;
-       unsigned int            custom_divisor;
-       unsigned int            line;                   /* port index */
-       unsigned long           mapbase;                /* for ioremap */
-       struct device           *dev;                   /* parent device */
-       unsigned char           hub6;                   /* this should be in the 8250 driver */
-       unsigned char           unused[3];
-};
-
-#define mdmode                 unused[2]
-#define MDMODE_ADDR            0x1
-#define MDMODE_ENABLE  0x2
-#define MDMODE_AUTO            0x4
-#define MDMODE_ADDRSEND        0x8
-
-struct sb_uart_state {
-       unsigned int            close_delay;            /* msec */
-       unsigned int            closing_wait;           /* msec */
-
-
-       int                     count;
-       int                     pm_state;
-       struct sb_uart_info     *info;
-       struct sb_uart_port     *port;
-
-       struct mutex            mutex;
-};
-
-typedef unsigned int  uif_t;
-
-struct sb_uart_info {
-       struct tty_struct       *tty;
-       struct circ_buf         xmit;
-       uif_t                   flags;
-
-       int                     blocked_open;
-
-       struct tasklet_struct   tlet;
-
-       wait_queue_head_t       open_wait;
-       wait_queue_head_t       delta_msr_wait;
-};
-
-
-struct module;
-struct tty_driver;
-
-struct uart_driver {
-       struct module           *owner;
-       const char              *driver_name;
-       const char              *dev_name;
-       int                      major;
-       int                      minor;
-       int                      nr;
-       struct console          *cons;
-
-       struct sb_uart_state    *state;
-        struct tty_driver               *tty_driver;
-};
-
-void sb_uart_write_wakeup(struct sb_uart_port *port)
-{
-    struct sb_uart_info *info = port->info;
-    tasklet_schedule(&info->tlet);
-}
-
-void sb_uart_update_timeout(struct sb_uart_port *port, unsigned int cflag,
-                        unsigned int baud)
-{
-    unsigned int bits;
-
-    switch (cflag & CSIZE)
-    {
-        case CS5:
-            bits = 7;
-            break;
-
-        case CS6:
-            bits = 8;
-            break;
-
-        case CS7:
-            bits = 9;
-            break;
-
-        default:
-            bits = 10;
-            break;
-    }
-
-    if (cflag & CSTOPB)
-    {
-        bits++;
-    }
-
-    if (cflag & PARENB)
-    {
-        bits++;
-    }
-
-    bits = bits * port->fifosize;
-
-    port->timeout = (HZ * bits) / baud + HZ/50;
-}
-unsigned int sb_uart_get_baud_rate(struct sb_uart_port *port, struct MP_TERMIOS *termios,
-                               struct MP_TERMIOS *old, unsigned int min,
-                               unsigned int max)
-{
-        unsigned int try, baud, altbaud = 38400;
-        upf_t flags = port->flags & UPF_SPD_MASK;
-
-        if (flags == UPF_SPD_HI)
-                altbaud = 57600;
-        if (flags == UPF_SPD_VHI)
-                altbaud = 115200;
-        if (flags == UPF_SPD_SHI)
-                altbaud = 230400;
-        if (flags == UPF_SPD_WARP)
-                altbaud = 460800;
-
-        for (try = 0; try < 2; try++) {
-
-                switch (termios->c_cflag & (CBAUD | CBAUDEX))
-                {
-                       case B921600    : baud = 921600;    break;
-                       case B460800    : baud = 460800;    break;
-                       case B230400    : baud = 230400;    break;
-                       case B115200    : baud = 115200;    break;
-                       case B57600     : baud = 57600;     break;
-                       case B38400     : baud = 38400;     break;
-                       case B19200     : baud = 19200;     break;
-                       case B9600      : baud = 9600;      break;
-                       case B4800      : baud = 4800;      break;
-                       case B2400      : baud = 2400;      break;
-                       case B1800      : baud = 1800;      break;
-                       case B1200      : baud = 1200;      break;
-                       case B600       : baud = 600;       break;
-                       case B300       : baud = 300;       break;
-                        case B200       : baud = 200;       break;
-                       case B150       : baud = 150;       break;
-                       case B134       : baud = 134;       break;
-                       case B110       : baud = 110;       break;
-                       case B75        : baud = 75;        break;
-                       case B50        : baud = 50;        break;
-                       default         : baud = 9600;      break;
-                }
-
-                if (baud == 38400)
-                        baud = altbaud;
-
-                if (baud == 0)
-                        baud = 9600;
-
-                if (baud >= min && baud <= max)
-                        return baud;
-
-                termios->c_cflag &= ~CBAUD;
-                if (old) {
-                        termios->c_cflag |= old->c_cflag & CBAUD;
-                        old = NULL;
-                        continue;
-                }
-
-                termios->c_cflag |= B9600;
-        }
-
-        return 0;
-}
-unsigned int sb_uart_get_divisor(struct sb_uart_port *port, unsigned int baud)
-{
-        unsigned int quot;
-
-        if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
-                quot = port->custom_divisor;
-        else
-                quot = (port->uartclk + (8 * baud)) / (16 * baud);
-
-        return quot;
-}
-
-
-
-static inline int sb_uart_handle_break(struct sb_uart_port *port)
-{
-       struct sb_uart_info *info = port->info;
-
-       if (port->flags & UPF_SAK)
-               do_SAK(info->tty);
-       return 0;
-}
-
-static inline void sb_uart_handle_dcd_change(struct sb_uart_port *port, unsigned int status)
-{
-       struct sb_uart_info *info = port->info;
-
-       port->icount.dcd++;
-
-       if (info->flags & UIF_CHECK_CD) {
-               if (status)
-                       wake_up_interruptible(&info->open_wait);
-               else if (info->tty)
-                       tty_hangup(info->tty);
-       }
-}
-
-static inline void sb_uart_handle_cts_change(struct sb_uart_port *port, unsigned int status)
-{
-       struct sb_uart_info *info = port->info;
-       struct tty_struct *tty = info->tty;
-
-       port->icount.cts++;
-
-       if (info->flags & UIF_CTS_FLOW) {
-               if (tty->hw_stopped) {
-                       if (status) {
-                               tty->hw_stopped = 0;
-                               port->ops->start_tx(port);
-                               sb_uart_write_wakeup(port);
-                       }
-               } else {
-                       if (!status) {
-                               tty->hw_stopped = 1;
-                               port->ops->stop_tx(port);
-                       }
-               }
-       }
-}
-
-
-
index 7fc267550c653bc080101d8c4a863ae9611f2b81..965485f71fe978bdcf0610878e8fe7537d203442 100644 (file)
@@ -112,7 +112,7 @@ static void sep_do_callback(struct work_struct *work)
  *     on what operation is to be done
  */
 static int sep_submit_work(struct workqueue_struct *work_queue,
-       void(*funct)(void *),
+       void (*funct)(void *),
        void *data)
 {
        struct sep_work_struct *sep_work;
index 122614c4092b6e1377196c36697774a6ee76d4d4..cbfc0cffb1d8637461a0d685637a61cf5721d21b 100644 (file)
@@ -1266,9 +1266,8 @@ static int sep_lock_user_pages(struct sep_device *sep,
        /* Check the number of pages locked - if not all then exit with error */
        if (result != num_pages) {
                dev_warn(&sep->pdev->dev,
-                       "[PID%d] not all pages locked by get_user_pages, "
-                       "result 0x%X, num_pages 0x%X\n",
-                               current->pid, result, num_pages);
+                       "[PID%d] not all pages locked by get_user_pages, result 0x%X, num_pages 0x%X\n",
+                       current->pid, result, num_pages);
                error = -ENOMEM;
                goto end_function_with_error3;
        }
@@ -1293,9 +1292,9 @@ static int sep_lock_user_pages(struct sep_device *sep,
                lli_array[count].block_size = PAGE_SIZE;
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] lli_array[%x].bus_address is %08lx, "
-                       "lli_array[%x].block_size is (hex) %x\n", current->pid,
-                       count, (unsigned long)lli_array[count].bus_address,
+                       "[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n",
+                       current->pid, count,
+                       (unsigned long)lli_array[count].bus_address,
                        count, lli_array[count].block_size);
        }
 
@@ -1314,8 +1313,7 @@ static int sep_lock_user_pages(struct sep_device *sep,
                        "[PID%d] After check if page 0 has all data\n",
                        current->pid);
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] lli_array[0].bus_address is (hex) %08lx, "
-                       "lli_array[0].block_size is (hex) %x\n",
+                       "[PID%d] lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n",
                        current->pid,
                        (unsigned long)lli_array[0].bus_address,
                        lli_array[0].block_size);
@@ -1332,8 +1330,7 @@ static int sep_lock_user_pages(struct sep_device *sep,
                        "[PID%d] After last page size adjustment\n",
                        current->pid);
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] lli_array[%x].bus_address is (hex) %08lx, "
-                       "lli_array[%x].block_size is (hex) %x\n",
+                       "[PID%d] lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n",
                        current->pid,
                        num_pages - 1,
                        (unsigned long)lli_array[num_pages - 1].bus_address,
@@ -1449,8 +1446,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep,
                start_page += PAGE_SIZE;
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] lli_array[%x].bus_address is %08lx, "
-                       "lli_array[%x].block_size is (hex) %x\n",
+                       "[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n",
                        current->pid,
                        count, (unsigned long)lli_array[count].bus_address,
                        count, lli_array[count].block_size);
@@ -1469,8 +1465,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep,
 
        dev_dbg(&sep->pdev->dev,
                "[PID%d] After check if page 0 has all data\n"
-               "lli_array[0].bus_address is (hex) %08lx, "
-               "lli_array[0].block_size is (hex) %x\n",
+               "lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n",
                current->pid,
                (unsigned long)lli_array[0].bus_address,
                lli_array[0].block_size);
@@ -1484,8 +1479,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep,
 
                dev_dbg(&sep->pdev->dev,
                        "[PID%d] After last page size adjustment\n"
-                       "lli_array[%x].bus_address is (hex) %08lx, "
-                       "lli_array[%x].block_size is (hex) %x\n",
+                       "lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n",
                        current->pid, num_pages - 1,
                        (unsigned long)lli_array[num_pages - 1].bus_address,
                        num_pages - 1,
@@ -1745,9 +1739,8 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
 
        while ((unsigned long) lli_table_ptr->bus_address != 0xffffffff) {
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] lli table %08lx, "
-                       "table_data_size is (hex) %lx\n",
-                               current->pid, table_count, table_data_size);
+                       "[PID%d] lli table %08lx, table_data_size is (hex) %lx\n",
+                       current->pid, table_count, table_data_size);
                dev_dbg(&sep->pdev->dev,
                        "[PID%d] num_table_entries is (hex) %lx\n",
                                current->pid, num_table_entries);
@@ -1762,8 +1755,8 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
                                (unsigned long) lli_table_ptr);
 
                        dev_dbg(&sep->pdev->dev,
-                               "[PID%d] phys address is %08lx "
-                               "block size is (hex) %x\n", current->pid,
+                               "[PID%d] phys address is %08lx block size is (hex) %x\n",
+                               current->pid,
                                (unsigned long)lli_table_ptr->bus_address,
                                lli_table_ptr->block_size);
                }
@@ -1772,14 +1765,12 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
                lli_table_ptr--;
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] phys lli_table_ptr->block_size "
-                       "is (hex) %x\n",
+                       "[PID%d] phys lli_table_ptr->block_size is (hex) %x\n",
                        current->pid,
                        lli_table_ptr->block_size);
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] phys lli_table_ptr->physical_address "
-                       "is %08lx\n",
+                       "[PID%d] phys lli_table_ptr->physical_address is %08lx\n",
                        current->pid,
                        (unsigned long)lli_table_ptr->bus_address);
 
@@ -1788,13 +1779,11 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
                num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] phys table_data_size is "
-                       "(hex) %lx num_table_entries is"
-                       " %lx bus_address is%lx\n",
-                               current->pid,
-                               table_data_size,
-                               num_table_entries,
-                               (unsigned long)lli_table_ptr->bus_address);
+                       "[PID%d] phys table_data_size is (hex) %lx num_table_entries is %lx bus_address is%lx\n",
+                       current->pid,
+                       table_data_size,
+                       num_table_entries,
+                       (unsigned long)lli_table_ptr->bus_address);
 
                if ((unsigned long)lli_table_ptr->bus_address != 0xffffffff)
                        lli_table_ptr = (struct sep_lli_entry *)
@@ -2244,14 +2233,12 @@ static int sep_construct_dma_tables_from_lli(
                        table_data_size = out_table_data_size;
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] construct tables from lli"
-                       " in_table_data_size is (hex) %x\n", current->pid,
-                       in_table_data_size);
+                       "[PID%d] construct tables from lli in_table_data_size is (hex) %x\n",
+                       current->pid, in_table_data_size);
 
                dev_dbg(&sep->pdev->dev,
-                       "[PID%d] construct tables from lli"
-                       "out_table_data_size is (hex) %x\n", current->pid,
-                       out_table_data_size);
+                       "[PID%d] construct tables from lli out_table_data_size is (hex) %x\n",
+                       current->pid, out_table_data_size);
 
                /* Construct input lli table */
                sep_build_lli_table(sep, &lli_in_array[current_in_entry],
@@ -2316,8 +2303,7 @@ static int sep_construct_dma_tables_from_lli(
                                info_in_entry_ptr->block_size);
 
                        dev_dbg(&sep->pdev->dev,
-                               "[PID%d] output lli_table_out_ptr:"
-                               "%08lx  %08x\n",
+                               "[PID%d] output lli_table_out_ptr: %08lx  %08x\n",
                                current->pid,
                                (unsigned long)info_out_entry_ptr->bus_address,
                                info_out_entry_ptr->block_size);
@@ -2446,8 +2432,8 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
                                dma_ctx);
                if (error) {
                        dev_warn(&sep->pdev->dev,
-                               "[PID%d] sep_lock_kernel_pages for input "
-                               "virtual buffer failed\n", current->pid);
+                               "[PID%d] sep_lock_kernel_pages for input virtual buffer failed\n",
+                               current->pid);
 
                        goto end_function;
                }
@@ -2460,8 +2446,8 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 
                if (error) {
                        dev_warn(&sep->pdev->dev,
-                               "[PID%d] sep_lock_kernel_pages for output "
-                               "virtual buffer failed\n", current->pid);
+                               "[PID%d] sep_lock_kernel_pages for output virtual buffer failed\n",
+                               current->pid);
 
                        goto end_function_free_lli_in;
                }
@@ -2476,8 +2462,8 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
                                dma_ctx);
                if (error) {
                        dev_warn(&sep->pdev->dev,
-                               "[PID%d] sep_lock_user_pages for input "
-                               "virtual buffer failed\n", current->pid);
+                               "[PID%d] sep_lock_user_pages for input virtual buffer failed\n",
+                               current->pid);
 
                        goto end_function;
                }
@@ -2491,8 +2477,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
                                SEP_DRIVER_OUT_FLAG, dma_ctx);
                        if (error) {
                                dev_warn(&sep->pdev->dev,
-                                       "[PID%d] secure dma table setup "
-                                       " for output virtual buffer failed\n",
+                                       "[PID%d] secure dma table setup for output virtual buffer failed\n",
                                        current->pid);
 
                                goto end_function_free_lli_in;
@@ -2512,8 +2497,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 
                        if (error) {
                                dev_warn(&sep->pdev->dev,
-                                       "[PID%d] sep_lock_user_pages"
-                                       " for output virtual buffer failed\n",
+                                       "[PID%d] sep_lock_user_pages for output virtual buffer failed\n",
                                        current->pid);
 
                                goto end_function_free_lli_in;
@@ -2826,8 +2810,7 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 
        if (error) {
                dev_warn(&sep->pdev->dev,
-                       "prepare DMA table call failed "
-                       "from prepare DCB call\n");
+                       "prepare DMA table call failed from prepare DCB call\n");
                goto end_function_error;
        }
 
@@ -2889,7 +2872,8 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet,
                 * Go over each DCB and see if
                 * tail pointer must be updated
                 */
-               for (i = 0; i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) {
+               for (i = 0; i < (*dma_ctx)->nr_dcb_creat;
+                    i++, dcb_table_ptr++) {
                        if (dcb_table_ptr->out_vr_tail_pt) {
                                pt_hold = (unsigned long)dcb_table_ptr->
                                        out_vr_tail_pt;
@@ -3762,8 +3746,7 @@ static inline ssize_t sep_fastcall_args_get(struct sep_device *sep,
 
        if (actual_count != count_user) {
                dev_warn(&sep->pdev->dev,
-                        "[PID%d] inconsistent message "
-                        "sizes 0x%08zX vs 0x%08zX\n",
+                        "[PID%d] inconsistent message sizes 0x%08zX vs 0x%08zX\n",
                         current->pid, actual_count, count_user);
                error = -EMSGSIZE;
                goto end_function;
index 4c7822bd5358ac1d4ce31fe8239a613b286e8092..702902cdb461d67380b5429f0baa88a76c75605e 100644 (file)
@@ -464,9 +464,12 @@ struct adapter {
        /*
        *  SLIC Handles
        */
-       struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1]; /* Object handles*/
-       struct slic_handle *pfree_slic_handles;          /* Free object handles*/
-       struct slic_spinlock     handle_lock;           /* Object handle list lock*/
+       /* Object handles*/
+       struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1];
+       /* Free object handles*/
+       struct slic_handle *pfree_slic_handles;
+       /* Object handle list lock*/
+       struct slic_spinlock     handle_lock;
        ushort              slic_handle_ix;
 
        u32             xmitq_full;
index e0de4979e1cba75f10ce75f7d26076def1bc2d4f..758c4efea0dedf2d0757b0fae83bd57ea988f206 100644 (file)
@@ -1830,7 +1830,7 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 #endif
 
        seq_printf(seq, "driver_version           : %s\n", slic_proc_version);
-       seq_puts(seq, "Microcode versions:           \n");
+       seq_puts(seq, "Microcode versions:\n");
        seq_printf(seq, "    Gigabit (gb)         : %s %s\n",
                    MOJAVE_UCODE_VERS_STRING, MOJAVE_UCODE_VERS_DATE);
        seq_printf(seq, "    Gigabit Receiver     : %s %s\n",
@@ -1917,16 +1917,14 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 
                        if (config->OEMFruFormat == VENDOR4_FRU_FORMAT) {
                                seq_printf(seq,
-                                           "Serial   #               : "
-                                           "%c%c%c%c%c%c%c%c%c%c%c%c\n",
+                                           "Serial   #               : %c%c%c%c%c%c%c%c%c%c%c%c\n",
                                            fru[8], fru[9], fru[10],
                                            fru[11], fru[12], fru[13],
                                            fru[16], fru[17], fru[18],
                                            fru[19], fru[20], fru[21]);
                        } else {
                                seq_printf(seq,
-                                           "Serial   #               : "
-                                           "%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+                                           "Serial   #               : %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
                                            fru[8], fru[9], fru[10],
                                            fru[11], fru[12], fru[13],
                                            fru[14], fru[15], fru[16],
@@ -1974,8 +1972,7 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
                {
                        seq_puts(seq, "FRU Information:\n");
                        seq_printf(seq,
-                                   "    Part     #           : "
-                                   "%c%c%c%c%c%c%c%c\n",
+                                   "    Part     #           : %c%c%c%c%c%c%c%c\n",
                                    oemfru[0], oemfru[1], oemfru[2],
                                    oemfru[3], oemfru[4], oemfru[5],
                                    oemfru[6], oemfru[7]);
@@ -2002,20 +1999,17 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
                {
                        seq_puts(seq, "FRU Information:\n");
                        seq_printf(seq,
-                                   "    FRU Number           : "
-                                   "%c%c%c%c%c%c%c%c\n",
+                                   "    FRU Number           : %c%c%c%c%c%c%c%c\n",
                                    oemfru[0], oemfru[1], oemfru[2],
                                    oemfru[3], oemfru[4], oemfru[5],
                                    oemfru[6], oemfru[7]);
                        seq_sprintf(seq,
-                                   "    Part Number          : "
-                                   "%c%c%c%c%c%c%c%c\n",
+                                   "    Part Number          : %c%c%c%c%c%c%c%c\n",
                                    oemfru[8], oemfru[9], oemfru[10],
                                    oemfru[11], oemfru[12], oemfru[13],
                                    oemfru[14], oemfru[15]);
                        seq_printf(seq,
-                                   "    EC Level             : "
-                                   "%c%c%c%c%c%c%c%c\n",
+                                   "    EC Level             : %c%c%c%c%c%c%c%c\n",
                                    oemfru[16], oemfru[17], oemfru[18],
                                    oemfru[19], oemfru[20], oemfru[21],
                                    oemfru[22], oemfru[23]);
@@ -2412,8 +2406,7 @@ static void slic_xmit_fail(struct adapter *adapter,
                switch (status) {
                case XMIT_FAIL_LINK_STATE:
                        dev_err(&adapter->netdev->dev,
-                               "reject xmit skb[%p: %x] linkstate[%s] "
-                               "adapter[%s:%d] card[%s:%d]\n",
+                               "reject xmit skb[%p: %x] linkstate[%s] adapter[%s:%d] card[%s:%d]\n",
                                skb, skb->pkt_type,
                                SLIC_LINKSTATE(adapter->linkstate),
                                SLIC_ADAPTER_STATE(adapter->state),
@@ -2428,8 +2421,7 @@ static void slic_xmit_fail(struct adapter *adapter,
                        break;
                case XMIT_FAIL_HOSTCMD_FAIL:
                        dev_err(&adapter->netdev->dev,
-                               "xmit_start skb[%p] type[%x] No host commands "
-                               "available\n", skb, skb->pkt_type);
+                               "xmit_start skb[%p] type[%x] No host commands available\n", skb, skb->pkt_type);
                        break;
                }
        }
@@ -2642,8 +2634,7 @@ static void slic_interrupt_card_up(u32 isr, struct adapter *adapter,
                                }
                        } else if (isr & ISR_XDROP) {
                                dev_err(&dev->dev,
-                                               "isr & ISR_ERR [%x] "
-                                               "ISR_XDROP \n", isr);
+                                               "isr & ISR_ERR [%x] ISR_XDROP\n", isr);
                        } else {
                                dev_err(&dev->dev,
                                                "isr & ISR_ERR [%x]\n",
@@ -3269,8 +3260,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter)
 
                if (!peeprom) {
                        dev_err(&adapter->pcidev->dev,
-                               "eeprom read failed to get memory "
-                               "bus %d slot %d\n", adapter->busnumber,
+                               "eeprom read failed to get memory bus %d slot %d\n", adapter->busnumber,
                                adapter->slotnumber);
                        return -ENOMEM;
                } else {
diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig
deleted file mode 100644 (file)
index e2922ae..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-config FB_SM7XX
-       tristate "Silicon Motion SM7XX framebuffer support"
-       depends on FB && PCI
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         Frame buffer driver for the Silicon Motion SM710, SM712, SM721
-         and SM722 chips.
-
-         This driver is also available as a module. The module will be
-         called sm7xxfb. If you want to compile it as a module, say M
-         here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile
deleted file mode 100644 (file)
index 48f471c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o
diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO
deleted file mode 100644 (file)
index 1fcead5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO:
-- Dual head support
-- 2D acceleration support
-- use kernel coding style
-- refine the code and remove unused code
-- move it to drivers/video/sm7xxfb.c
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
-Teddy Wang <teddy.wang@siliconmotion.com.cn>.
diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h
deleted file mode 100644 (file)
index 8599861..0000000
+++ /dev/null
@@ -1,779 +0,0 @@
-/*
- * Silicon Motion SM712 frame buffer device
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors:    Ge Wang, gewang@siliconmotion.com
- *             Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.com
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#define NR_PALETTE        256
-
-#define FB_ACCEL_SMI_LYNX 88
-
-#define SCREEN_X_RES      1024
-#define SCREEN_Y_RES      600
-#define SCREEN_BPP        16
-
-/*Assume SM712 graphics chip has 4MB VRAM */
-#define SM712_VIDEOMEMORYSIZE    0x00400000
-/*Assume SM722 graphics chip has 8MB VRAM */
-#define SM722_VIDEOMEMORYSIZE    0x00800000
-
-#define dac_reg        (0x3c8)
-#define dac_val        (0x3c9)
-
-extern void __iomem *smtc_RegBaseAddress;
-#define smtc_mmiowb(dat, reg)  writeb(dat, smtc_RegBaseAddress + reg)
-#define smtc_mmioww(dat, reg)  writew(dat, smtc_RegBaseAddress + reg)
-#define smtc_mmiowl(dat, reg)  writel(dat, smtc_RegBaseAddress + reg)
-
-#define smtc_mmiorb(reg)       readb(smtc_RegBaseAddress + reg)
-#define smtc_mmiorw(reg)       readw(smtc_RegBaseAddress + reg)
-#define smtc_mmiorl(reg)       readl(smtc_RegBaseAddress + reg)
-
-#define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
-#define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
-#define SIZE_SR30_SR75      (0x75 - 0x30 + 1)
-#define SIZE_SR80_SR93      (0x93 - 0x80 + 1)
-#define SIZE_SRA0_SRAF      (0xAF - 0xA0 + 1)
-#define SIZE_GR00_GR08      (0x08 - 0x00 + 1)
-#define SIZE_AR00_AR14      (0x14 - 0x00 + 1)
-#define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
-#define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
-#define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
-#define SIZE_VPR               (0x6C + 1)
-#define SIZE_DPR               (0x44 + 1)
-
-static inline void smtc_crtcw(int reg, int val)
-{
-       smtc_mmiowb(reg, 0x3d4);
-       smtc_mmiowb(val, 0x3d5);
-}
-
-static inline unsigned int smtc_crtcr(int reg)
-{
-       smtc_mmiowb(reg, 0x3d4);
-       return smtc_mmiorb(0x3d5);
-}
-
-static inline void smtc_grphw(int reg, int val)
-{
-       smtc_mmiowb(reg, 0x3ce);
-       smtc_mmiowb(val, 0x3cf);
-}
-
-static inline unsigned int smtc_grphr(int reg)
-{
-       smtc_mmiowb(reg, 0x3ce);
-       return smtc_mmiorb(0x3cf);
-}
-
-static inline void smtc_attrw(int reg, int val)
-{
-       smtc_mmiorb(0x3da);
-       smtc_mmiowb(reg, 0x3c0);
-       smtc_mmiorb(0x3c1);
-       smtc_mmiowb(val, 0x3c0);
-}
-
-static inline void smtc_seqw(int reg, int val)
-{
-       smtc_mmiowb(reg, 0x3c4);
-       smtc_mmiowb(val, 0x3c5);
-}
-
-static inline unsigned int smtc_seqr(int reg)
-{
-       smtc_mmiowb(reg, 0x3c4);
-       return smtc_mmiorb(0x3c5);
-}
-
-/* The next structure holds all information relevant for a specific video mode.
- */
-
-struct ModeInit {
-       int mmSizeX;
-       int mmSizeY;
-       int bpp;
-       int hz;
-       unsigned char Init_MISC;
-       unsigned char Init_SR00_SR04[SIZE_SR00_SR04];
-       unsigned char Init_SR10_SR24[SIZE_SR10_SR24];
-       unsigned char Init_SR30_SR75[SIZE_SR30_SR75];
-       unsigned char Init_SR80_SR93[SIZE_SR80_SR93];
-       unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF];
-       unsigned char Init_GR00_GR08[SIZE_GR00_GR08];
-       unsigned char Init_AR00_AR14[SIZE_AR00_AR14];
-       unsigned char Init_CR00_CR18[SIZE_CR00_CR18];
-       unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D];
-       unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7];
-};
-
-/**********************************************************************
-                        SM712 Mode table.
- **********************************************************************/
-struct ModeInit VGAMode[] = {
-       {
-        /*  mode#0: 640 x 480  16Bpp  60Hz */
-        640, 480, 16, 60,
-        /*  Init_MISC */
-        0xE3,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x00, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-         },
-        },
-       {
-        /*  mode#1: 640 x 480  24Bpp  60Hz */
-        640, 480, 24, 60,
-        /*  Init_MISC */
-        0xE3,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x00, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-         },
-        },
-       {
-        /*  mode#0: 640 x 480  32Bpp  60Hz */
-        640, 480, 32, 60,
-        /*  Init_MISC */
-        0xE3,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x00, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-         },
-        },
-
-       {                       /*  mode#2: 800 x 600  16Bpp  60Hz */
-        800, 600, 16, 60,
-        /*  Init_MISC */
-        0x2B,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
-         0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
-         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-         0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
-         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-         0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
-         0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-         },
-        },
-       {                       /*  mode#3: 800 x 600  24Bpp  60Hz */
-        800, 600, 24, 60,
-        0x2B,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
-         0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
-         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-         0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-         0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
-         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-         },
-        },
-       {                       /*  mode#7: 800 x 600  32Bpp  60Hz */
-        800, 600, 32, 60,
-        /*  Init_MISC */
-        0x2B,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
-         0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
-         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-         0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
-         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-         0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
-         0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-         },
-        },
-       /* We use 1024x768 table to light 1024x600 panel for lemote */
-       {                       /*  mode#4: 1024 x 600  16Bpp  60Hz  */
-        1024, 600, 16, 60,
-        /*  Init_MISC */
-        0xEB,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x00, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
-         0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x00, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
-         0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
-         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-         0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
-         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
-         0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-         0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
-         0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-         },
-        },
-       {                       /*  mode#5: 1024 x 768  24Bpp  60Hz */
-        1024, 768, 24, 60,
-        /*  Init_MISC */
-        0xEB,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x30, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
-         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-         0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
-         0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-         },
-        },
-       {                       /*  mode#4: 1024 x 768  32Bpp  60Hz */
-        1024, 768, 32, 60,
-        /*  Init_MISC */
-        0xEB,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x32, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
-         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-         0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
-         0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-         },
-        },
-       {                       /*  mode#6: 320 x 240  16Bpp  60Hz */
-        320, 240, 16, 60,
-        /*  Init_MISC */
-        0xEB,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x32, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
-         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-         0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-         0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
-         0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-         },
-        },
-
-       {                       /*  mode#8: 320 x 240  32Bpp  60Hz */
-        320, 240, 32, 60,
-        /*  Init_MISC */
-        0xEB,
-        {                      /*  Init_SR0_SR4 */
-         0x03, 0x01, 0x0F, 0x03, 0x0E,
-         },
-        {                      /*  Init_SR10_SR24 */
-         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xC4, 0x32, 0x02, 0x01, 0x01,
-         },
-        {                      /*  Init_SR30_SR75 */
-         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-         0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
-         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-         },
-        {                      /*  Init_SR80_SR93 */
-         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-         0x00, 0x00, 0x00, 0x00,
-         },
-        {                      /*  Init_SRA0_SRAF */
-         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-         },
-        {                      /*  Init_GR00_GR08 */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-         0xFF,
-         },
-        {                      /*  Init_AR00_AR14 */
-         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-         0x41, 0x00, 0x0F, 0x00, 0x00,
-         },
-        {                      /*  Init_CR00_CR18 */
-         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-         0xFF,
-         },
-        {                      /*  Init_CR30_CR4D */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-         0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-         0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
-         0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
-         },
-        {                      /*  Init_CR90_CRA7 */
-         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-         },
-        },
-};
-
-#define numVGAModes            ARRAY_SIZE(VGAMode)
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
deleted file mode 100644 (file)
index 6176d98..0000000
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*
- * Silicon Motion SM7XX frame buffer device
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors:  Ge Wang, gewang@siliconmotion.com
- *          Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author:   Wu Zhangjin, wuzhangjin@gmail.com
- *
- * Copyright (C) 2011 Igalia, S.L.
- * Author:   Javier M. Mellid <jmunhoz@igalia.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
- */
-
-#include <linux/io.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/screen_info.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include "sm7xx.h"
-
-/*
-* Private structure
-*/
-struct smtcfb_info {
-       struct pci_dev *pdev;
-       struct fb_info fb;
-       u16 chip_id;
-       u8  chip_rev_id;
-
-       void __iomem *lfb;      /* linear frame buffer */
-       void __iomem *dp_regs;  /* drawing processor control regs */
-       void __iomem *vp_regs;  /* video processor control regs */
-       void __iomem *cp_regs;  /* capture processor control regs */
-       void __iomem *mmio;     /* memory map IO port */
-
-       u_int width;
-       u_int height;
-       u_int hz;
-
-       u32 colreg[17];
-};
-
-void __iomem *smtc_RegBaseAddress;     /* Memory Map IO starting address */
-
-static struct fb_var_screeninfo smtcfb_var = {
-       .xres           = 1024,
-       .yres           = 600,
-       .xres_virtual   = 1024,
-       .yres_virtual   = 600,
-       .bits_per_pixel = 16,
-       .red            = {16, 8, 0},
-       .green          = {8, 8, 0},
-       .blue           = {0, 8, 0},
-       .activate       = FB_ACTIVATE_NOW,
-       .height         = -1,
-       .width          = -1,
-       .vmode          = FB_VMODE_NONINTERLACED,
-       .nonstd         = 0,
-       .accel_flags    = FB_ACCELF_TEXT,
-};
-
-static struct fb_fix_screeninfo smtcfb_fix = {
-       .id             = "smXXXfb",
-       .type           = FB_TYPE_PACKED_PIXELS,
-       .visual         = FB_VISUAL_TRUECOLOR,
-       .line_length    = 800 * 3,
-       .accel          = FB_ACCEL_SMI_LYNX,
-       .type_aux       = 0,
-       .xpanstep       = 0,
-       .ypanstep       = 0,
-       .ywrapstep      = 0,
-};
-
-struct vesa_mode {
-       char index[6];
-       u16  lfb_width;
-       u16  lfb_height;
-       u16  lfb_depth;
-};
-
-static struct vesa_mode vesa_mode_table[] = {
-       {"0x301", 640,  480,  8},
-       {"0x303", 800,  600,  8},
-       {"0x305", 1024, 768,  8},
-       {"0x307", 1280, 1024, 8},
-
-       {"0x311", 640,  480,  16},
-       {"0x314", 800,  600,  16},
-       {"0x317", 1024, 768,  16},
-       {"0x31A", 1280, 1024, 16},
-
-       {"0x312", 640,  480,  24},
-       {"0x315", 800,  600,  24},
-       {"0x318", 1024, 768,  24},
-       {"0x31B", 1280, 1024, 24},
-};
-
-struct screen_info smtc_scr_info;
-
-/* process command line options, get vga parameter */
-static int __init sm7xx_vga_setup(char *options)
-{
-       int i;
-
-       if (!options || !*options)
-               return -EINVAL;
-
-       smtc_scr_info.lfb_width = 0;
-       smtc_scr_info.lfb_height = 0;
-       smtc_scr_info.lfb_depth = 0;
-
-       pr_debug("sm7xx_vga_setup = %s\n", options);
-
-       for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
-               if (strstr(options, vesa_mode_table[i].index)) {
-                       smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
-                       smtc_scr_info.lfb_height =
-                                               vesa_mode_table[i].lfb_height;
-                       smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
-                       return 0;
-               }
-       }
-
-       return -1;
-}
-__setup("vga=", sm7xx_vga_setup);
-
-static void sm712_setpalette(int regno, unsigned red, unsigned green,
-                            unsigned blue, struct fb_info *info)
-{
-       /* set bit 5:4 = 01 (write LCD RAM only) */
-       smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
-
-       smtc_mmiowb(regno, dac_reg);
-       smtc_mmiowb(red >> 10, dac_val);
-       smtc_mmiowb(green >> 10, dac_val);
-       smtc_mmiowb(blue >> 10, dac_val);
-}
-
-/* chan_to_field
- *
- * convert a colour value into a field position
- *
- * from pxafb.c
- */
-
-static inline unsigned int chan_to_field(unsigned int chan,
-                                        struct fb_bitfield *bf)
-{
-       chan &= 0xffff;
-       chan >>= 16 - bf->length;
-       return chan << bf->offset;
-}
-
-static int smtc_blank(int blank_mode, struct fb_info *info)
-{
-       /* clear DPMS setting */
-       switch (blank_mode) {
-       case FB_BLANK_UNBLANK:
-               /* Screen On: HSync: On, VSync : On */
-               smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
-               smtc_seqw(0x6a, 0x16);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
-               smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
-               smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
-               smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
-               smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
-               break;
-       case FB_BLANK_NORMAL:
-               /* Screen Off: HSync: On, VSync : On   Soft blank */
-               smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
-               smtc_seqw(0x6a, 0x16);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
-               smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
-               smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
-               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-               break;
-       case FB_BLANK_VSYNC_SUSPEND:
-               /* Screen On: HSync: On, VSync : Off */
-               smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-               smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-               smtc_seqw(0x6a, 0x0c);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-               smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
-               smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
-               smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-               smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-               break;
-       case FB_BLANK_HSYNC_SUSPEND:
-               /* Screen On: HSync: Off, VSync : On */
-               smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-               smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-               smtc_seqw(0x6a, 0x0c);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-               smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
-               smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
-               smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-               smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-               break;
-       case FB_BLANK_POWERDOWN:
-               /* Screen On: HSync: Off, VSync : Off */
-               smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-               smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-               smtc_seqw(0x6a, 0x0c);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-               smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
-               smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
-               smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-               smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
-                         unsigned blue, unsigned trans, struct fb_info *info)
-{
-       struct smtcfb_info *sfb;
-       u32 val;
-
-       sfb = info->par;
-
-       if (regno > 255)
-               return 1;
-
-       switch (sfb->fb.fix.visual) {
-       case FB_VISUAL_DIRECTCOLOR:
-       case FB_VISUAL_TRUECOLOR:
-               /*
-                * 16/32 bit true-colour, use pseudo-palette for 16 base color
-                */
-               if (regno < 16) {
-                       if (sfb->fb.var.bits_per_pixel == 16) {
-                               u32 *pal = sfb->fb.pseudo_palette;
-                               val = chan_to_field(red, &sfb->fb.var.red);
-                               val |= chan_to_field(green, &sfb->fb.var.green);
-                               val |= chan_to_field(blue, &sfb->fb.var.blue);
-#ifdef __BIG_ENDIAN
-                               pal[regno] =
-                                   ((red & 0xf800) >> 8) |
-                                   ((green & 0xe000) >> 13) |
-                                   ((green & 0x1c00) << 3) |
-                                   ((blue & 0xf800) >> 3);
-#else
-                               pal[regno] = val;
-#endif
-                       } else {
-                               u32 *pal = sfb->fb.pseudo_palette;
-                               val = chan_to_field(red, &sfb->fb.var.red);
-                               val |= chan_to_field(green, &sfb->fb.var.green);
-                               val |= chan_to_field(blue, &sfb->fb.var.blue);
-#ifdef __BIG_ENDIAN
-                               val =
-                                   (val & 0xff00ff00 >> 8) |
-                                   (val & 0x00ff00ff << 8);
-#endif
-                               pal[regno] = val;
-                       }
-               }
-               break;
-
-       case FB_VISUAL_PSEUDOCOLOR:
-               /* color depth 8 bit */
-               sm712_setpalette(regno, red, green, blue, info);
-               break;
-
-       default:
-               return 1;       /* unknown type */
-       }
-
-       return 0;
-
-}
-
-#ifdef __BIG_ENDIAN
-static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t
-                               count, loff_t *ppos)
-{
-       unsigned long p = *ppos;
-
-       u32 *buffer, *dst;
-       u32 __iomem *src;
-       int c, i, cnt = 0, err = 0;
-       unsigned long total_size;
-
-       if (!info || !info->screen_base)
-               return -ENODEV;
-
-       if (info->state != FBINFO_STATE_RUNNING)
-               return -EPERM;
-
-       total_size = info->screen_size;
-
-       if (total_size == 0)
-               total_size = info->fix.smem_len;
-
-       if (p >= total_size)
-               return 0;
-
-       if (count >= total_size)
-               count = total_size;
-
-       if (count + p > total_size)
-               count = total_size - p;
-
-       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       src = (u32 __iomem *) (info->screen_base + p);
-
-       if (info->fbops->fb_sync)
-               info->fbops->fb_sync(info);
-
-       while (count) {
-               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-               dst = buffer;
-               for (i = c >> 2; i--;) {
-                       *dst = fb_readl(src++);
-                       *dst =
-                           (*dst & 0xff00ff00 >> 8) |
-                           (*dst & 0x00ff00ff << 8);
-                       dst++;
-               }
-               if (c & 3) {
-                       u8 *dst8 = (u8 *) dst;
-                       u8 __iomem *src8 = (u8 __iomem *) src;
-
-                       for (i = c & 3; i--;) {
-                               if (i & 1) {
-                                       *dst8++ = fb_readb(++src8);
-                               } else {
-                                       *dst8++ = fb_readb(--src8);
-                                       src8 += 2;
-                               }
-                       }
-                       src = (u32 __iomem *) src8;
-               }
-
-               if (copy_to_user(buf, buffer, c)) {
-                       err = -EFAULT;
-                       break;
-               }
-               *ppos += c;
-               buf += c;
-               cnt += c;
-               count -= c;
-       }
-
-       kfree(buffer);
-
-       return (err) ? err : cnt;
-}
-
-static ssize_t
-smtcfb_write(struct fb_info *info, const char __user *buf, size_t count,
-            loff_t *ppos)
-{
-       unsigned long p = *ppos;
-
-       u32 *buffer, *src;
-       u32 __iomem *dst;
-       int c, i, cnt = 0, err = 0;
-       unsigned long total_size;
-
-       if (!info || !info->screen_base)
-               return -ENODEV;
-
-       if (info->state != FBINFO_STATE_RUNNING)
-               return -EPERM;
-
-       total_size = info->screen_size;
-
-       if (total_size == 0)
-               total_size = info->fix.smem_len;
-
-       if (p > total_size)
-               return -EFBIG;
-
-       if (count > total_size) {
-               err = -EFBIG;
-               count = total_size;
-       }
-
-       if (count + p > total_size) {
-               if (!err)
-                       err = -ENOSPC;
-
-               count = total_size - p;
-       }
-
-       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       dst = (u32 __iomem *) (info->screen_base + p);
-
-       if (info->fbops->fb_sync)
-               info->fbops->fb_sync(info);
-
-       while (count) {
-               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-               src = buffer;
-
-               if (copy_from_user(src, buf, c)) {
-                       err = -EFAULT;
-                       break;
-               }
-
-               for (i = c >> 2; i--;) {
-                       fb_writel((*src & 0xff00ff00 >> 8) |
-                                 (*src & 0x00ff00ff << 8), dst++);
-                       src++;
-               }
-               if (c & 3) {
-                       u8 *src8 = (u8 *) src;
-                       u8 __iomem *dst8 = (u8 __iomem *) dst;
-
-                       for (i = c & 3; i--;) {
-                               if (i & 1) {
-                                       fb_writeb(*src8++, ++dst8);
-                               } else {
-                                       fb_writeb(*src8++, --dst8);
-                                       dst8 += 2;
-                               }
-                       }
-                       dst = (u32 __iomem *) dst8;
-               }
-
-               *ppos += c;
-               buf += c;
-               cnt += c;
-               count -= c;
-       }
-
-       kfree(buffer);
-
-       return (cnt) ? cnt : err;
-}
-#endif /* ! __BIG_ENDIAN */
-
-static void sm7xx_set_timing(struct smtcfb_info *sfb)
-{
-       int i = 0, j = 0;
-       u32 m_nScreenStride;
-
-       dev_dbg(&sfb->pdev->dev,
-               "sfb->width=%d sfb->height=%d "
-               "sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n",
-               sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz);
-
-       for (j = 0; j < numVGAModes; j++) {
-               if (VGAMode[j].mmSizeX == sfb->width &&
-                   VGAMode[j].mmSizeY == sfb->height &&
-                   VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
-                   VGAMode[j].hz == sfb->hz) {
-
-                       dev_dbg(&sfb->pdev->dev,
-                               "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d "
-                               "VGAMode[j].bpp=%d VGAMode[j].hz=%d\n",
-                               VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
-                               VGAMode[j].bpp, VGAMode[j].hz);
-
-                       dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j);
-
-                       smtc_mmiowb(0x0, 0x3c6);
-
-                       smtc_seqw(0, 0x1);
-
-                       smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
-
-                       /* init SEQ register SR00 - SR04 */
-                       for (i = 0; i < SIZE_SR00_SR04; i++)
-                               smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]);
-
-                       /* init SEQ register SR10 - SR24 */
-                       for (i = 0; i < SIZE_SR10_SR24; i++)
-                               smtc_seqw(i + 0x10,
-                                         VGAMode[j].Init_SR10_SR24[i]);
-
-                       /* init SEQ register SR30 - SR75 */
-                       for (i = 0; i < SIZE_SR30_SR75; i++)
-                               if ((i + 0x30) != 0x62 &&
-                                   (i + 0x30) != 0x6a &&
-                                   (i + 0x30) != 0x6b)
-                                       smtc_seqw(i + 0x30,
-                                               VGAMode[j].Init_SR30_SR75[i]);
-
-                       /* init SEQ register SR80 - SR93 */
-                       for (i = 0; i < SIZE_SR80_SR93; i++)
-                               smtc_seqw(i + 0x80,
-                                         VGAMode[j].Init_SR80_SR93[i]);
-
-                       /* init SEQ register SRA0 - SRAF */
-                       for (i = 0; i < SIZE_SRA0_SRAF; i++)
-                               smtc_seqw(i + 0xa0,
-                                         VGAMode[j].Init_SRA0_SRAF[i]);
-
-                       /* init Graphic register GR00 - GR08 */
-                       for (i = 0; i < SIZE_GR00_GR08; i++)
-                               smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]);
-
-                       /* init Attribute register AR00 - AR14 */
-                       for (i = 0; i < SIZE_AR00_AR14; i++)
-                               smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]);
-
-                       /* init CRTC register CR00 - CR18 */
-                       for (i = 0; i < SIZE_CR00_CR18; i++)
-                               smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]);
-
-                       /* init CRTC register CR30 - CR4D */
-                       for (i = 0; i < SIZE_CR30_CR4D; i++)
-                               smtc_crtcw(i + 0x30,
-                                          VGAMode[j].Init_CR30_CR4D[i]);
-
-                       /* init CRTC register CR90 - CRA7 */
-                       for (i = 0; i < SIZE_CR90_CRA7; i++)
-                               smtc_crtcw(i + 0x90,
-                                          VGAMode[j].Init_CR90_CRA7[i]);
-               }
-       }
-       smtc_mmiowb(0x67, 0x3c2);
-
-       /* set VPR registers */
-       writel(0x0, sfb->vp_regs + 0x0C);
-       writel(0x0, sfb->vp_regs + 0x40);
-
-       /* set data width */
-       m_nScreenStride =
-               (sfb->width * sfb->fb.var.bits_per_pixel) / 64;
-       switch (sfb->fb.var.bits_per_pixel) {
-       case 8:
-               writel(0x0, sfb->vp_regs + 0x0);
-               break;
-       case 16:
-               writel(0x00020000, sfb->vp_regs + 0x0);
-               break;
-       case 24:
-               writel(0x00040000, sfb->vp_regs + 0x0);
-               break;
-       case 32:
-               writel(0x00030000, sfb->vp_regs + 0x0);
-               break;
-       }
-       writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
-              sfb->vp_regs + 0x10);
-
-}
-
-static void smtc_set_timing(struct smtcfb_info *sfb)
-{
-       switch (sfb->chip_id) {
-       case 0x710:
-       case 0x712:
-       case 0x720:
-               sm7xx_set_timing(sfb);
-               break;
-       }
-}
-
-static void smtcfb_setmode(struct smtcfb_info *sfb)
-{
-       switch (sfb->fb.var.bits_per_pixel) {
-       case 32:
-               sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-               sfb->fb.fix.line_length  = sfb->fb.var.xres * 4;
-               sfb->fb.var.red.length   = 8;
-               sfb->fb.var.green.length = 8;
-               sfb->fb.var.blue.length  = 8;
-               sfb->fb.var.red.offset   = 16;
-               sfb->fb.var.green.offset = 8;
-               sfb->fb.var.blue.offset  = 0;
-               break;
-       case 24:
-               sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-               sfb->fb.fix.line_length  = sfb->fb.var.xres * 3;
-               sfb->fb.var.red.length   = 8;
-               sfb->fb.var.green.length = 8;
-               sfb->fb.var.blue.length  = 8;
-               sfb->fb.var.red.offset   = 16;
-               sfb->fb.var.green.offset = 8;
-               sfb->fb.var.blue.offset  = 0;
-               break;
-       case 8:
-               sfb->fb.fix.visual       = FB_VISUAL_PSEUDOCOLOR;
-               sfb->fb.fix.line_length  = sfb->fb.var.xres;
-               sfb->fb.var.red.length   = 3;
-               sfb->fb.var.green.length = 3;
-               sfb->fb.var.blue.length  = 2;
-               sfb->fb.var.red.offset   = 5;
-               sfb->fb.var.green.offset = 2;
-               sfb->fb.var.blue.offset  = 0;
-               break;
-       case 16:
-       default:
-               sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-               sfb->fb.fix.line_length  = sfb->fb.var.xres * 2;
-               sfb->fb.var.red.length   = 5;
-               sfb->fb.var.green.length = 6;
-               sfb->fb.var.blue.length  = 5;
-               sfb->fb.var.red.offset   = 11;
-               sfb->fb.var.green.offset = 5;
-               sfb->fb.var.blue.offset  = 0;
-               break;
-       }
-
-       sfb->width  = sfb->fb.var.xres;
-       sfb->height = sfb->fb.var.yres;
-       sfb->hz = 60;
-       smtc_set_timing(sfb);
-}
-
-static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-       /* sanity checks */
-       if (var->xres_virtual < var->xres)
-               var->xres_virtual = var->xres;
-
-       if (var->yres_virtual < var->yres)
-               var->yres_virtual = var->yres;
-
-       /* set valid default bpp */
-       if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
-           (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
-               var->bits_per_pixel = 16;
-
-       return 0;
-}
-
-static int smtc_set_par(struct fb_info *info)
-{
-       smtcfb_setmode(info->par);
-
-       return 0;
-}
-
-static struct fb_ops smtcfb_ops = {
-       .owner        = THIS_MODULE,
-       .fb_check_var = smtc_check_var,
-       .fb_set_par   = smtc_set_par,
-       .fb_setcolreg = smtc_setcolreg,
-       .fb_blank     = smtc_blank,
-       .fb_fillrect  = cfb_fillrect,
-       .fb_imageblit = cfb_imageblit,
-       .fb_copyarea  = cfb_copyarea,
-#ifdef __BIG_ENDIAN
-       .fb_read      = smtcfb_read,
-       .fb_write     = smtcfb_write,
-#endif
-};
-
-/*
- * alloc struct smtcfb_info and assign default values
- */
-static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev)
-{
-       struct smtcfb_info *sfb;
-
-       sfb = kzalloc(sizeof(*sfb), GFP_KERNEL);
-
-       if (!sfb)
-               return NULL;
-
-       sfb->pdev = pdev;
-
-       sfb->fb.flags          = FBINFO_FLAG_DEFAULT;
-       sfb->fb.fbops          = &smtcfb_ops;
-       sfb->fb.fix            = smtcfb_fix;
-       sfb->fb.var            = smtcfb_var;
-       sfb->fb.pseudo_palette = sfb->colreg;
-       sfb->fb.par            = sfb;
-
-       return sfb;
-}
-
-/*
- * free struct smtcfb_info
- */
-static void smtc_free_fb_info(struct smtcfb_info *sfb)
-{
-       kfree(sfb);
-}
-
-/*
- * Unmap in the memory mapped IO registers
- */
-
-static void smtc_unmap_mmio(struct smtcfb_info *sfb)
-{
-       if (sfb && smtc_RegBaseAddress)
-               smtc_RegBaseAddress = NULL;
-}
-
-/*
- * Map in the screen memory
- */
-
-static int smtc_map_smem(struct smtcfb_info *sfb,
-               struct pci_dev *pdev, u_long smem_len)
-{
-
-       sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);
-
-#ifdef __BIG_ENDIAN
-       if (sfb->fb.var.bits_per_pixel == 32)
-               sfb->fb.fix.smem_start += 0x800000;
-#endif
-
-       sfb->fb.fix.smem_len = smem_len;
-
-       sfb->fb.screen_base = sfb->lfb;
-
-       if (!sfb->fb.screen_base) {
-               dev_err(&pdev->dev,
-                       "%s: unable to map screen memory\n", sfb->fb.fix.id);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-/*
- * Unmap in the screen memory
- *
- */
-static void smtc_unmap_smem(struct smtcfb_info *sfb)
-{
-       if (sfb && sfb->fb.screen_base) {
-               iounmap(sfb->fb.screen_base);
-               sfb->fb.screen_base = NULL;
-       }
-}
-
-/*
- * We need to wake up the device and make sure its in linear memory mode.
- */
-static inline void sm7xx_init_hw(void)
-{
-       outb_p(0x18, 0x3c4);
-       outb_p(0x11, 0x3c5);
-}
-
-static int smtcfb_pci_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
-{
-       struct smtcfb_info *sfb;
-       u_long smem_size = 0x00800000;  /* default 8MB */
-       int err;
-       unsigned long mmio_base;
-
-       dev_info(&pdev->dev, "Silicon Motion display driver.");
-
-       err = pci_enable_device(pdev);  /* enable SMTC chip */
-       if (err)
-               return err;
-
-       sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
-
-       sfb = smtc_alloc_fb_info(pdev);
-
-       if (!sfb) {
-               err = -ENOMEM;
-               goto failed_free;
-       }
-
-       sfb->chip_id = ent->device;
-
-       pci_set_drvdata(pdev, sfb);
-
-       sm7xx_init_hw();
-
-       /* get mode parameter from smtc_scr_info */
-       if (smtc_scr_info.lfb_width != 0) {
-               sfb->fb.var.xres = smtc_scr_info.lfb_width;
-               sfb->fb.var.yres = smtc_scr_info.lfb_height;
-               sfb->fb.var.bits_per_pixel = smtc_scr_info.lfb_depth;
-       } else {
-               /* default resolution 1024x600 16bit mode */
-               sfb->fb.var.xres = SCREEN_X_RES;
-               sfb->fb.var.yres = SCREEN_Y_RES;
-               sfb->fb.var.bits_per_pixel = SCREEN_BPP;
-       }
-
-#ifdef __BIG_ENDIAN
-       if (sfb->fb.var.bits_per_pixel == 24)
-               sfb->fb.var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32);
-#endif
-       /* Map address and memory detection */
-       mmio_base = pci_resource_start(pdev, 0);
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
-
-       switch (sfb->chip_id) {
-       case 0x710:
-       case 0x712:
-               sfb->fb.fix.mmio_start = mmio_base + 0x00400000;
-               sfb->fb.fix.mmio_len = 0x00400000;
-               smem_size = SM712_VIDEOMEMORYSIZE;
-#ifdef __BIG_ENDIAN
-               sfb->lfb = ioremap(mmio_base, 0x00c00000);
-#else
-               sfb->lfb = ioremap(mmio_base, 0x00800000);
-#endif
-               sfb->mmio = (smtc_RegBaseAddress =
-                   sfb->lfb + 0x00700000);
-               sfb->dp_regs = sfb->lfb + 0x00408000;
-               sfb->vp_regs = sfb->lfb + 0x0040c000;
-#ifdef __BIG_ENDIAN
-               if (sfb->fb.var.bits_per_pixel == 32) {
-                       sfb->lfb += 0x800000;
-                       dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb);
-               }
-#endif
-               if (!smtc_RegBaseAddress) {
-                       dev_err(&pdev->dev,
-                               "%s: unable to map memory mapped IO!",
-                               sfb->fb.fix.id);
-                       err = -ENOMEM;
-                       goto failed_fb;
-               }
-
-               /* set MCLK = 14.31818 * (0x16 / 0x2) */
-               smtc_seqw(0x6a, 0x16);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x62, 0x3e);
-               /* enable PCI burst */
-               smtc_seqw(0x17, 0x20);
-               /* enable word swap */
-#ifdef __BIG_ENDIAN
-               if (sfb->fb.var.bits_per_pixel == 32)
-                       smtc_seqw(0x17, 0x30);
-#endif
-               break;
-       case 0x720:
-               sfb->fb.fix.mmio_start = mmio_base;
-               sfb->fb.fix.mmio_len = 0x00200000;
-               smem_size = SM722_VIDEOMEMORYSIZE;
-               sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
-               sfb->lfb = sfb->dp_regs + 0x00200000;
-               sfb->mmio = (smtc_RegBaseAddress =
-                   sfb->dp_regs + 0x000c0000);
-               sfb->vp_regs = sfb->dp_regs + 0x800;
-
-               smtc_seqw(0x62, 0xff);
-               smtc_seqw(0x6a, 0x0d);
-               smtc_seqw(0x6b, 0x02);
-               break;
-       default:
-               dev_err(&pdev->dev,
-                       "No valid Silicon Motion display chip was detected!");
-
-               goto failed_fb;
-       }
-
-       /* can support 32 bpp */
-       if (15 == sfb->fb.var.bits_per_pixel)
-               sfb->fb.var.bits_per_pixel = 16;
-
-       sfb->fb.var.xres_virtual = sfb->fb.var.xres;
-       sfb->fb.var.yres_virtual = sfb->fb.var.yres;
-       err = smtc_map_smem(sfb, pdev, smem_size);
-       if (err)
-               goto failed;
-
-       smtcfb_setmode(sfb);
-
-       err = register_framebuffer(&sfb->fb);
-       if (err < 0)
-               goto failed;
-
-       dev_info(&pdev->dev,
-                "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.",
-                sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres,
-                sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);
-
-       return 0;
-
-failed:
-       dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.");
-
-       smtc_unmap_smem(sfb);
-       smtc_unmap_mmio(sfb);
-failed_fb:
-       smtc_free_fb_info(sfb);
-
-failed_free:
-       pci_disable_device(pdev);
-
-       return err;
-}
-
-/*
- * 0x710 (LynxEM)
- * 0x712 (LynxEM+)
- * 0x720 (Lynx3DM, Lynx3DM+)
- */
-static const struct pci_device_id smtcfb_pci_table[] = {
-       { PCI_DEVICE(0x126f, 0x710), },
-       { PCI_DEVICE(0x126f, 0x712), },
-       { PCI_DEVICE(0x126f, 0x720), },
-       {0,}
-};
-
-static void smtcfb_pci_remove(struct pci_dev *pdev)
-{
-       struct smtcfb_info *sfb;
-
-       sfb = pci_get_drvdata(pdev);
-       smtc_unmap_smem(sfb);
-       smtc_unmap_mmio(sfb);
-       unregister_framebuffer(&sfb->fb);
-       smtc_free_fb_info(sfb);
-}
-
-#ifdef CONFIG_PM
-static int smtcfb_pci_suspend(struct device *device)
-{
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct smtcfb_info *sfb;
-
-       sfb = pci_get_drvdata(pdev);
-
-       /* set the hw in sleep mode use external clock and self memory refresh
-        * so that we can turn off internal PLLs later on
-        */
-       smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
-       smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
-
-       console_lock();
-       fb_set_suspend(&sfb->fb, 1);
-       console_unlock();
-
-       /* additionally turn off all function blocks including internal PLLs */
-       smtc_seqw(0x21, 0xff);
-
-       return 0;
-}
-
-static int smtcfb_pci_resume(struct device *device)
-{
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct smtcfb_info *sfb;
-
-       sfb = pci_get_drvdata(pdev);
-
-       /* reinit hardware */
-       sm7xx_init_hw();
-       switch (sfb->chip_id) {
-       case 0x710:
-       case 0x712:
-               /* set MCLK = 14.31818 *  (0x16 / 0x2) */
-               smtc_seqw(0x6a, 0x16);
-               smtc_seqw(0x6b, 0x02);
-               smtc_seqw(0x62, 0x3e);
-               /* enable PCI burst */
-               smtc_seqw(0x17, 0x20);
-#ifdef __BIG_ENDIAN
-               if (sfb->fb.var.bits_per_pixel == 32)
-                       smtc_seqw(0x17, 0x30);
-#endif
-               break;
-       case 0x720:
-               smtc_seqw(0x62, 0xff);
-               smtc_seqw(0x6a, 0x0d);
-               smtc_seqw(0x6b, 0x02);
-               break;
-       }
-
-       smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
-       smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
-
-       smtcfb_setmode(sfb);
-
-       console_lock();
-       fb_set_suspend(&sfb->fb, 0);
-       console_unlock();
-
-       return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
-#define SM7XX_PM_OPS (&sm7xx_pm_ops)
-
-#else  /* !CONFIG_PM */
-
-#define SM7XX_PM_OPS NULL
-
-#endif /* !CONFIG_PM */
-
-static struct pci_driver smtcfb_driver = {
-       .name = "smtcfb",
-       .id_table = smtcfb_pci_table,
-       .probe = smtcfb_pci_probe,
-       .remove = smtcfb_pci_remove,
-       .driver.pm  = SM7XX_PM_OPS,
-};
-
-module_pci_driver(smtcfb_driver);
-
-MODULE_AUTHOR("Siliconmotion ");
-MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
-MODULE_LICENSE("GPL");
index e322fb7aebe1da0de4ebf8ec3c51eddde30a6cb8..c2829aa7780fb832fb814776c9bb63fb90af4cf8 100644 (file)
@@ -2127,7 +2127,7 @@ void dump_dl_modules(struct bridge_dev_context *bridge_context)
        u32 module_size;
        u32 module_struct_size = 0;
        u32 sect_ndx;
-       char *sect_str ;
+       char *sect_str;
        int status = 0;
 
        status = dev_get_intf_fxns(dev_object, &intf_fxns);
index 1862afd80dc1b0987b45e5d3ecf43724c3f2e050..657104f37f7de485fbf6909159b452883e5541b4 100644 (file)
@@ -99,7 +99,8 @@ int handle_hibernation_from_dsp(struct bridge_dev_context *dev_context)
                        return -EPERM;
                }
                pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
-                                       OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
+                                                  OMAP2_PM_PWSTST) &
+                                                  OMAP_POWERSTATEST_MASK;
        }
        if (timeout == 0) {
                pr_err("%s: Timed out waiting for DSP off mode\n", __func__);
@@ -209,7 +210,8 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
                        return -EPERM;
                }
                pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
-                                       OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
+                                                  OMAP2_PM_PWSTST) &
+                                                  OMAP_POWERSTATEST_MASK;
        }
 
        if (!timeout) {
@@ -355,7 +357,7 @@ int pre_scale_dsp(struct bridge_dev_context *dev_context, void *pargs)
            (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
                dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
                return 0;
-       } else if ((dev_context->brd_state == BRD_RUNNING)) {
+       } else if (dev_context->brd_state == BRD_RUNNING) {
                /* Send a prenotification to DSP */
                dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
                sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
@@ -396,13 +398,14 @@ int post_scale_dsp(struct bridge_dev_context *dev_context,
                io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
                dev_dbg(bridge, "OPP: %s IVA in sleep. Wrote to shm\n",
                        __func__);
-       } else if ((dev_context->brd_state == BRD_RUNNING)) {
+       } else if (dev_context->brd_state == BRD_RUNNING) {
                /* Update the OPP value in shared memory */
                io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
                /* Send a post notification to DSP */
                sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_POSTNOTIFY);
-               dev_dbg(bridge, "OPP: %s wrote to shm. Sent post notification "
-                       "to DSP\n", __func__);
+               dev_dbg(bridge,
+                       "OPP: %s wrote to shm. Sent post notification to DSP\n",
+                        __func__);
        } else {
                status = -EPERM;
        }
index 404af1895980bdc100d09225583b643a7182cd31..5f0431305fbbbefe7fb95268eb100b4e12b8c34c 100644 (file)
@@ -503,7 +503,7 @@ static int priv_tgt_img_gen(struct dload_state *dlthis, u32 base,
  *       TRAMPOLINES ARE TREATED AS 2ND PASS even though this is really
  *       the first (and only) relocation that will be performed on them.
  */
-static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t * data,
+static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t *data,
                         struct reloc_record_t *rp[], u32 relo_count)
 {
        int ret_val = 1;
index 190ca3fe7327c634cebed7c3c687fcc032a2958f..2ae48c9a936213dc0868d0f2baa682060b12a309 100644 (file)
@@ -101,14 +101,14 @@ static int dcd_uuid_from_string(char *sz_uuid, struct dsp_uuid *uuid_obj)
         * if the converted value doesn't fit in u32. So, convert the
         * last six bytes to u64 and memcpy what is needed
         */
-       if(sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
+       if (sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
               &uuid_tmp.data1, &c, &uuid_tmp.data2, &c,
               &uuid_tmp.data3, &c, &uuid_tmp.data4,
               &uuid_tmp.data5, &c, &t) != 10)
                return -EINVAL;
 
        t = cpu_to_be64(t);
-       memcpy(&uuid_tmp.data6[0], ((char*)&t) + 2, 6);
+       memcpy(&uuid_tmp.data6[0], ((char *)&t) + 2, 6);
        *uuid_obj = uuid_tmp;
 
        return 0;
index be26917a68968897758d0ce70fbd56ebb976f484..757ae20b38ee447efb596f0005bbc0cf8977b1fc 100644 (file)
@@ -738,7 +738,7 @@ void mem_ext_phys_pool_release(void)
  *     Allocate physically contiguous, uncached memory from external memory pool
  */
 
-static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 * phys_addr)
+static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 *phys_addr)
 {
        u32 new_alloc_ptr;
        u32 offset;
index ca3805046a73c8b08a44d76fe0fd89eed07c7fe2..5ac507ccd19d6aac6282d658317ef748e553f056 100644 (file)
@@ -623,7 +623,7 @@ void nldr_delete(struct nldr_object *nldr_obj)
  *  ======== nldr_get_fxn_addr ========
  */
 int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj,
-                            char *str_fxn, u32 * addr)
+                            char *str_fxn, u32 *addr)
 {
        struct dbll_sym_val *dbll_sym;
        struct nldr_object *nldr_obj;
@@ -1751,9 +1751,8 @@ static void unload_ovly(struct nldr_nodeobject *nldr_node_obj,
        }
        if (ref_count && (*ref_count > 0)) {
                *ref_count -= 1;
-               if (other_ref) {
+               if (other_ref)
                        *other_ref -= 1;
-               }
        }
 
        if (ref_count && *ref_count == 0) {
index 87dfa92ab45b91665fdd27c9c9d838e1f48b48da..9d3044a384eeb4b882cc1cd24cb8cf26e86082a8 100644 (file)
@@ -246,7 +246,7 @@ static void fill_stream_def(struct node_object *hnode,
                            struct node_strmdef *pstrm_def,
                            struct dsp_strmattr *pattrs);
 static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream);
-static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
+static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
                                  u32 phase);
 static int get_node_props(struct dcd_manager *hdcd_mgr,
                                 struct node_object *hnode,
@@ -406,7 +406,7 @@ int node_allocate(struct proc_object *hprocessor,
 
        /* check for page aligned Heap size */
        if (((attr_in->heap_size) & (PG_SIZE4K - 1))) {
-               pr_err("%s: node heap size not aligned to 4K, size = 0x%x \n",
+               pr_err("%s: node heap size not aligned to 4K, size = 0x%x\n",
                       __func__, attr_in->heap_size);
                status = -EINVAL;
        } else {
@@ -703,9 +703,9 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
                pattr = &node_dfltbufattrs;     /* set defaults */
 
        status = proc_get_processor_id(pnode->processor, &proc_id);
-       if (proc_id != DSP_UNIT) {
+       if (proc_id != DSP_UNIT)
                goto func_end;
-       }
+
        /*  If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
         *  virt  address, so set this info in this node's translator
         *  object for  future ref. If MEM_GETVIRTUALSEGID then retrieve
@@ -886,11 +886,10 @@ int node_connect(struct node_object *node1, u32 stream1,
        if (pattrs && pattrs->strm_mode != STRMMODE_PROCCOPY)
                return -EPERM;  /* illegal stream mode */
 
-       if (node1_type != NODE_GPP) {
+       if (node1_type != NODE_GPP)
                hnode_mgr = node1->node_mgr;
-       } else {
+       else
                hnode_mgr = node2->node_mgr;
-       }
 
        /* Enter critical section */
        mutex_lock(&hnode_mgr->node_mgr_lock);
@@ -1576,7 +1575,7 @@ func_end:
  *  Purpose:
  *      Frees the message buffer.
  */
-int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer,
+int node_free_msg_buf(struct node_object *hnode, u8 *pbuffer,
                             struct dsp_bufferattr *pattr)
 {
        struct node_object *pnode = (struct node_object *)hnode;
@@ -2322,7 +2321,8 @@ int node_terminate(struct node_object *hnode, int *pstatus)
                        if (!hdeh_mgr)
                                goto func_cont;
 
-                       bridge_deh_notify(hdeh_mgr, DSP_SYSERROR, DSP_EXCEPTIONABORT);
+                       bridge_deh_notify(hdeh_mgr, DSP_SYSERROR,
+                                         DSP_EXCEPTIONABORT);
                }
        }
 func_cont:
@@ -2640,7 +2640,7 @@ static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream)
  *  Purpose:
  *      Retrieves the address for create, execute or delete phase for a node.
  */
-static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
+static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
                                  u32 phase)
 {
        char *pstr_fxn_name = NULL;
diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt
new file mode 100644 (file)
index 0000000..8d078e4
--- /dev/null
@@ -0,0 +1,174 @@
+
+Overview
+
+This document describes the driver set for Unisys Secure Partitioning (s-Par®).
+
+s-Par is firmware that provides hardware partitioning capabilities for
+splitting large-scale Intel x86 servers into multiple isolated
+partitions. s-Par provides a set of para-virtualized device drivers to
+allow guest partitions on the same server to share devices that would
+normally be unsharable; specifically, PCI network interfaces and host
+bus adapters that do not support shared access via SR-IOV. The shared
+device is owned and managed by a small, single-purpose service
+partition, which communicates with each guest partition sharing that
+device through an area of shared memory called a channel. Additional
+drivers provide support interfaces for communicating with s-Par
+services, logging and diagnostics, and accessing the Linux console
+from the s-Par user interface.
+
+The driver stack consists of a set of support modules, a set of bus
+modules, and a set of device driver modules. The support modules
+handle a number of common functions across each of the other
+drivers. The bus modules provide organization for the device driver
+modules, which provide the shared device functionality.
+
+These drivers are for the Unisys virtual PCI hardware model where the
+hypervisor need not intervene (other than normal interrupt handling)
+in the interactions between the client drivers and the virtual adapter
+firmware in the adapter service partition.
+
+Driver Descriptions
+
+Device Modules
+
+The modules in this section handle shared devices and the virtual
+buses required to support them. These modules use functions in and
+depend on the modules described in the support modules section.
+
+visorchipset
+
+The visorchipset module receives device creation and destruction
+events from the Command service partition of s-Par, as well as
+controlling registration of shared device drivers with the s-Par
+driver core. The events received are used to populate other s-Par
+modules with their assigned shared devices. Visorchipset is required
+for shared device drivers to function properly. Visorchipset also
+stores information for handling dump disk device creation during
+kdump.
+
+In operation, the visorchipset module processes device creation and
+destruction messages sent by s-Par's Command service partition through
+a channel. These messages result in creation (or destruction) of each
+virtual bus and virtual device. Each bus and device is also associated
+with a communication channel, which is used to communicate with one or
+more IO service partitions to perform device IO on behalf of the
+guest.
+
+virthba
+
+The virthba module provides access to a shared SCSI host bus adapter
+and one or more disk devices, by proxying SCSI commands between the
+guest and the service partition that owns the shared SCSI adapter,
+using a channel between the guest and the service partition. The disks
+that appear on the shared bus are defined by the s-Par configuration
+and enforced by the service partition, while the guest driver handles
+sending commands and handling responses. Each disk is shared as a
+whole to a guest. Sharing the bus adapter in this way provides
+resiliency; should the device encounter an error, only the service
+partition is rebooted, and the device is reinitialized. This allows
+guests to continue running and to recover from the error.
+
+virtnic
+
+The virtnic module provides a paravirtualized network interface to a
+guest by proxying buffer information between the guest and the service
+partition that owns the shared network interface, using a channel
+between the guest and the service partition. The connectivity of this
+interface with the shared interface and possibly other guest
+partitions is defined by the s-Par configuration and enforced by the
+service partition; the guest driver handles communication and link
+status.
+
+visorserial
+
+The visorserial module allows the console of the linux guest to be
+accessed via the s-Par console serial channel. It creates devices in
+/dev/visorserialclientX which behave like a serial terminal and are
+connected to the diagnostics system in s-Par. By assigning a getty to
+the terminal in the guest, a user could log into and access the guest
+from the s-Par diagnostics SWITCH RUN terminal.
+
+visorbus
+
+The visorbus module handles the bus functions for most functional
+drivers except visorserial, visordiag, virthba, and virtnic. It
+maintains the sysfs subtree /sys/devices/visorbus*/. It is responsible
+for device creation and destruction of the devices on its bus.
+
+visorclientbus
+
+The visorclientbus module forwards the bus functions for virthba, and
+virtnic to the virtpci driver.
+
+virtpci
+
+The virtpci module handles the bus functions for virthba, and virtnic.
+
+s-Par Integration Modules
+
+The modules in this section provide integration with s-Par guest
+partition services like diagnostics and remote desktop. These modules
+depend on functions in the modules described in the support modules
+section.
+
+visorvideoclient
+
+The visorvideoclient module provides functionality for video support
+for the Unisys s-Par Partition Desktop application. The guest OS must
+also have the UEFI GOP protocol enabled for the partition desktop to
+function.  visorconinclient The visorconinclient module provides
+keyboard and mouse support for the Unisys s-Par Partition Desktop
+application.
+
+sparstop
+
+The sparstop module handles requests from the Unisys s-Par platform to
+shutdown the linux guest. It allows a program on the guest to perform
+clean-up functions on the guest before the guest is shut down or
+rebooted using ACPI.
+
+visordiag
+
+This driver provides the ability for the guest to write information
+into the s-Par diagnostics subsystem. It creates a set of devices
+named /dev/visordiag.X which can be written to by the guest to add
+text to the s-Par system log.
+
+Support Modules
+
+The modules described in this section provide functions and
+abstractions to support the modules described in the previous
+sections, to avoid having duplicated functionality.
+
+visornoop
+
+The visornoop module is a placeholder that responds to device
+create/destroy messages that are currently not in use by linux guests.
+
+visoruislib
+
+The visoruislib module is a support library, used to handle requests
+from virtpci.
+
+visorchannelstub
+
+The visorchannelstub module provides support routines for storing and
+retrieving data from a channel.
+
+visorchannel
+
+The visorchannel module is a support library that abstracts reading
+and writing a channel in memory.
+
+visorutil
+
+The visorutil module is a support library required by all other s-Par
+driver modules. Among its features it abstracts reading, writing, and
+manipulating a block of memory.
+
+Minimum Required Driver Set
+
+The drivers required to boot a Linux guest are visorchipset, visorbus,
+visorvideoclient, visorconinclient, visoruislib, visorchannelstub,
+visorchannel, and visorutil. The other drivers are required by the
+product configurations that are currently being marketed.
diff --git a/drivers/staging/unisys/Documentation/proc-entries.txt b/drivers/staging/unisys/Documentation/proc-entries.txt
new file mode 100644 (file)
index 0000000..426f92b
--- /dev/null
@@ -0,0 +1,93 @@
+ s-Par Proc Entries
+This document describes the proc entries created by the Unisys s-Par modules.
+
+Support Module Entries
+These entries are provided primarily for debugging.
+
+/proc/uislib/info: This entry contains debugging information for the
+uislib module, including bus information and memory usage.
+
+/proc/visorchipset/controlvm: This directory contains debugging
+entries for the controlvm channel used by visorchipset.
+
+/proc/uislib/platform: This entry is used to display the platform
+number this node is in the system. For some guests, this may be
+invalid.
+
+/proc/visorchipset/chipsetready: This entry is written to by scripts
+to signify that any user level activity has been completed before the
+guest can be considered running and is shown as running in the s-Par
+UI.
+
+Device Entries
+These entries provide status of the devices shared by a service partition.
+
+/proc/uislib/vbus: this is a directory containing entries for each
+virtual bus. Each numbered sub-directory contains an info entry, which
+describes the devices that appear on that bus.
+
+/proc/uislib/cycles_before_wait: This entry is used to tune
+performance, by setting the number of cycles we wait before going idle
+when in polling mode. A longer time will reduce message latency but
+spend more processing time polling.
+
+/proc/uislib/smart_wakeup: This entry is used to tune performance, by
+enabling or disabling smart wakeup.
+
+/proc/virthba/info: This entry contains debugging information for the
+virthba module, including interrupt information and memory usage.
+
+/proc/virthba/enable_ints: This entry controls interrupt use by the
+virthba module. Writing a 0 to this entry will disable interrupts.
+
+/proc/virtnic/info: This entry contains debugging information for the
+virtnic module, including interrupt information, send and receive
+counts, and other device information.
+
+/proc/virtnic/ethX: This is a directory containing entries for each
+virtual NIC. Each named subdirectory contains two entries,
+clientstring and zone.
+
+/proc/virtpci/info: This entry contains debugging information for the
+virtpci module, including virtual PCI bus information and device
+locations.
+
+/proc/virtnic/enable_ints: This entry controls interrupt use by the
+virtnic module. Writing a 0 to this entry will disable interrupts.
+
+Visorconinclient, visordiag, visornoop, visorserialclient, and
+visorvideoclient Entries
+
+The entries in proc for these modules all follow the same
+pattern. Each module has its own proc directory with the same name,
+e.g. visordiag presents a /proc/visordiag directory. Inside of the
+module's directory are a device directory, which contains one numbered
+directory for each device provided by that module. Each device has a
+diag entry that presents the device number and visorbus name for that
+device. The module directory also has a driver/diag entry, which
+reports the corresponding s-Par version number of the driver.
+
+Automated Installation Entries
+
+These entries are used to pass information between the s-Par platform
+and the Linux-based installation and recovery tool. These values are
+read/write, however, the guest can only reset them to 0, or report an
+error status through the installer entry. The values are only set via
+s-Par's firmware interface, to help prevent accidentally booting into
+the tool.
+
+/proc/visorchipset/boottotool: This entry instructs s-Par that the
+next reboot will launch the installation and recovery tool. If set to
+0, the next boot will happen according to the UEFI boot manager
+settings.
+
+/proc/visorchipset/toolaction: This entry indicates the installation
+and recovery tool mode requested for the next boot.
+
+/proc/visorchipset/installer: this entry is used by the installation
+and recovery tool to pass status and result information back to the
+s-Par firmware.
+
+/proc/visorchipset/partition: This directory contains the guest
+partition configuration data for each virtual bus, for use during
+installation and at runtime for s-Par service partitions.
diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
new file mode 100644 (file)
index 0000000..ac080c9
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Unisys SPAR driver configuration
+#
+menuconfig UNISYSSPAR
+       bool "Unisys SPAR driver support"
+       depends on X86_64
+       ---help---
+       Support for the Unisys SPAR drivers
+
+if UNISYSSPAR
+
+source "drivers/staging/unisys/visorutil/Kconfig"
+source "drivers/staging/unisys/visorchannel/Kconfig"
+source "drivers/staging/unisys/visorchipset/Kconfig"
+source "drivers/staging/unisys/channels/Kconfig"
+source "drivers/staging/unisys/uislib/Kconfig"
+source "drivers/staging/unisys/virtpci/Kconfig"
+source "drivers/staging/unisys/virthba/Kconfig"
+
+endif # UNISYSSPAR
diff --git a/drivers/staging/unisys/MAINTAINERS b/drivers/staging/unisys/MAINTAINERS
new file mode 100644 (file)
index 0000000..c9cef0b
--- /dev/null
@@ -0,0 +1,6 @@
+Unisys s-Par drivers
+M:     Ben Romer <sparmaintainer@unisys.com>
+S:     Maintained
+F:     Documentation/s-Par/overview.txt
+F:     Documentation/s-Par/proc-entries.txt
+F:     drivers/staging/unisys/
diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile
new file mode 100644 (file)
index 0000000..b988d69
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for Unisys SPAR drivers
+#
+obj-$(CONFIG_UNISYS_VISORUTIL)         += visorutil/
+obj-$(CONFIG_UNISYS_VISORCHANNEL)      += visorchannel/
+obj-$(CONFIG_UNISYS_VISORCHIPSET)      += visorchipset/
+obj-$(CONFIG_UNISYS_CHANNELSTUB)       += channels/
+obj-$(CONFIG_UNISYS_UISLIB)            += uislib/
+obj-$(CONFIG_UNISYS_VIRTPCI)           += virtpci/
+obj-$(CONFIG_UNISYS_VIRTHBA)           += virthba/
diff --git a/drivers/staging/unisys/TODO b/drivers/staging/unisys/TODO
new file mode 100644 (file)
index 0000000..c4265a2
--- /dev/null
@@ -0,0 +1,20 @@
+TODO:
+       -checkpatch warnings
+       -move /proc entries to /sys
+       -proper major number(s)
+       -add other drivers needed for full functionality:
+               -visorclientbus
+               -visorbus
+               -visordiag
+               -virtnic
+               -visornoop
+               -visorserial
+               -visorvideoclient
+               -visorconinclient
+               -sparstop
+       -move individual drivers into proper driver subsystems
+               
+
+Patches to:
+       Ken Cox <jkc@redhat.com>
+       Ben Romer <sparmaintainer@unisys.com>
diff --git a/drivers/staging/unisys/channels/Kconfig b/drivers/staging/unisys/channels/Kconfig
new file mode 100644 (file)
index 0000000..47a2353
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys channels configuration
+#
+
+config UNISYS_CHANNELSTUB
+       tristate "Unisys channelstub driver"
+       depends on UNISYSSPAR
+       ---help---
+       If you say Y here, you will enable the Unisys channels driver.
+
diff --git a/drivers/staging/unisys/channels/Makefile b/drivers/staging/unisys/channels/Makefile
new file mode 100644 (file)
index 0000000..e60b0ae
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for Unisys channelstub
+#
+
+obj-$(CONFIG_UNISYS_CHANNELSTUB)       += visorchannelstub.o
+
+visorchannelstub-y := channel.o chanstub.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/channels/channel.c b/drivers/staging/unisys/channels/channel.c
new file mode 100644 (file)
index 0000000..afe8cea
--- /dev/null
@@ -0,0 +1,307 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>                /* for module_init and module_exit */
+#include <linux/slab.h>                /* for memcpy */
+#include <linux/types.h>
+
+/* Implementation of exported functions for Supervisor channels */
+#include "channel.h"
+
+/*
+ * Routine Description:
+ * Tries to insert the prebuilt signal pointed to by pSignal into the nth
+ * Queue of the Channel pointed to by pChannel
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to the signal
+ *
+ * Assumptions:
+ * - pChannel, Queue and pSignal are valid.
+ * - If insertion fails due to a full queue, the caller will determine the
+ * retry policy (e.g. wait & try again, report an error, etc.).
+ *
+ * Return value:
+ * 1 if the insertion succeeds, 0 if the queue was full.
+ */
+unsigned char
+SignalInsert(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+       void *psignal;
+       unsigned int head, tail;
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+
+       /* capture current head and tail */
+       head = pqhdr->Head;
+       tail = pqhdr->Tail;
+
+       /* queue is full if (head + 1) % n equals tail */
+       if (((head + 1) % pqhdr->MaxSignalSlots) == tail) {
+               pqhdr->NumOverflows++;
+               return 0;
+       }
+
+       /* increment the head index */
+       head = (head + 1) % pqhdr->MaxSignalSlots;
+
+       /* copy signal to the head location from the area pointed to
+        * by pSignal
+        */
+       psignal =
+           (char *) pqhdr + pqhdr->oSignalBase + (head * pqhdr->SignalSize);
+       MEMCPY(psignal, pSignal, pqhdr->SignalSize);
+
+       VolatileBarrier();
+       pqhdr->Head = head;
+
+       pqhdr->NumSignalsSent++;
+       return 1;
+}
+EXPORT_SYMBOL_GPL(SignalInsert);
+
+/*
+ * Routine Description:
+ * Removes one signal from Channel pChannel's nth Queue at the
+ * time of the call and copies it into the memory pointed to by
+ * pSignal.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold queue's SignalSize
+ *
+ * Return value:
+ * 1 if the removal succeeds, 0 if the queue was empty.
+ */
+unsigned char
+SignalRemove(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+       void *psource;
+       unsigned int head, tail;
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+
+       /* capture current head and tail */
+       head = pqhdr->Head;
+       tail = pqhdr->Tail;
+
+       /* queue is empty if the head index equals the tail index */
+       if (head == tail) {
+               pqhdr->NumEmptyCnt++;
+               return 0;
+       }
+
+       /* advance past the 'empty' front slot */
+       tail = (tail + 1) % pqhdr->MaxSignalSlots;
+
+       /* copy signal from tail location to the area pointed to by pSignal */
+       psource =
+           (char *) pqhdr + pqhdr->oSignalBase + (tail * pqhdr->SignalSize);
+       MEMCPY(pSignal, psource, pqhdr->SignalSize);
+
+       VolatileBarrier();
+       pqhdr->Tail = tail;
+
+       pqhdr->NumSignalsReceived++;
+       return 1;
+}
+EXPORT_SYMBOL_GPL(SignalRemove);
+
+/*
+ * Routine Description:
+ * Removes all signals present in Channel pChannel's nth Queue at the
+ * time of the call and copies them into the memory pointed to by
+ * pSignal.  Returns the # of signals copied as the value of the routine.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold Queue's MaxSignals
+ * # of signals, each of which is Queue's SignalSize.
+ *
+ * Return value:
+ * # of signals copied.
+ */
+unsigned int
+SignalRemoveAll(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+       void *psource;
+       unsigned int head, tail, signalCount = 0;
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+
+       /* capture current head and tail */
+       head = pqhdr->Head;
+       tail = pqhdr->Tail;
+
+       /* queue is empty if the head index equals the tail index */
+       if (head == tail)
+               return 0;
+
+       while (head != tail) {
+               /* advance past the 'empty' front slot */
+               tail = (tail + 1) % pqhdr->MaxSignalSlots;
+
+               /* copy signal from tail location to the area pointed
+                * to by pSignal
+                */
+               psource =
+                   (char *) pqhdr + pqhdr->oSignalBase +
+                   (tail * pqhdr->SignalSize);
+               MEMCPY((char *) pSignal + (pqhdr->SignalSize * signalCount),
+                      psource, pqhdr->SignalSize);
+
+               VolatileBarrier();
+               pqhdr->Tail = tail;
+
+               signalCount++;
+               pqhdr->NumSignalsReceived++;
+       }
+
+       return signalCount;
+}
+
+/*
+ * Routine Description:
+ * Copies one signal from channel pChannel's nth Queue at the given position
+ * at the time of the call into the memory pointed to by pSignal.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * Position: (IN) nth entry in Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold queue's SignalSize
+ *
+ * Return value:
+ * 1 if the copy succeeds, 0 if the queue was empty or Position was invalid.
+ */
+unsigned char
+SignalPeek(pCHANNEL_HEADER pChannel, U32 Queue, U32 Position, void *pSignal)
+{
+       void *psignal;
+       unsigned int head, tail;
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+
+       head = pqhdr->Head;
+       tail = pqhdr->Tail;
+
+       /* check if Position is out of range or queue is empty */
+       if (Position >= pqhdr->MaxSignalSlots || Position == tail
+           || head == tail)
+               return 0;
+
+       /* check if Position is between tail and head */
+       if (head > tail) {
+               if (Position > head || Position < tail)
+                       return 0;
+       } else if ((Position > head) && (Position < tail))
+               return 0;
+
+       /* copy signal from Position location to the area pointed to
+        * by pSignal
+        */
+       psignal =
+           (char *) pqhdr + pqhdr->oSignalBase +
+           (Position * pqhdr->SignalSize);
+       MEMCPY(pSignal, psignal, pqhdr->SignalSize);
+
+       return 1;
+}
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is empty.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue is empty, 0 otherwise.
+ */
+unsigned char
+SignalQueueIsEmpty(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+       return pqhdr->Head == pqhdr->Tail;
+}
+EXPORT_SYMBOL_GPL(SignalQueueIsEmpty);
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is empty.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue has 1 element, 0 otherwise.
+ */
+unsigned char
+SignalQueueHasOneElement(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+       return ((pqhdr->Tail + 1) % pqhdr->MaxSignalSlots) == pqhdr->Head;
+}
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is full.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue is full, 0 otherwise.
+ */
+unsigned char
+SignalQueueIsFull(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+       pSIGNAL_QUEUE_HEADER pqhdr =
+           (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+                                   pChannel->oChannelSpace) + Queue;
+       return ((pqhdr->Head + 1) % pqhdr->MaxSignalSlots) == pqhdr->Tail;
+}
diff --git a/drivers/staging/unisys/channels/chanstub.c b/drivers/staging/unisys/channels/chanstub.c
new file mode 100644 (file)
index 0000000..37e207d
--- /dev/null
@@ -0,0 +1,70 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>                /* for module_init and module_exit */
+#include <linux/slab.h>                /* for memcpy */
+#include <linux/types.h>
+
+#include "channel.h"
+#include "chanstub.h"
+#include "version.h"
+
+__init int
+channel_mod_init(void)
+{
+       return 0;
+}
+
+__exit void
+channel_mod_exit(void)
+{
+}
+
+unsigned char
+SignalInsert_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+                     void *pSignal, spinlock_t *lock)
+{
+       unsigned char result;
+       unsigned long flags;
+       spin_lock_irqsave(lock, flags);
+       result = SignalInsert(pChannel, Queue, pSignal);
+       spin_unlock_irqrestore(lock, flags);
+       return result;
+}
+
+unsigned char
+SignalRemove_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+                     void *pSignal, spinlock_t *lock)
+{
+       unsigned char result;
+       spin_lock(lock);
+       result = SignalRemove(pChannel, Queue, pSignal);
+       spin_unlock(lock);
+       return result;
+}
+
+module_init(channel_mod_init);
+module_exit(channel_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bryan Glaudel");
+MODULE_ALIAS("uischan");
+       /* this is extracted during depmod and kept in modules.dep */
diff --git a/drivers/staging/unisys/channels/chanstub.h b/drivers/staging/unisys/channels/chanstub.h
new file mode 100644 (file)
index 0000000..dadd7cd
--- /dev/null
@@ -0,0 +1,23 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHANSTUB_H__
+#define __CHANSTUB_H__
+unsigned char SignalInsert_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+                                    void *pSignal, spinlock_t *lock);
+unsigned char SignalRemove_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+                                    void *pSignal, spinlock_t *lock);
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/channels/channel.h b/drivers/staging/unisys/common-spar/include/channels/channel.h
new file mode 100644 (file)
index 0000000..83906b4
--- /dev/null
@@ -0,0 +1,645 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHANNEL_H__
+#define __CHANNEL_H__
+
+/*
+* Whenever this file is changed a corresponding change must be made in
+* the Console/ServicePart/visordiag_early/supervisor_channel.h file
+* which is needed for Linux kernel compiles. These two files must be
+* in sync.
+*/
+
+/* define the following to prevent include nesting in kernel header
+ * files of similar abreviated content
+ */
+#define __SUPERVISOR_CHANNEL_H__
+
+#include "commontypes.h"
+
+#define SIGNATURE_16(A, B) ((A) | (B<<8))
+#define SIGNATURE_32(A, B, C, D) \
+       (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16))
+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
+       (SIGNATURE_32(A, B, C, D) | ((U64)(SIGNATURE_32(E, F, G, H)) << 32))
+
+#ifndef lengthof
+#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
+#endif
+#ifndef COVERQ
+#define COVERQ(v, d)  (((v)+(d)-1) / (d))
+#endif
+#ifndef COVER
+#define COVER(v, d)   ((d)*COVERQ(v, d))
+#endif
+
+#ifndef GUID0
+#define GUID0 {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }
+#endif
+
+/*  The C language is inconsistent with respect to where it allows literal
+ *  constants, especially literal constant structs.  Literal constant structs
+ *  are allowed for initialization only, whereas other types of literal
+ *  constants are allowed anywhere.  We get around this inconsistency by
+ *  declaring a "static const" variable for each GUID.  This variable can be
+ *  used in expressions where the literal constant would not be allowed.
+ */
+static const GUID Guid0 = GUID0;
+
+#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE  SIGNATURE_32('E', 'C', 'N', 'L')
+
+typedef enum {
+       CHANNELSRV_UNINITIALIZED = 0,   /* channel is in an undefined state */
+       CHANNELSRV_READY = 1    /* channel has been initialized by server */
+} CHANNEL_SERVERSTATE;
+
+typedef enum {
+       CHANNELCLI_DETACHED = 0,
+       CHANNELCLI_DISABLED = 1,        /* client can see channel but is NOT
+                                        * allowed to use it unless given TBD
+                                        * explicit request (should actually be
+                                        * < DETACHED) */
+       CHANNELCLI_ATTACHING = 2,       /* legacy EFI client request
+                                        * for EFI server to attach */
+       CHANNELCLI_ATTACHED = 3,        /* idle, but client may want
+                                        * to use channel any time */
+       CHANNELCLI_BUSY = 4,    /* client either wants to use or is
+                                * using channel */
+       CHANNELCLI_OWNED = 5    /* "no worries" state - client can
+                                * access channel anytime */
+} CHANNEL_CLIENTSTATE;
+static inline const U8 *
+ULTRA_CHANNELCLI_STRING(U32 v)
+{
+       switch (v) {
+       case CHANNELCLI_DETACHED:
+               return (const U8 *) ("DETACHED");
+       case CHANNELCLI_DISABLED:
+               return (const U8 *) ("DISABLED");
+       case CHANNELCLI_ATTACHING:
+               return (const U8 *) ("ATTACHING");
+       case CHANNELCLI_ATTACHED:
+               return (const U8 *) ("ATTACHED");
+       case CHANNELCLI_BUSY:
+               return (const U8 *) ("BUSY");
+       case CHANNELCLI_OWNED:
+               return (const U8 *) ("OWNED");
+       default:
+               break;
+       }
+       return (const U8 *) ("?");
+}
+
+#define ULTRA_CHANNELSRV_IS_READY(x)     ((x) == CHANNELSRV_READY)
+#define ULTRA_CHANNEL_SERVER_READY(pChannel) \
+       (ULTRA_CHANNELSRV_IS_READY((pChannel)->SrvState))
+
+#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n)                                \
+       (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \
+         (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \
+         (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \
+         (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \
+         (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \
+         (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \
+         (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \
+         (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \
+         (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \
+         (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \
+         (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \
+         (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \
+         (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \
+         (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \
+         (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \
+        ? (1) : (0))
+
+#define ULTRA_CHANNEL_CLIENT_CHK_TRANSITION(old, new, chanId, logCtx,  \
+                                           file, line)                 \
+       do {                                                            \
+               if (!ULTRA_VALID_CHANNELCLI_TRANSITION(old, new))       \
+                       UltraLogEvent(logCtx,                           \
+                                     CHANNELSTATE_DIAG_EVENTID_TRANSITERR, \
+                                     CHANNELSTATE_DIAG_SEVERITY, \
+                                     CHANNELSTATE_DIAG_SUBSYS,         \
+                                     __func__, __LINE__,               \
+                                     "%s Channel StateTransition INVALID! (%s) %s(%d)-->%s(%d) @%s:%d\n", \
+                                     chanId, "CliState<x>",            \
+                                     ULTRA_CHANNELCLI_STRING(old),     \
+                                     old,                              \
+                                     ULTRA_CHANNELCLI_STRING(new),     \
+                                     new,                              \
+                                     PathName_Last_N_Nodes((U8 *)file, 4), \
+                                     line);                            \
+       } while (0)
+
+#define ULTRA_CHANNEL_CLIENT_TRANSITION(pChan, chanId, field, \
+                                       newstate, logCtx)               \
+       do {                                                            \
+               ULTRA_CHANNEL_CLIENT_CHK_TRANSITION(                    \
+                       (((CHANNEL_HEADER *)(pChan))->field), newstate, \
+                       chanId, logCtx, __FILE__, __LINE__);            \
+               UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK, \
+                       CHANNELSTATE_DIAG_SEVERITY, \
+                             CHANNELSTATE_DIAG_SUBSYS,                 \
+                             __func__, __LINE__,                       \
+                             "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n", \
+                             chanId, #field,                           \
+                             ULTRA_CHANNELCLI_STRING(((CHANNEL_HEADER *) \
+                                                      (pChan))->field), \
+                             ((CHANNEL_HEADER *)(pChan))->field,       \
+                             ULTRA_CHANNELCLI_STRING(newstate),        \
+                             newstate,                                 \
+                             PathName_Last_N_Nodes(__FILE__, 4), __LINE__); \
+               ((CHANNEL_HEADER *)(pChan))->field = newstate;          \
+               MEMORYBARRIER;                                          \
+       } while (0)
+
+#define ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(pChan, chanId, logCtx) \
+       ULTRA_channel_client_acquire_os(pChan, chanId, logCtx,          \
+                                       (char *)__FILE__, __LINE__,     \
+                                       (char *)__func__)
+#define ULTRA_CHANNEL_CLIENT_RELEASE_OS(pChan, chanId, logCtx) \
+       ULTRA_channel_client_release_os(pChan, chanId, logCtx,  \
+               (char *)__FILE__, __LINE__, (char *)__func__)
+
+/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
+/* throttling invalid boot channel statetransition error due to client
+ * disabled */
+#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED    0x01
+
+/* throttling invalid boot channel statetransition error due to client
+ * not attached */
+#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
+
+/* throttling invalid boot channel statetransition error due to busy channel */
+#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY        0x04
+
+/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */
+/* throttling invalid guest OS channel statetransition error due to
+ * client disabled */
+#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED      0x01
+
+/* throttling invalid guest OS channel statetransition error due to
+ * client not attached */
+#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED   0x02
+
+/* throttling invalid guest OS channel statetransition error due to
+ * busy channel */
+#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY          0x04
+
+/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
+* that windows guest can look at the FeatureFlags in the io channel,
+* and configure the windows driver to use interrupts or not based on
+* this setting.  This flag is set in uislib after the
+* ULTRA_VHBA_init_channel is called.  All feature bits for all
+* channels should be defined here.  The io channel feature bits are
+* defined right here */
+#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
+#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
+#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
+#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5)
+#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
+
+#pragma pack(push, 1)          /* both GCC and VC now allow this pragma */
+/* Common Channel Header */
+typedef struct _CHANNEL_HEADER {
+       U64 Signature;          /* Signature */
+       U32 LegacyState;        /* DEPRECATED - being replaced by */
+       /* /              SrvState, CliStateBoot, and CliStateOS below */
+       U32 HeaderSize;         /* sizeof(CHANNEL_HEADER) */
+       U64 Size;               /* Total size of this channel in bytes */
+       U64 Features;           /* Flags to modify behavior */
+       GUID Type;              /* Channel type: data, bus, control, etc. */
+       U64 PartitionHandle;    /* ID of guest partition */
+       U64 Handle;             /* Device number of this channel in client */
+       U64 oChannelSpace;      /* Offset in bytes to channel specific area */
+       U32 VersionId;          /* CHANNEL_HEADER Version ID */
+       U32 PartitionIndex;     /* Index of guest partition */
+       GUID ZoneGuid;          /* Guid of Channel's zone */
+       U32 oClientString;      /* offset from channel header to
+                                * nul-terminated ClientString (0 if
+                                * ClientString not present) */
+       U32 CliStateBoot;       /* CHANNEL_CLIENTSTATE of pre-boot
+                                * EFI client of this channel */
+       U32 CmdStateCli;        /* CHANNEL_COMMANDSTATE (overloaded in
+                                * Windows drivers, see ServerStateUp,
+                                * ServerStateDown, etc) */
+       U32 CliStateOS;         /* CHANNEL_CLIENTSTATE of Guest OS
+                                * client of this channel */
+       U32 ChannelCharacteristics;     /* CHANNEL_CHARACTERISTIC_<xxx> */
+       U32 CmdStateSrv;        /* CHANNEL_COMMANDSTATE (overloaded in
+                                * Windows drivers, see ServerStateUp,
+                                * ServerStateDown, etc) */
+       U32 SrvState;           /* CHANNEL_SERVERSTATE */
+       U8 CliErrorBoot;        /* bits to indicate err states for
+                                * boot clients, so err messages can
+                                * be throttled */
+       U8 CliErrorOS;          /* bits to indicate err states for OS
+                                * clients, so err messages can be
+                                * throttled */
+       U8 Filler[1];           /* Pad out to 128 byte cacheline */
+       /* Please add all new single-byte values below here */
+       U8 RecoverChannel;
+} CHANNEL_HEADER, *pCHANNEL_HEADER, ULTRA_CHANNEL_PROTOCOL;
+
+#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
+
+/* Subheader for the Signal Type variation of the Common Channel */
+typedef struct _SIGNAL_QUEUE_HEADER {
+       /* 1st cache line */
+       U32 VersionId;          /* SIGNAL_QUEUE_HEADER Version ID */
+       U32 Type;               /* Queue type: storage, network */
+       U64 Size;               /* Total size of this queue in bytes */
+       U64 oSignalBase;        /* Offset to signal queue area */
+       U64 FeatureFlags;       /* Flags to modify behavior */
+       U64 NumSignalsSent;     /* Total # of signals placed in this queue */
+       U64 NumOverflows;       /* Total # of inserts failed due to
+                                * full queue */
+       U32 SignalSize;         /* Total size of a signal for this queue */
+       U32 MaxSignalSlots;     /* Max # of slots in queue, 1 slot is
+                                * always empty */
+       U32 MaxSignals;         /* Max # of signals in queue
+                                * (MaxSignalSlots-1) */
+       U32 Head;               /* Queue head signal # */
+       /* 2nd cache line */
+       U64 NumSignalsReceived; /* Total # of signals removed from this queue */
+       U32 Tail;               /* Queue tail signal # (on separate
+                                * cache line) */
+       U32 Reserved1;          /* Reserved field */
+       U64 Reserved2;          /* Resrved field */
+       U64 ClientQueue;
+       U64 NumInterruptsReceived;      /* Total # of Interrupts received.  This
+                                        * is incremented by the ISR in the
+                                        * guest windows driver */
+       U64 NumEmptyCnt;        /* Number of times that SignalRemove
+                                * is called and returned Empty
+                                * Status. */
+       U32 ErrorFlags;         /* Error bits set during SignalReinit
+                                * to denote trouble with client's
+                                * fields */
+       U8 Filler[12];          /* Pad out to 64 byte cacheline */
+} SIGNAL_QUEUE_HEADER, *pSIGNAL_QUEUE_HEADER;
+
+#pragma pack(pop)
+
+#define SignalInit(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ)       \
+       do {                                                            \
+               MEMSET(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD));       \
+               chan->QHDRFLD.VersionId = ver;                          \
+               chan->QHDRFLD.Type = typ;                               \
+               chan->QHDRFLD.Size = sizeof(chan->QDATAFLD);            \
+               chan->QHDRFLD.SignalSize = sizeof(QDATATYPE);           \
+               chan->QHDRFLD.oSignalBase = (UINTN)(chan->QDATAFLD)-    \
+                       (UINTN)(&chan->QHDRFLD);                        \
+               chan->QHDRFLD.MaxSignalSlots =                          \
+                       sizeof(chan->QDATAFLD)/sizeof(QDATATYPE);       \
+               chan->QHDRFLD.MaxSignals = chan->QHDRFLD.MaxSignalSlots-1; \
+       } while (0)
+
+/* Generic function useful for validating any type of channel when it is
+ * received by the client that will be accessing the channel.
+ * Note that <logCtx> is only needed for callers in the EFI environment, and
+ * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
+ */
+static inline int
+ULTRA_check_channel_client(void *pChannel,
+                          GUID expectedTypeGuid,
+                          char *channelName,
+                          U64 expectedMinBytes,
+                          U32 expectedVersionId,
+                          U64 expectedSignature,
+                          char *fileName, int lineNumber, void *logCtx)
+{
+       if (MEMCMP(&expectedTypeGuid, &Guid0, sizeof(GUID)) != 0)
+               /* caller wants us to verify type GUID */
+               if (MEMCMP(&(((CHANNEL_HEADER *) (pChannel))->Type),
+                          &expectedTypeGuid, sizeof(GUID)) != 0) {
+                       CHANNEL_GUID_MISMATCH(expectedTypeGuid, channelName,
+                                             "type", expectedTypeGuid,
+                                             ((CHANNEL_HEADER *)
+                                              (pChannel))->Type, fileName,
+                                             lineNumber, logCtx);
+                       return 0;
+               }
+       if (expectedMinBytes > 0)       /* caller wants us to verify
+                                        * channel size */
+               if (((CHANNEL_HEADER *) (pChannel))->Size < expectedMinBytes) {
+                       CHANNEL_U64_MISMATCH(expectedTypeGuid, channelName,
+                                            "size", expectedMinBytes,
+                                            ((CHANNEL_HEADER *)
+                                             (pChannel))->Size, fileName,
+                                            lineNumber, logCtx);
+                       return 0;
+               }
+       if (expectedVersionId > 0)      /* caller wants us to verify
+                                        * channel version */
+               if (((CHANNEL_HEADER *) (pChannel))->VersionId !=
+                   expectedVersionId) {
+                       CHANNEL_U32_MISMATCH(expectedTypeGuid, channelName,
+                                            "version", expectedVersionId,
+                                            ((CHANNEL_HEADER *)
+                                             (pChannel))->VersionId, fileName,
+                                            lineNumber, logCtx);
+                       return 0;
+               }
+       if (expectedSignature > 0)      /* caller wants us to verify
+                                        * channel signature */
+               if (((CHANNEL_HEADER *) (pChannel))->Signature !=
+                   expectedSignature) {
+                       CHANNEL_U64_MISMATCH(expectedTypeGuid, channelName,
+                                            "signature", expectedSignature,
+                                            ((CHANNEL_HEADER *)
+                                             (pChannel))->Signature, fileName,
+                                            lineNumber, logCtx);
+                       return 0;
+               }
+       return 1;
+}
+
+/* Generic function useful for validating any type of channel when it is about
+ * to be initialized by the server of the channel.
+ * Note that <logCtx> is only needed for callers in the EFI environment, and
+ * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
+ */
+static inline int
+ULTRA_check_channel_server(GUID typeGuid,
+                          char *channelName,
+                          U64 expectedMinBytes,
+                          U64 actualBytes,
+                          char *fileName, int lineNumber, void *logCtx)
+{
+       if (expectedMinBytes > 0)       /* caller wants us to verify
+                                        * channel size */
+               if (actualBytes < expectedMinBytes) {
+                       CHANNEL_U64_MISMATCH(typeGuid, channelName, "size",
+                                            expectedMinBytes, actualBytes,
+                                            fileName, lineNumber, logCtx);
+                       return 0;
+               }
+       return 1;
+}
+
+/* Given a file pathname <s> (with '/' or '\' separating directory nodes),
+ * returns a pointer to the beginning of a node within that pathname such
+ * that the number of nodes from that pointer to the end of the string is
+ * NOT more than <n>.  Note that if the pathname has less than <n> nodes
+ * in it, the return pointer will be to the beginning of the string.
+ */
+static inline U8 *
+PathName_Last_N_Nodes(U8 *s, unsigned int n)
+{
+       U8 *p = s;
+       unsigned int node_count = 0;
+       while (*p != '\0') {
+               if ((*p == '/') || (*p == '\\'))
+                       node_count++;
+               p++;
+       }
+       if (node_count <= n)
+               return s;
+       while (n > 0) {
+               p--;
+               if (p == s)
+                       break;  /* should never happen, unless someone
+                                * is changing the string while we are
+                                * looking at it!! */
+               if ((*p == '/') || (*p == '\\'))
+                       n--;
+       }
+       return p + 1;
+}
+
+static inline int
+ULTRA_channel_client_acquire_os(void *pChannel, U8 *chanId, void *logCtx,
+                               char *file, int line, char *func)
+{
+       CHANNEL_HEADER *pChan = (CHANNEL_HEADER *) (pChannel);
+
+       if (pChan->CliStateOS == CHANNELCLI_DISABLED) {
+               if ((pChan->
+                    CliErrorOS & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
+                       /* we are NOT throttling this message */
+                       pChan->CliErrorOS |=
+                               ULTRA_CLIERROROS_THROTTLEMSG_DISABLED;
+                       /* throttle until acquire successful */
+
+                       UltraLogEvent(logCtx,
+                                     CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
+                                     CHANNELSTATE_DIAG_SEVERITY,
+                                     CHANNELSTATE_DIAG_SUBSYS, func, line,
+                                     "%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED @%s:%d\n",
+                                     chanId, PathName_Last_N_Nodes(
+                                             (U8 *) file, 4), line);
+               }
+               return 0;
+       }
+       if ((pChan->CliStateOS != CHANNELCLI_OWNED)
+           && (pChan->CliStateBoot == CHANNELCLI_DISABLED)) {
+               /* Our competitor is DISABLED, so we can transition to OWNED */
+               UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+                             CHANNELSTATE_DIAG_SEVERITY,
+                             CHANNELSTATE_DIAG_SUBSYS, func, line,
+                             "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n",
+                             chanId, "CliStateOS",
+                             ULTRA_CHANNELCLI_STRING(pChan->CliStateOS),
+                             pChan->CliStateOS,
+                             ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
+                             CHANNELCLI_OWNED,
+                             PathName_Last_N_Nodes((U8 *) file, 4), line);
+               pChan->CliStateOS = CHANNELCLI_OWNED;
+               MEMORYBARRIER;
+       }
+       if (pChan->CliStateOS == CHANNELCLI_OWNED) {
+               if (pChan->CliErrorOS != 0) {
+                       /* we are in an error msg throttling state;
+                        * come out of it */
+                       UltraLogEvent(logCtx,
+                                     CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+                                     CHANNELSTATE_DIAG_SEVERITY,
+                                     CHANNELSTATE_DIAG_SUBSYS, func, line,
+                                     "%s Channel OS client acquire now successful @%s:%d\n",
+                                     chanId, PathName_Last_N_Nodes((U8 *) file,
+                                                                   4), line);
+                       pChan->CliErrorOS = 0;
+               }
+               return 1;
+       }
+
+       /* We have to do it the "hard way".  We transition to BUSY,
+       * and can use the channel iff our competitor has not also
+       * transitioned to BUSY. */
+       if (pChan->CliStateOS != CHANNELCLI_ATTACHED) {
+               if ((pChan->
+                    CliErrorOS & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) ==
+                   0) {
+                       /* we are NOT throttling this message */
+                       pChan->CliErrorOS |=
+                               ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED;
+                       /* throttle until acquire successful */
+                       UltraLogEvent(logCtx,
+                                     CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
+                                     CHANNELSTATE_DIAG_SEVERITY,
+                                     CHANNELSTATE_DIAG_SUBSYS, func, line,
+                                     "%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d)) @%s:%d\n",
+                                     chanId,
+                                     ULTRA_CHANNELCLI_STRING(pChan->CliStateOS),
+                                     pChan->CliStateOS,
+                                     PathName_Last_N_Nodes((U8 *) file, 4),
+                                     line);
+               }
+               return 0;
+       }
+       pChan->CliStateOS = CHANNELCLI_BUSY;
+       MEMORYBARRIER;
+       if (pChan->CliStateBoot == CHANNELCLI_BUSY) {
+               if ((pChan->CliErrorOS & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) ==
+                   0) {
+                       /* we are NOT throttling this message */
+                       pChan->CliErrorOS |= ULTRA_CLIERROROS_THROTTLEMSG_BUSY;
+                       /* throttle until acquire successful */
+                       UltraLogEvent(logCtx,
+                                     CHANNELSTATE_DIAG_EVENTID_TRANSITBUSY,
+                                     CHANNELSTATE_DIAG_SEVERITY,
+                                     CHANNELSTATE_DIAG_SUBSYS, func, line,
+                                     "%s Channel StateTransition failed - host OS acquire failed because boot BUSY @%s:%d\n",
+                                     chanId, PathName_Last_N_Nodes((U8 *) file,
+                                                                   4), line);
+               }
+               pChan->CliStateOS = CHANNELCLI_ATTACHED;        /* reset busy */
+               MEMORYBARRIER;
+               return 0;
+       }
+       if (pChan->CliErrorOS != 0) {
+               /* we are in an error msg throttling state; come out of it */
+               UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+                             CHANNELSTATE_DIAG_SEVERITY,
+                             CHANNELSTATE_DIAG_SUBSYS, func, line,
+                             "%s Channel OS client acquire now successful @%s:%d\n",
+                             chanId, PathName_Last_N_Nodes((U8 *) file, 4),
+                             line);
+               pChan->CliErrorOS = 0;
+       }
+       return 1;
+}
+
+static inline void
+ULTRA_channel_client_release_os(void *pChannel, U8 *chanId, void *logCtx,
+                               char *file, int line, char *func)
+{
+       CHANNEL_HEADER *pChan = (CHANNEL_HEADER *) (pChannel);
+       if (pChan->CliErrorOS != 0) {
+               /* we are in an error msg throttling state; come out of it */
+               UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+                             CHANNELSTATE_DIAG_SEVERITY,
+                             CHANNELSTATE_DIAG_SUBSYS, func, line,
+                             "%s Channel OS client error state cleared @%s:%d\n",
+                             chanId, PathName_Last_N_Nodes((U8 *) file, 4),
+                             line);
+               pChan->CliErrorOS = 0;
+       }
+       if (pChan->CliStateOS == CHANNELCLI_OWNED)
+               return;
+       if (pChan->CliStateOS != CHANNELCLI_BUSY) {
+               UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
+                             CHANNELSTATE_DIAG_SEVERITY,
+                             CHANNELSTATE_DIAG_SUBSYS, func, line,
+                             "%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d)) @%s:%d\n",
+                             chanId,
+                             ULTRA_CHANNELCLI_STRING(pChan->CliStateOS),
+                             pChan->CliStateOS,
+                             PathName_Last_N_Nodes((U8 *) file, 4), line);
+               /* return; */
+       }
+       pChan->CliStateOS = CHANNELCLI_ATTACHED;        /* release busy */
+}
+
+/*
+* Routine Description:
+* Tries to insert the prebuilt signal pointed to by pSignal into the nth
+* Queue of the Channel pointed to by pChannel
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+* pSignal: (IN) pointer to the signal
+*
+* Assumptions:
+* - pChannel, Queue and pSignal are valid.
+* - If insertion fails due to a full queue, the caller will determine the
+* retry policy (e.g. wait & try again, report an error, etc.).
+*
+* Return value: 1 if the insertion succeeds, 0 if the queue was
+* full.
+*/
+
+unsigned char SignalInsert(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal);
+
+/*
+* Routine Description:
+* Removes one signal from Channel pChannel's nth Queue at the
+* time of the call and copies it into the memory pointed to by
+* pSignal.
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+* pSignal: (IN) pointer to where the signals are to be copied
+*
+* Assumptions:
+* - pChannel and Queue are valid.
+* - pSignal points to a memory area large enough to hold queue's SignalSize
+*
+* Return value: 1 if the removal succeeds, 0 if the queue was
+* empty.
+*/
+
+unsigned char SignalRemove(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal);
+
+/*
+* Routine Description:
+* Removes all signals present in Channel pChannel's nth Queue at the
+* time of the call and copies them into the memory pointed to by
+* pSignal.  Returns the # of signals copied as the value of the routine.
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+* pSignal: (IN) pointer to where the signals are to be copied
+*
+* Assumptions:
+* - pChannel and Queue are valid.
+* - pSignal points to a memory area large enough to hold Queue's MaxSignals
+* # of signals, each of which is Queue's SignalSize.
+*
+* Return value:
+* # of signals copied.
+*/
+unsigned int SignalRemoveAll(pCHANNEL_HEADER pChannel, U32 Queue,
+                            void *pSignal);
+
+/*
+* Routine Description:
+* Determine whether a signal queue is empty.
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+*
+* Return value:
+* 1 if the signal queue is empty, 0 otherwise.
+*/
+unsigned char SignalQueueIsEmpty(pCHANNEL_HEADER pChannel, U32 Queue);
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/channels/channel_guid.h b/drivers/staging/unisys/common-spar/include/channels/channel_guid.h
new file mode 100644 (file)
index 0000000..ae0dc2b
--- /dev/null
@@ -0,0 +1,64 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * CHANNEL Guids
+ */
+
+/* Used in IOChannel
+ * {414815ed-c58c-11da-95a9-00e08161165f}
+ */
+#define ULTRA_VHBA_CHANNEL_PROTOCOL_GUID \
+       { 0x414815ed, 0xc58c, 0x11da, \
+               { 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f } }
+static const GUID UltraVhbaChannelProtocolGuid =
+       ULTRA_VHBA_CHANNEL_PROTOCOL_GUID;
+
+/* Used in IOChannel
+ * {8cd5994d-c58e-11da-95a9-00e08161165f}
+ */
+#define ULTRA_VNIC_CHANNEL_PROTOCOL_GUID \
+       { 0x8cd5994d, 0xc58e, 0x11da, \
+               { 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f } }
+static const GUID UltraVnicChannelProtocolGuid =
+       ULTRA_VNIC_CHANNEL_PROTOCOL_GUID;
+
+/* Used in IOChannel
+ * {72120008-4AAB-11DC-8530-444553544200}
+ */
+#define ULTRA_SIOVM_GUID \
+       { 0x72120008, 0x4AAB, 0x11DC,                                   \
+               { 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00 } }
+static const GUID UltraSIOVMGuid = ULTRA_SIOVM_GUID;
+
+
+/* Used in visornoop/visornoop_main.c
+ * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f}
+ */
+#define ULTRA_CONTROLDIRECTOR_CHANNEL_PROTOCOL_GUID  \
+       { 0x5b52c5ac, 0xe5f5, 0x4d42, \
+               { 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f } }
+
+static const GUID UltraControlDirectorChannelProtocolGuid =
+       ULTRA_CONTROLDIRECTOR_CHANNEL_PROTOCOL_GUID;
+
+/* Used in visorchipset/visorchipset_main.c
+ * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C}
+ */
+#define ULTRA_DIAG_POOL_CHANNEL_PROTOCOL_GUID                          \
+       {0xb4e79625, 0xaede, 0x4eaa,                                    \
+               { 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c } }
+
+
diff --git a/drivers/staging/unisys/common-spar/include/channels/controlframework.h b/drivers/staging/unisys/common-spar/include/channels/controlframework.h
new file mode 100644 (file)
index 0000000..5126433
--- /dev/null
@@ -0,0 +1,77 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Module Name:
+ *  controlframework.h
+ *
+ * Abstract: This file defines common structures in the unmanaged
+ *          Ultravisor (mostly EFI) space.
+ *
+ */
+
+#ifndef _CONTROL_FRAMEWORK_H_
+#define _CONTROL_FRAMEWORK_H_
+
+#include "commontypes.h"
+#include "channel.h"
+
+#define ULTRA_MEMORY_COUNT_Ki 1024
+
+/* Scale order 0 is one 32-bit (4-byte) word (in 64 or 128-bit
+ * architecture potentially 64 or 128-bit word) */
+#define ULTRA_MEMORY_PAGE_WORD 4
+
+/* Define Ki scale page to be traditional 4KB page */
+#define ULTRA_MEMORY_PAGE_Ki (ULTRA_MEMORY_PAGE_WORD * ULTRA_MEMORY_COUNT_Ki)
+typedef struct _ULTRA_SEGMENT_STATE  {
+       U16 Enabled:1;          /* Bit 0: May enter other states */
+       U16 Active:1;           /* Bit 1: Assigned to active partition */
+       U16 Alive:1;            /* Bit 2: Configure message sent to
+                                * service/server */
+       U16 Revoked:1;          /* Bit 3: similar to partition state
+                                * ShuttingDown */
+       U16 Allocated:1;        /* Bit 4: memory (device/port number)
+                                * has been selected by Command */
+       U16 Known:1;            /* Bit 5: has been introduced to the
+                                * service/guest partition */
+       U16 Ready:1;            /* Bit 6: service/Guest partition has
+                                * responded to introduction */
+       U16 Operating:1;        /* Bit 7: resource is configured and
+                                * operating */
+       /* Note: don't use high bit unless we need to switch to ushort
+        * which is non-compliant */
+} ULTRA_SEGMENT_STATE;
+static const ULTRA_SEGMENT_STATE SegmentStateRunning = {
+       1, 1, 1, 0, 1, 1, 1, 1
+};
+static const ULTRA_SEGMENT_STATE SegmentStatePaused = {
+       1, 1, 1, 0, 1, 1, 1, 0
+};
+static const ULTRA_SEGMENT_STATE SegmentStateStandby = {
+       1, 1, 0, 0, 1, 1, 1, 0
+};
+typedef union {
+       U64 Full;
+       struct {
+               U8 Major;       /* will be 1 for the first release and
+                                * increment thereafter  */
+               U8 Minor;
+               U16 Maintenance;
+               U32 Revision;   /* Subversion revision */
+       } Part;
+} ULTRA_COMPONENT_VERSION;
+
+#endif                         /* _CONTROL_FRAMEWORK_H_ not defined */
diff --git a/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h b/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h
new file mode 100644 (file)
index 0000000..47f1c4f
--- /dev/null
@@ -0,0 +1,619 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CONTROLVMCHANNEL_H__
+#define __CONTROLVMCHANNEL_H__
+
+#include "commontypes.h"
+#include "channel.h"
+#include "controlframework.h"
+enum { INVALID_GUEST_FIRMWARE, SAMPLE_GUEST_FIRMWARE,
+           TIANO32_GUEST_FIRMWARE, TIANO64_GUEST_FIRMWARE
+};
+
+/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
+#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_GUID  \
+       {0x2b3c2d10, 0x7ef5, 0x4ad8, \
+               {0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d} }
+
+static const GUID UltraControlvmChannelProtocolGuid =
+       ULTRA_CONTROLVM_CHANNEL_PROTOCOL_GUID;
+
+#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \
+       ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define CONTROLVM_MESSAGE_MAX     64
+
+/* Must increment this whenever you insert or delete fields within
+* this channel struct.  Also increment whenever you change the meaning
+* of fields within this channel struct so as to break pre-existing
+* software.  Note that you can usually add fields to the END of the
+* channel struct withOUT needing to increment this. */
+#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID  1
+
+#define ULTRA_CONTROLVM_CHANNEL_OK_CLIENT(pChannel, logCtx)           \
+       (ULTRA_check_channel_client(pChannel, \
+               UltraControlvmChannelProtocolGuid, \
+               "controlvm", \
+               sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL), \
+               ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \
+               ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE, \
+               __FILE__, __LINE__, logCtx))
+#define ULTRA_CONTROLVM_CHANNEL_OK_SERVER(actualBytes, logCtx)        \
+       (ULTRA_check_channel_server(UltraControlvmChannelProtocolGuid,  \
+                                   "controlvm",                        \
+                                   sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL), \
+                                   actualBytes, __FILE__, __LINE__, logCtx))
+
+#define MY_DEVICE_INDEX 0
+#define MAX_MACDATA_LEN 8 /* number of bytes for MAC address in config packet */
+#define MAX_SERIAL_NUM 32
+
+#define DISK_ZERO_PUN_NUMBER   1  /* Target ID on the SCSI bus for LUN 0 */
+#define DISK_ZERO_LUN_NUMBER   3  /* Logical Unit Number */
+
+/* Defines for various channel queues... */
+#define CONTROLVM_QUEUE_REQUEST                0
+#define CONTROLVM_QUEUE_RESPONSE       1
+#define        CONTROLVM_QUEUE_EVENT           2
+#define CONTROLVM_QUEUE_ACK            3
+
+/* Max number of messages stored during IOVM creation to be reused
+ * after crash */
+#define CONTROLVM_CRASHMSG_MAX         2
+
+/** Ids for commands that may appear in either queue of a ControlVm channel.
+ *
+ *  Commands that are initiated by the command partition (CP), by an IO or
+ *  console service partition (SP), or by a guest partition (GP)are:
+ *  - issued on the RequestQueue queue (q #0) in the ControlVm channel
+ *  - responded to on the ResponseQueue queue (q #1) in the ControlVm channel
+ *
+ *  Events that are initiated by an IO or console service partition (SP) or
+ *  by a guest partition (GP) are:
+ *  - issued on the EventQueue queue (q #2) in the ControlVm channel
+ *  - responded to on the EventAckQueue queue (q #3) in the ControlVm channel
+ */
+typedef enum  {
+       CONTROLVM_INVALID = 0,
+       /* SWITCH commands required Parameter: SwitchNumber  */
+       /* BUS commands required Parameter: BusNumber  */
+       CONTROLVM_BUS_CREATE = 0x101,   /* CP --> SP, GP */
+       CONTROLVM_BUS_DESTROY = 0x102,  /* CP --> SP, GP */
+       CONTROLVM_BUS_CONFIGURE = 0x104,        /* CP --> SP */
+       CONTROLVM_BUS_CHANGESTATE = 0x105,      /* CP --> SP, GP */
+       CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */
+/* DEVICE commands required Parameter: BusNumber, DeviceNumber  */
+
+       CONTROLVM_DEVICE_CREATE = 0x201,        /* CP --> SP, GP */
+       CONTROLVM_DEVICE_DESTROY = 0x202,       /* CP --> SP, GP */
+       CONTROLVM_DEVICE_CONFIGURE = 0x203,     /* CP --> SP */
+       CONTROLVM_DEVICE_CHANGESTATE = 0x204,   /* CP --> SP, GP */
+       CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */
+       CONTROLVM_DEVICE_RECONFIGURE = 0x206,   /* CP --> Boot */
+/* DISK commands required Parameter: BusNumber, DeviceNumber  */
+       CONTROLVM_DISK_CREATE = 0x221,  /* CP --> SP */
+       CONTROLVM_DISK_DESTROY = 0x222, /* CP --> SP */
+       CONTROLVM_DISK_CONFIGURE = 0x223,       /* CP --> SP */
+       CONTROLVM_DISK_CHANGESTATE = 0x224,     /* CP --> SP */
+/* CHIPSET commands */
+       CONTROLVM_CHIPSET_INIT = 0x301, /* CP --> SP, GP */
+       CONTROLVM_CHIPSET_STOP = 0x302, /* CP --> SP, GP */
+       CONTROLVM_CHIPSET_SHUTDOWN = 0x303,     /* CP --> SP */
+       CONTROLVM_CHIPSET_READY = 0x304,        /* CP --> SP */
+       CONTROLVM_CHIPSET_SELFTEST = 0x305,     /* CP --> SP */
+
+} CONTROLVM_ID;
+
+struct InterruptInfo {
+        /**< specifies interrupt info. It is used to send interrupts
+         *   for this channel. The peer at the end of this channel
+         *   who has registered an interrupt (using recv fields
+         *   above) will receive the interrupt. Passed as a parameter
+         *   to Issue_VMCALL_IO_QUEUE_TRANSITION, which generates the
+         *   interrupt.  Currently this is used by IOPart-SP to wake
+         *   up GP when Data Channel transitions from empty to
+         *   non-empty.*/
+       U64 sendInterruptHandle;
+
+        /**< specifies interrupt handle. It is used to retrieve the
+         *   corresponding interrupt pin from Monitor; and the
+         *   interrupt pin is used to connect to the corresponding
+         *   intrrupt.  Used by IOPart-GP only. */
+       U64 recvInterruptHandle;
+
+        /**< specifies interrupt vector. It, interrupt pin, and shared are
+         *   used to connect to the corresponding interrupt.  Used by
+         *   IOPart-GP only. */
+       U32 recvInterruptVector;
+
+    /**< specifies if the recvInterrupt is shared.  It, interrupt pin
+     *   and vector are used to connect to 0 = not shared; 1 = shared.
+     *   the corresponding interrupt.  Used by IOPart-GP only. */
+       U8 recvInterruptShared;
+       U8 reserved[3]; /* Natural alignment purposes */
+};
+
+struct PciId {
+       U16 Domain;
+       U8 Bus;
+       U8 Slot;
+       U8 Func;
+       U8 Reserved[3]; /* Natural alignment purposes */
+};
+
+struct PciConfigHdr {
+       U16 VendorId;
+       U16 SubSysVendor;
+       U16 DeviceId;
+       U16 SubSysDevice;
+       U32 ClassCode;
+       U32 Reserved;           /* Natural alignment purposes */
+};
+
+struct ScsiId {
+       U32 Bus;
+       U32 Target;
+       U32 Lun;
+       U32 Host; /* Command should ignore this for *
+                  * DiskArrival/RemovalEvents */
+};
+
+struct WWID {
+       U32 wwid1;
+       U32 wwid2;
+};
+
+struct virtDiskInfo  {
+       U32 switchNo;           /* defined by SWITCH_CREATE */
+       U32 externalPortNo;     /* 0 for SAS RAID provided (external)
+                                * virtual disks, 1 for virtual disk
+                                * images, 2 for gold disk images */
+       U16 VirtualDiskIndex;   /* Index of disk descriptor in the
+                                * VirtualDisk segment associated with
+                                * externalPortNo */
+       U16 Reserved1;
+       U32 Reserved2;
+};
+
+typedef enum {
+       CONTROLVM_ACTION_NONE = 0,
+       CONTROLVM_ACTION_SET_RESTORE = 0x05E7,
+       CONTROLVM_ACTION_CLEAR_RESTORE = 0x0C18,
+       CONTROLVM_ACTION_RESTORING = 0x08E5,
+       CONTROLVM_ACTION_RESTORE_BUSY = 0x0999,
+       CONTROLVM_ACTION_CLEAR_NVRAM = 0xB01
+} CONTROLVM_ACTION;
+
+typedef enum _ULTRA_TOOL_ACTIONS {
+           /* enumeration that defines intended action  */
+           ULTRA_TOOL_ACTION_NONE = 0, /* normal boot of boot disk */
+       ULTRA_TOOL_ACTION_INSTALL = 1,  /* install source disk(s) to boot
+                                        * disk */
+       ULTRA_TOOL_ACTION_CAPTURE = 2,  /* capture boot disk to target disk(s)
+                                        * as 'gold image' */
+       ULTRA_TOOL_ACTION_REPAIR = 3,   /* use source disk(s) to repair
+                                        * installation on boot disk */
+       ULTRA_TOOL_ACTION_CLEAN = 4,    /* 'scrub' virtual disk before
+                                        * releasing back to storage pool */
+       ULTRA_TOOL_ACTION_UPGRADE = 5,  /* upgrade to use content of images
+                                        * referenced from newer blueprint */
+       ULTRA_TOOL_ACTION_DIAG = 6,     /* use tool to invoke diagnostic script
+                                        * provided by blueprint */
+       ULTRA_TOOL_ACTION_FAILED = 7,   /* used when tool fails installation
+                                          and cannot continue */
+       ULTRA_TOOL_ACTION_COUNT = 8
+} ULTRA_TOOL_ACTIONS;
+
+typedef struct _ULTRA_EFI_SPAR_INDICATION  {
+       U64 BootToFirmwareUI:1; /* Bit 0: Stop in uefi ui */
+       U64 ClearNvram:1;       /* Bit 1: Clear NVRAM */
+       U64 ClearCmos:1;        /* Bit 2: Clear CMOS */
+       U64 BootToTool:1;       /* Bit 3: Run install tool */
+       /* remaining bits are available */
+} ULTRA_EFI_SPAR_INDICATION;
+
+typedef enum {
+       ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001,
+       ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
+       ULTRA_CHIPSET_FEATURE_PCIVBUS = 0x00000004
+} ULTRA_CHIPSET_FEATURE;
+
+/** This is the common structure that is at the beginning of every
+ *  ControlVm message (both commands and responses) in any ControlVm
+ *  queue.  Commands are easily distinguished from responses by
+ *  looking at the flags.response field.
+ */
+typedef struct _CONTROLVM_MESSAGE_HEADER  {
+       U32 Id;         /* See CONTROLVM_ID. */
+       /* For requests, indicates the message type. */
+       /* For responses, indicates the type of message we are responding to. */
+
+       U32 MessageSize;        /* Includes size of this struct + size
+                                * of message */
+       U32 SegmentIndex;       /* Index of segment containing Vm
+                                * message/information */
+       U32 CompletionStatus;   /* Error status code or result of
+                                * message completion */
+       struct  {
+               U32 failed:1;              /**< =1 in a response to * signify
+                                           * failure */
+               U32 responseExpected:1;   /**< =1 in all messages that expect a
+                                          * response (Control ignores this
+                                          * bit) */
+               U32 server:1;              /**< =1 in all bus & device-related
+                                           * messages where the message
+                                           * receiver is to act as the bus or
+                                           * device server */
+               U32 testMessage:1;         /**< =1 for testing use only
+                                           * (Control and Command ignore this
+                                           * bit) */
+               U32 partialCompletion:1;  /**< =1 if there are forthcoming
+                                          * responses/acks associated
+                                          * with this message */
+               U32 preserve:1;        /**< =1 this is to let us know to
+                                       * preserve channel contents
+                                       * (for running guests)*/
+               U32 writerInDiag:1;     /**< =1 the DiagWriter is active in the
+                                        * Diagnostic Partition*/
+
+                   /* remaining bits in this 32-bit word are available */
+       } Flags;
+       U32 Reserved;           /* Natural alignment */
+       U64 MessageHandle;      /* Identifies the particular message instance,
+                                * and is used to match particular */
+       /* request instances with the corresponding response instance. */
+       U64 PayloadVmOffset;    /* Offset of payload area from start of this
+                                * instance of ControlVm segment */
+       U32 PayloadMaxBytes;    /* Maximum bytes allocated in payload
+                                * area of ControlVm segment */
+       U32 PayloadBytes;       /* Actual number of bytes of payload
+                                * area to copy between IO/Command; */
+       /* if non-zero, there is a payload to copy. */
+} CONTROLVM_MESSAGE_HEADER;
+
+typedef struct _CONTROLVM_PACKET_DEVICE_CREATE  {
+       U32 busNo;         /**< bus # (0..n-1) from the msg receiver's
+                           * perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+       U32 devNo;         /**< bus-relative (0..n-1) device number */
+       U64 channelAddr;  /**< Guest physical address of the channel, which
+                       *   can be dereferenced by the receiver
+                       *   of this ControlVm command */
+       U64 channelBytes; /**< specifies size of the channel in bytes */
+       GUID dataTypeGuid;/**< specifies format of data in channel */
+       GUID devInstGuid; /**< instance guid for the device */
+       struct InterruptInfo intr; /**< specifies interrupt information */
+} CONTROLVM_PACKET_DEVICE_CREATE;      /* for CONTROLVM_DEVICE_CREATE */
+
+typedef struct _CONTROLVM_PACKET_DEVICE_CONFIGURE  {
+       U32 busNo;            /**< bus # (0..n-1) from the msg
+                              * receiver's perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+       U32 devNo;            /**< bus-relative (0..n-1) device number */
+} CONTROLVM_PACKET_DEVICE_CONFIGURE;   /* for CONTROLVM_DEVICE_CONFIGURE */
+
+typedef struct _CONTROLVM_MESSAGE_DEVICE_CREATE  {
+       CONTROLVM_MESSAGE_HEADER Header;
+       CONTROLVM_PACKET_DEVICE_CREATE Packet;
+} CONTROLVM_MESSAGE_DEVICE_CREATE;     /* total 128 bytes */
+
+typedef struct _CONTROLVM_MESSAGE_DEVICE_CONFIGURE  {
+       CONTROLVM_MESSAGE_HEADER Header;
+       CONTROLVM_PACKET_DEVICE_CONFIGURE Packet;
+} CONTROLVM_MESSAGE_DEVICE_CONFIGURE;  /* total 56 bytes */
+
+/* This is the format for a message in any ControlVm queue. */
+typedef struct _CONTROLVM_MESSAGE_PACKET  {
+       union  {
+
+               /* BEGIN Request messages */
+               struct  {
+                       U32 busNo;            /*< bus # (0..n-1) from the msg
+                                              * receiver's perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+                       U32 deviceCount;      /*< indicates the max number of
+                                              * devices on this bus */
+                       U64 channelAddr;     /*< Guest physical address of the
+                                             *   channel, which can be
+                                             *   dereferenced by the receiver
+                                             *   of this ControlVm command */
+                       U64 channelBytes;    /*< size of the channel in bytes */
+                       GUID busDataTypeGuid;/*< indicates format of data in bus
+                                             * channel */
+                       GUID busInstGuid;    /*< instance guid for the bus */
+               } createBus;    /* for CONTROLVM_BUS_CREATE */
+               struct  {
+                       U32 busNo;            /*< bus # (0..n-1) from the msg
+                                              * receiver's perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+                       U32 reserved;   /* Natural alignment purposes */
+               } destroyBus;   /* for CONTROLVM_BUS_DESTROY */
+               struct  {
+                       U32 busNo;                  /*< bus # (0..n-1) from the
+                                                    * msg receiver's
+                                                    * perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+                       U32 reserved1;              /* for alignment purposes */
+                       U64 guestHandle;            /* This is used to convert
+                                        *  guest physical address to real
+                                        *  physical address for DMA, for ex. */
+                       U64 recvBusInterruptHandle;/*< specifies interrupt
+                                        *   info. It is used by SP to register
+                                        *   to receive interrupts from the CP.
+                                        *   This interrupt is used for bus
+                                        *   level notifications.  The
+                                        *   corresponding
+                                        *   sendBusInterruptHandle is kept in
+                                        *   CP. */
+               } configureBus; /* for CONTROLVM_BUS_CONFIGURE */
+
+               /* for CONTROLVM_DEVICE_CREATE */
+               CONTROLVM_PACKET_DEVICE_CREATE createDevice;
+               struct  {
+                       U32 busNo;            /*< bus # (0..n-1) from the msg
+                                              * receiver's perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+                       U32 devNo;            /*< bus-relative (0..n-1) device
+                                              * number */
+               } destroyDevice;        /* for CONTROLVM_DEVICE_DESTROY */
+
+               /* for CONTROLVM_DEVICE_CONFIGURE */
+               CONTROLVM_PACKET_DEVICE_CONFIGURE configureDevice;
+               struct  {
+                       U32 busNo;            /*< bus # (0..n-1) from the msg
+                                              * receiver's perspective */
+
+           /* Control uses header SegmentIndex field to access bus number... */
+                       U32 devNo;            /*< bus-relative (0..n-1) device
+                                              * number */
+               } reconfigureDevice;    /* for CONTROLVM_DEVICE_RECONFIGURE */
+               struct  {
+                       U32 busNo;
+                       ULTRA_SEGMENT_STATE state;
+                       U8 reserved[2]; /* Natural alignment purposes */
+               } busChangeState;       /* for CONTROLVM_BUS_CHANGESTATE */
+               struct  {
+                       U32 busNo;
+                       U32 devNo;
+                       ULTRA_SEGMENT_STATE state;
+                       struct  {
+                               U32 physicalDevice:1;   /* =1 if message is for
+                                                        * a physical device */
+                       /* remaining bits in this 32-bit word are available */
+                       } flags;
+                       U8 reserved[2]; /* Natural alignment purposes */
+               } deviceChangeState;    /* for CONTROLVM_DEVICE_CHANGESTATE */
+               struct  {
+                       U32 busNo;
+                       U32 devNo;
+                       ULTRA_SEGMENT_STATE state;
+                       U8 reserved[6]; /* Natural alignment purposes */
+               } deviceChangeStateEvent; /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */
+               struct  {
+                       U32 busCount; /*< indicates the max number of busses */
+                       U32 switchCount; /*< indicates the max number of
+                                         *   switches (applicable for service
+                                         *   partition only) */
+                       ULTRA_CHIPSET_FEATURE features;
+                       U32 platformNumber;     /* Platform Number */
+               } initChipset;  /* for CONTROLVM_CHIPSET_INIT */
+               struct  {
+                       U32 Options; /*< reserved */
+                       U32 Test;    /*< bit 0 set to run embedded selftest */
+               } chipsetSelftest;      /* for CONTROLVM_CHIPSET_SELFTEST */
+
+                   /* END Request messages */
+
+                   /* BEGIN Response messages */
+
+                   /* END Response messages */
+
+                   /* BEGIN Event messages */
+
+                   /* END Event messages */
+
+                   /* BEGIN Ack messages */
+
+                   /* END Ack messages */
+               U64 addr;           /*< a physical address of something, that
+                                    *   can be dereferenced by the receiver of
+                                    *   this ControlVm command (depends on
+                                    *   command id) */
+               U64 handle;         /*< a handle of something (depends on
+                                    * command id) */
+       };
+} CONTROLVM_MESSAGE_PACKET;
+
+/* All messages in any ControlVm queue have this layout. */
+typedef struct _CONTROLVM_MESSAGE  {
+       CONTROLVM_MESSAGE_HEADER hdr;
+       CONTROLVM_MESSAGE_PACKET cmd;
+} CONTROLVM_MESSAGE;
+
+typedef struct _DEVICE_MAP  {
+       GUEST_PHYSICAL_ADDRESS DeviceChannelAddress;
+       U64 DeviceChannelSize;
+       U32 CA_Index;
+       U32 Reserved;           /* natural alignment */
+       U64 Reserved2;          /* Align structure on 32-byte boundary */
+} DEVICE_MAP;
+
+typedef struct _GUEST_DEVICES  {
+       DEVICE_MAP VideoChannel;
+       DEVICE_MAP KeyboardChannel;
+       DEVICE_MAP NetworkChannel;
+       DEVICE_MAP StorageChannel;
+       DEVICE_MAP ConsoleChannel;
+       U32 PartitionIndex;
+       U32 Pad;
+} GUEST_DEVICES;
+
+typedef struct _ULTRA_CONTROLVM_CHANNEL_PROTOCOL  {
+        CHANNEL_HEADER Header;
+        GUEST_PHYSICAL_ADDRESS gpControlVm;    /* guest physical address of
+                                                * this channel */
+        GUEST_PHYSICAL_ADDRESS gpPartitionTables; /* guest physical address of
+                                                   * partition tables */
+        GUEST_PHYSICAL_ADDRESS gpDiagGuest;    /* guest physical address of
+                                                * diagnostic channel */
+        GUEST_PHYSICAL_ADDRESS gpBootRomDisk;  /* guest phys addr of (read
+                                                * only) Boot ROM disk */
+        GUEST_PHYSICAL_ADDRESS gpBootRamDisk;  /* guest phys addr of writable
+                                                * Boot RAM disk */
+        GUEST_PHYSICAL_ADDRESS gpAcpiTable;    /* guest phys addr of acpi
+                                                * table */
+        GUEST_PHYSICAL_ADDRESS gpControlChannel; /* guest phys addr of control
+                                                  * channel */
+        GUEST_PHYSICAL_ADDRESS gpDiagRomDisk;  /* guest phys addr of diagnostic
+                                                * ROM disk */
+        GUEST_PHYSICAL_ADDRESS gpNvram;        /* guest phys addr of NVRAM
+                                                * channel */
+        U64 RequestPayloadOffset;      /* Offset to request payload area */
+        U64 EventPayloadOffset;        /* Offset to event payload area */
+        U32 RequestPayloadBytes;       /* Bytes available in request payload
+                                        * area */
+        U32 EventPayloadBytes; /* Bytes available in event payload area */
+        U32 ControlChannelBytes;
+        U32 NvramChannelBytes; /* Bytes in PartitionNvram segment */
+        U32 MessageBytes;      /* sizeof(CONTROLVM_MESSAGE) */
+        U32 MessageCount;      /* CONTROLVM_MESSAGE_MAX */
+        GUEST_PHYSICAL_ADDRESS gpSmbiosTable;  /* guest phys addr of SMBIOS
+                                                * tables */
+        GUEST_PHYSICAL_ADDRESS gpPhysicalSmbiosTable;  /* guest phys addr of
+                                                        * SMBIOS table  */
+        /* ULTRA_MAX_GUESTS_PER_SERVICE */
+        GUEST_DEVICES gpObsoleteGuestDevices[16];
+
+        /* guest physical address of EFI firmware image base  */
+        GUEST_PHYSICAL_ADDRESS VirtualGuestFirmwareImageBase;
+
+        /* guest physical address of EFI firmware entry point  */
+        GUEST_PHYSICAL_ADDRESS VirtualGuestFirmwareEntryPoint;
+
+        /* guest EFI firmware image size  */
+        U64 VirtualGuestFirmwareImageSize;
+
+        /* GPA = 1MB where EFI firmware image is copied to  */
+        GUEST_PHYSICAL_ADDRESS VirtualGuestFirmwareBootBase;
+        GUEST_PHYSICAL_ADDRESS VirtualGuestImageBase;
+        GUEST_PHYSICAL_ADDRESS VirtualGuestImageSize;
+        U64 PrototypeControlChannelOffset;
+        GUEST_PHYSICAL_ADDRESS VirtualGuestPartitionHandle;
+
+        U16 RestoreAction;     /* Restore Action field to restore the guest
+                                * partition */
+       U16 DumpAction;         /* For Windows guests it shows if the visordisk
+                                * is running in dump mode */
+       U16 NvramFailCount;
+       U16 SavedCrashMsgCount; /* = CONTROLVM_CRASHMSG_MAX */
+       U32 SavedCrashMsgOffset;        /* Offset to request payload area needed
+                                        * for crash dump */
+       U32 InstallationError;  /* Type of error encountered during
+                                * installation */
+       U32 InstallationTextId; /* Id of string to display */
+       U16 InstallationRemainingSteps; /* Number of remaining installation
+                                        * steps (for progress bars) */
+       U8 ToolAction;          /* ULTRA_TOOL_ACTIONS Installation Action
+                                * field */
+       U8 Reserved;            /* alignment */
+       ULTRA_EFI_SPAR_INDICATION EfiSparIndication;
+       ULTRA_EFI_SPAR_INDICATION EfiSparIndicationSupported;
+       U32 SPReserved;
+       U8 Reserved2[28];       /* Force signals to begin on 128-byte cache
+                                * line */
+       SIGNAL_QUEUE_HEADER RequestQueue;       /* Service or guest partition
+                                                * uses this queue to send
+                                                * requests to Control */
+       SIGNAL_QUEUE_HEADER ResponseQueue;      /* Control uses this queue to
+                                                * respond to service or guest
+                                                * partition requests */
+       SIGNAL_QUEUE_HEADER EventQueue;         /* Control uses this queue to
+                                                * send events to service or
+                                                * guest partition */
+       SIGNAL_QUEUE_HEADER EventAckQueue;      /* Service or guest partition
+                                                * uses this queue to ack
+                                                * Control events */
+
+        /* Request fixed-size message pool - does not include payload */
+        CONTROLVM_MESSAGE RequestMsg[CONTROLVM_MESSAGE_MAX];
+
+        /* Response fixed-size message pool - does not include payload */
+        CONTROLVM_MESSAGE ResponseMsg[CONTROLVM_MESSAGE_MAX];
+
+        /* Event fixed-size message pool - does not include payload */
+        CONTROLVM_MESSAGE EventMsg[CONTROLVM_MESSAGE_MAX];
+
+        /* Ack fixed-size message pool - does not include payload */
+        CONTROLVM_MESSAGE EventAckMsg[CONTROLVM_MESSAGE_MAX];
+
+        /* Message stored during IOVM creation to be reused after crash */
+        CONTROLVM_MESSAGE SavedCrashMsg[CONTROLVM_CRASHMSG_MAX];
+} ULTRA_CONTROLVM_CHANNEL_PROTOCOL;
+
+/* Offsets for VM channel attributes... */
+#define VM_CH_REQ_QUEUE_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, RequestQueue)
+#define VM_CH_RESP_QUEUE_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, ResponseQueue)
+#define VM_CH_EVENT_QUEUE_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventQueue)
+#define VM_CH_ACK_QUEUE_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventAckQueue)
+#define VM_CH_REQ_MSG_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, RequestMsg)
+#define VM_CH_RESP_MSG_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, ResponseMsg)
+#define VM_CH_EVENT_MSG_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventMsg)
+#define VM_CH_ACK_MSG_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventAckMsg)
+#define VM_CH_CRASH_MSG_OFFSET \
+       offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, SavedCrashMsg)
+
+/* The following header will be located at the beginning of PayloadVmOffset for
+ *  various ControlVm commands. The receiver of a ControlVm command with a
+ *  PayloadVmOffset will dereference this address and then use ConnectionOffset,
+ *  InitiatorOffset, and TargetOffset to get the location of UTF-8 formatted
+ *  strings that can be parsed to obtain command-specific information. The value
+ *  of TotalLength should equal PayloadBytes.  The format of the strings at
+ *  PayloadVmOffset will take different forms depending on the message.  See the
+ *  following Wiki page for more information:
+ *  https://ustr-linux-1.na.uis.unisys.com/spar/index.php/ControlVm_Parameters_Area
+ */
+typedef struct _ULTRA_CONTROLVM_PARAMETERS_HEADER  {
+       U32 TotalLength;
+       U32 HeaderLength;
+       U32 ConnectionOffset;
+       U32 ConnectionLength;
+       U32 InitiatorOffset;
+       U32 InitiatorLength;
+       U32 TargetOffset;
+       U32 TargetLength;
+       U32 ClientOffset;
+       U32 ClientLength;
+       U32 NameOffset;
+       U32 NameLength;
+       GUID Id;
+       U32 Revision;
+       U32 Reserved;           /* Natural alignment */
+} ULTRA_CONTROLVM_PARAMETERS_HEADER;
+
+#endif                         /* __CONTROLVMCHANNEL_H__ */
diff --git a/drivers/staging/unisys/common-spar/include/channels/diagchannel.h b/drivers/staging/unisys/common-spar/include/channels/diagchannel.h
new file mode 100644 (file)
index 0000000..c93515e
--- /dev/null
@@ -0,0 +1,427 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*++
+ *
+ * Module Name:
+ *
+ * diagchannel.h
+ *
+ * Abstract:
+ *
+ * This file defines the DiagChannel protocol.  This protocol is used to aid in
+ * preserving event data sent by external applications.  This protocol provides
+ * a region for event data to reside in.  This data will eventually be sent to
+ * the Boot Partition where it will be committed to memory and/or disk.  This
+ * file contains platform-independent data that can be built using any
+ * Supervisor build environment (Windows, Linux, EFI).
+ *
+*/
+
+#ifndef _DIAG_CHANNEL_H_
+#define _DIAG_CHANNEL_H_
+
+#include "commontypes.h"
+#include "channel.h"
+
+/* {EEA7A573-DB82-447c-8716-EFBEAAAE4858} */
+#define ULTRA_DIAG_CHANNEL_PROTOCOL_GUID \
+       {0xeea7a573, 0xdb82, 0x447c, \
+               {0x87, 0x16, 0xef, 0xbe, 0xaa, 0xae, 0x48, 0x58} }
+
+static const GUID UltraDiagChannelProtocolGuid =
+       ULTRA_DIAG_CHANNEL_PROTOCOL_GUID;
+
+/* {E850F968-3263-4484-8CA5-2A35D087A5A8} */
+#define ULTRA_DIAG_ROOT_CHANNEL_PROTOCOL_GUID \
+       {0xe850f968, 0x3263, 0x4484, \
+               {0x8c, 0xa5, 0x2a, 0x35, 0xd0, 0x87, 0xa5, 0xa8} }
+
+#define ULTRA_DIAG_CHANNEL_PROTOCOL_SIGNATURE  ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+
+/* Must increment this whenever you insert or delete fields within this channel
+* struct.  Also increment whenever you change the meaning of fields within this
+* channel struct so as to break pre-existing software.  Note that you can
+* usually add fields to the END of the channel struct withOUT needing to
+* increment this. */
+#define ULTRA_DIAG_CHANNEL_PROTOCOL_VERSIONID 2
+
+#define ULTRA_DIAG_CHANNEL_OK_CLIENT(pChannel, logCtx)                 \
+       (ULTRA_check_channel_client(pChannel,                           \
+                                   UltraDiagChannelProtocolGuid,       \
+                                   "diag",                             \
+                                   sizeof(ULTRA_DIAG_CHANNEL_PROTOCOL), \
+                                   ULTRA_DIAG_CHANNEL_PROTOCOL_VERSIONID, \
+                                   ULTRA_DIAG_CHANNEL_PROTOCOL_SIGNATURE, \
+                                   __FILE__, __LINE__, logCtx))
+#define ULTRA_DIAG_CHANNEL_OK_SERVER(actualBytes, logCtx)              \
+       (ULTRA_check_channel_server(UltraDiagChannelProtocolGuid,       \
+                                   "diag",                             \
+                                   sizeof(ULTRA_DIAG_CHANNEL_PROTOCOL), \
+                                   actualBytes, __FILE__, __LINE__, logCtx))
+#define MAX_MODULE_NAME_SIZE 128       /* Maximum length of module name... */
+#define MAX_ADDITIONAL_INFO_SIZE 256   /* Maximum length of any additional info
+                                        * accompanying event... */
+#define MAX_SUBSYSTEMS 64      /* Maximum number of subsystems allowed in
+                                * DiagChannel... */
+#define LOW_SUBSYSTEMS 32      /* Half of MAX_SUBSYSTEMS to allow 64-bit
+                                * math */
+#define SUBSYSTEM_DEBUG 0      /* Standard subsystem for debug events */
+#define SUBSYSTEM_DEFAULT 1    /* Default subsystem for legacy calls to
+                                * ReportEvent */
+
+/* few useful subsystem mask values */
+#define SUBSYSTEM_MASK_DEBUG   0x01    /* Standard subsystem for debug
+                                        * events */
+#define SUBSYSTEM_MASK_DEFAULT  0x02   /* Default subsystem for legacy calls to
+                                        * ReportEvents */
+
+/* Event parameter "Severity" is overloaded with Cause in byte 2 and Severity in
+ * byte 0, bytes 1 and 3 are reserved */
+#define SEVERITY_MASK 0x0FF    /* mask out all but the Severity in byte 0 */
+#define CAUSE_MASK 0x0FF0000   /* mask out all but the cause in byte 2 */
+#define CAUSE_SHIFT_AMT 16     /* shift 2 bytes to place it in byte 2 */
+
+/* SubsystemSeverityFilter */
+#define SEVERITY_FILTER_MASK 0x0F /* mask out the Cause half, SeverityFilter is
+                                  * in the lower nibble */
+#define CAUSE_FILTER_MASK 0xF0 /* mask out the Severity half, CauseFilter is in
+                                * the upper nibble */
+#define CAUSE_FILTER_SHIFT_AMT 4 /* shift amount to place it in lower or upper
+                                  * nibble */
+
+/* Copied from EFI's EFI_TIME struct in efidef.h.  EFI headers are not allowed
+* in some of the Supervisor areas, such as Monitor, so it has been "ported" here
+* for use in diagnostic event timestamps... */
+typedef struct _DIAG_EFI_TIME  {
+       U16 Year;               /* 1998 - 20XX */
+       U8 Month;               /* 1 - 12 */
+       U8 Day;                 /* 1 - 31 */
+       U8 Hour;                /* 0 - 23 */
+       U8 Minute;              /* 0 - 59 */
+       U8 Second;              /* 0 - 59 */
+       U8 Pad1;
+       U32 Nanosecond; /* 0 - 999, 999, 999 */
+       S16 TimeZone;           /* -1440 to 1440 or 2047 */
+       U8 Daylight;
+       U8 Pad2;
+} DIAG_EFI_TIME;
+
+typedef enum  {
+        ULTRA_COMPONENT_GUEST = 0,
+        ULTRA_COMPONENT_MONITOR = 0x01,
+        ULTRA_COMPONENT_CCM = 0x02,    /* Common Control module */
+        /* RESERVED 0x03 - 0x7 */
+
+        /* Ultravisor Components */
+        ULTRA_COMPONENT_BOOT = 0x08,
+        ULTRA_COMPONENT_IDLE = 0x09,
+        ULTRA_COMPONENT_CONTROL = 0x0A,
+        ULTRA_COMPONENT_LOGGER = 0x0B,
+        ULTRA_COMPONENT_ACPI = 0X0C,
+        /* RESERVED 0x0D - 0x0F */
+
+        /* sPAR Components */
+        ULTRA_COMPONENT_COMMAND = 0x10,
+        ULTRA_COMPONENT_IODRIVER = 0x11,
+        ULTRA_COMPONENT_CONSOLE = 0x12,
+        ULTRA_COMPONENT_OPERATIONS = 0x13,
+        ULTRA_COMPONENT_MANAGEMENT = 0x14,
+        ULTRA_COMPONENT_DIAG = 0x15,
+        ULTRA_COMPONENT_HWDIAG = 0x16,
+        ULTRA_COMPONENT_PSERVICES = 0x17,
+        ULTRA_COMPONENT_PDIAG = 0x18
+        /* RESERVED 0x18 - 0x1F */
+} ULTRA_COMPONENT_TYPES;
+
+/* Structure: DIAG_CHANNEL_EVENT Purpose: Contains attributes that make up an
+ * event to be written to the DIAG_CHANNEL memory.  Attributes: EventId: Id of
+ * the diagnostic event to write to memory.  Severity: Severity of the event
+ * (Error, Info, etc).  ModuleName: Module/file name where event originated.
+ * LineNumber: Line number in module name where event originated.  Timestamp:
+ * Date/time when event was received by ReportEvent, and written to DiagChannel.
+ * Reserved: Padding to align structure on a 64-byte cache line boundary.
+ * AdditionalInfo: Array of characters for additional event info (may be
+ * empty).  */
+typedef struct _DIAG_CHANNEL_EVENT  {
+       U32 EventId;
+       U32 Severity;
+       U8 ModuleName[MAX_MODULE_NAME_SIZE];
+       U32 LineNumber;
+       DIAG_EFI_TIME Timestamp;        /* Size = 16 bytes */
+       U32 PartitionNumber;    /* Filled in by Diag Switch as pool blocks are
+                                * filled */
+       U16 VirtualProcessorNumber;
+       U16 LogicalProcessorNumber;
+       U8 ComponentType;       /* ULTRA_COMPONENT_TYPES */
+       U8 Subsystem;
+       U16 Reserved0;          /* pad to U64 alignment */
+       U32 BlockNumber;        /* filled in by DiagSwitch as pool blocks are
+                                * filled */
+       U32 BlockNumberHigh;
+       U32 EventNumber;        /* filled in by DiagSwitch as pool blocks are
+                                * filled */
+       U32 EventNumberHigh;
+
+       /* The BlockNumber and EventNumber fields are set only by DiagSwitch
+        * and referenced only by WinDiagDisplay formatting tool as
+        * additional diagnostic information.  Other tools including
+        * WinDiagDisplay currently ignore these 'Reserved' bytes. */
+       U8 Reserved[8];
+       U8 AdditionalInfo[MAX_ADDITIONAL_INFO_SIZE];
+
+       /* NOTE: Changesto DIAG_CHANNEL_EVENT generally need to be reflected in
+        * existing copies *
+        * - for AppOS at
+        * GuestLinux/visordiag_early/supervisor_diagchannel.h *
+        * - for WinDiagDisplay at
+        * EFI/Ultra/Tools/WinDiagDisplay/WinDiagDisplay/diagstruct.h */
+} DIAG_CHANNEL_EVENT;
+
+/* Levels of severity for diagnostic events, in order from lowest severity to
+* highest (i.e. fatal errors are the most severe, and should always be logged,
+* but info events rarely need to be logged except during debugging).  The values
+* DIAG_SEVERITY_ENUM_BEGIN and DIAG_SEVERITY_ENUM_END are not valid severity
+* values.  They exist merely to dilineate the list, so that future additions
+* won't require changes to the driver (i.e. when checking for out-of-range
+* severities in SetSeverity).  The values DIAG_SEVERITY_OVERRIDE and
+* DIAG_SEVERITY_SHUTOFF are not valid severity values for logging events but
+* they are valid for controlling the amount of event data.  This enum is also
+* defined in DotNet\sParFramework\ControlFramework\ControlFramework.cs.  If a
+* change is made to this enum, they should also be reflected in that file.  */
+typedef enum  { DIAG_SEVERITY_ENUM_BEGIN = 0,
+               DIAG_SEVERITY_OVERRIDE = DIAG_SEVERITY_ENUM_BEGIN,
+               DIAG_SEVERITY_VERBOSE = DIAG_SEVERITY_OVERRIDE, /* 0 */
+               DIAG_SEVERITY_INFO = DIAG_SEVERITY_VERBOSE + 1, /* 1 */
+               DIAG_SEVERITY_WARNING = DIAG_SEVERITY_INFO + 1, /* 2 */
+               DIAG_SEVERITY_ERR = DIAG_SEVERITY_WARNING + 1,  /* 3 */
+               DIAG_SEVERITY_PRINT = DIAG_SEVERITY_ERR + 1,    /* 4 */
+               DIAG_SEVERITY_SHUTOFF = DIAG_SEVERITY_PRINT + 1, /* 5 */
+               DIAG_SEVERITY_ENUM_END = DIAG_SEVERITY_SHUTOFF, /* 5 */
+               DIAG_SEVERITY_NONFATAL_ERR = DIAG_SEVERITY_ERR,
+               DIAG_SEVERITY_FATAL_ERR = DIAG_SEVERITY_PRINT
+} DIAG_SEVERITY;
+
+/* Event Cause enums
+*
+* Levels of cause for diagnostic events, in order from least to greatest cause
+* Internal errors are most urgent since ideally they should never exist
+* Invalid requests are preventable by avoiding invalid inputs
+* Operations errors depend on environmental factors which may impact which
+* requests are possible
+* Manifest provides intermediate value to capture firmware and configuration
+* version information
+* Trace provides suplimental debug information in release firmware
+* Unknown Log captures unclasified LogEvent calls.
+* Debug is the least urgent since it provides suplimental debug information only
+* in debug firmware
+* Unknown Debug captures unclassified DebugEvent calls.
+* This enum is also defined in
+* DotNet\sParFramework\ControlFramework\ControlFramework.cs.
+* If a change is made to this enum, they should also be reflected in that
+* file.  */
+
+
+
+/* A cause value "DIAG_CAUSE_FILE_XFER" together with a severity value of
+* "DIAG_SEVERITY_PRINT" (=4), is used for transferring text or binary file to
+* the Diag partition. This cause-severity combination will be used by Logger
+* DiagSwitch to segregate events into block types. The files are transferred in
+* 256 byte chunks maximum, in the AdditionalInfo field of the DIAG_CHANNEL_EVENT
+* structure. In the file transfer mode, some event fields will have different
+* meaning: EventId specifies the file offset, severity specifies the block type,
+* ModuleName specifies the filename, LineNumber specifies the number of valid
+* data bytes in an event and AdditionalInfo contains up to 256 bytes of data. */
+
+/* The Diag DiagWriter appends event blocks to events.raw as today, and for data
+ * blocks uses DIAG_CHANNEL_EVENT
+ * PartitionNumber to extract and append 'AdditionalInfo' to filename (specified
+ * by ModuleName). */
+
+/* The Dell PDiag uses this new mechanism to stash DSET .zip onto the
+ * 'diagnostic' virtual disk.  */
+typedef enum  {
+       DIAG_CAUSE_UNKNOWN = 0,
+       DIAG_CAUSE_UNKNOWN_DEBUG = DIAG_CAUSE_UNKNOWN + 1,      /* 1 */
+       DIAG_CAUSE_DEBUG = DIAG_CAUSE_UNKNOWN_DEBUG + 1,        /* 2 */
+       DIAG_CAUSE_UNKNOWN_LOG = DIAG_CAUSE_DEBUG + 1,  /* 3 */
+       DIAG_CAUSE_TRACE = DIAG_CAUSE_UNKNOWN_LOG + 1,  /* 4 */
+       DIAG_CAUSE_MANIFEST = DIAG_CAUSE_TRACE + 1,     /* 5 */
+       DIAG_CAUSE_OPERATIONS_ERROR = DIAG_CAUSE_MANIFEST + 1,  /* 6 */
+       DIAG_CAUSE_INVALID_REQUEST = DIAG_CAUSE_OPERATIONS_ERROR + 1,   /* 7 */
+       DIAG_CAUSE_INTERNAL_ERROR = DIAG_CAUSE_INVALID_REQUEST + 1, /* 8 */
+       DIAG_CAUSE_FILE_XFER = DIAG_CAUSE_INTERNAL_ERROR + 1,   /* 9 */
+       DIAG_CAUSE_ENUM_END = DIAG_CAUSE_FILE_XFER      /* 9 */
+} DIAG_CAUSE;
+
+/* Event Cause category defined into the byte 2 of Severity */
+#define CAUSE_DEBUG (DIAG_CAUSE_DEBUG << CAUSE_SHIFT_AMT)
+#define CAUSE_TRACE (DIAG_CAUSE_TRACE << CAUSE_SHIFT_AMT)
+#define CAUSE_MANIFEST (DIAG_CAUSE_MANIFEST << CAUSE_SHIFT_AMT)
+#define CAUSE_OPERATIONS_ERROR (DIAG_CAUSE_OPERATIONS_ERROR << CAUSE_SHIFT_AMT)
+#define CAUSE_INVALID_REQUEST (DIAG_CAUSE_INVALID_REQUEST << CAUSE_SHIFT_AMT)
+#define CAUSE_INTERNAL_ERROR (DIAG_CAUSE_INTERNAL_ERROR << CAUSE_SHIFT_AMT)
+#define CAUSE_FILE_XFER (DIAG_CAUSE_FILE_XFER << CAUSE_SHIFT_AMT)
+#define CAUSE_ENUM_END CAUSE_FILE_XFER
+
+/* Combine Cause and Severity categories into one */
+#define CAUSE_DEBUG_SEVERITY_VERBOSE \
+       (CAUSE_DEBUG | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_TRACE_SEVERITY_VERBOSE \
+       (CAUSE_TRACE | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_MANIFEST_SEVERITY_VERBOSE\
+       (CAUSE_MANIFEST | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_OPERATIONS_SEVERITY_VERBOSE \
+       (CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_INVALID_SEVERITY_VERBOSE \
+       (CAUSE_INVALID_REQUEST  | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_INTERNAL_SEVERITY_VERBOSE \
+       (CAUSE_INTERNAL_ERROR   | DIAG_SEVERITY_VERBOSE)
+
+#define CAUSE_DEBUG_SEVERITY_INFO \
+       (CAUSE_DEBUG | DIAG_SEVERITY_INFO)
+#define CAUSE_TRACE_SEVERITY_INFO \
+       (CAUSE_TRACE | DIAG_SEVERITY_INFO)
+#define CAUSE_MANIFEST_SEVERITY_INFO \
+       (CAUSE_MANIFEST | DIAG_SEVERITY_INFO)
+#define CAUSE_OPERATIONS_SEVERITY_INFO \
+       (CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_INFO)
+#define CAUSE_INVALID_SEVERITY_INFO \
+       (CAUSE_INVALID_REQUEST  | DIAG_SEVERITY_INFO)
+#define CAUSE_INTERNAL_SEVERITY_INFO \
+       (CAUSE_INTERNAL_ERROR | DIAG_SEVERITY_INFO)
+
+#define CAUSE_DEBUG_SEVERITY_WARN \
+       (CAUSE_DEBUG | DIAG_SEVERITY_WARNING)
+#define CAUSE_TRACE_SEVERITY_WARN \
+       (CAUSE_TRACE | DIAG_SEVERITY_WARNING)
+#define CAUSE_MANIFEST_SEVERITY_WARN \
+       (CAUSE_MANIFEST | DIAG_SEVERITY_WARNING)
+#define CAUSE_OPERATIONS_SEVERITY_WARN \
+       (CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_WARNING)
+#define CAUSE_INVALID_SEVERITY_WARN \
+       (CAUSE_INVALID_REQUEST | DIAG_SEVERITY_WARNING)
+#define CAUSE_INTERNAL_SEVERITY_WARN \
+       (CAUSE_INTERNAL_ERROR | DIAG_SEVERITY_WARNING)
+
+#define CAUSE_DEBUG_SEVERITY_ERR \
+       (CAUSE_DEBUG | DIAG_SEVERITY_ERR)
+#define CAUSE_TRACE_SEVERITY_ERR \
+       (CAUSE_TRACE | DIAG_SEVERITY_ERR)
+#define CAUSE_MANIFEST_SEVERITY_ERR \
+       (CAUSE_MANIFEST | DIAG_SEVERITY_ERR)
+#define CAUSE_OPERATIONS_SEVERITY_ERR \
+       (CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_ERR)
+#define CAUSE_INVALID_SEVERITY_ERR \
+       (CAUSE_INVALID_REQUEST  | DIAG_SEVERITY_ERR)
+#define CAUSE_INTERNAL_SEVERITY_ERR \
+       (CAUSE_INTERNAL_ERROR   | DIAG_SEVERITY_ERR)
+
+#define CAUSE_DEBUG_SEVERITY_PRINT \
+       (CAUSE_DEBUG | DIAG_SEVERITY_PRINT)
+#define CAUSE_TRACE_SEVERITY_PRINT \
+       (CAUSE_TRACE | DIAG_SEVERITY_PRINT)
+#define CAUSE_MANIFEST_SEVERITY_PRINT \
+       (CAUSE_MANIFEST | DIAG_SEVERITY_PRINT)
+#define CAUSE_OPERATIONS_SEVERITY_PRINT \
+       (CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_PRINT)
+#define CAUSE_INVALID_SEVERITY_PRINT \
+       (CAUSE_INVALID_REQUEST | DIAG_SEVERITY_PRINT)
+#define CAUSE_INTERNAL_SEVERITY_PRINT \
+       (CAUSE_INTERNAL_ERROR | DIAG_SEVERITY_PRINT)
+#define CAUSE_FILE_XFER_SEVERITY_PRINT \
+       (CAUSE_FILE_XFER | DIAG_SEVERITY_PRINT)
+
+/* Structure: DIAG_CHANNEL_PROTOCOL_HEADER
+ *
+ * Purpose: Contains attributes that make up the header specific to the
+ * DIAG_CHANNEL area.
+ *
+ * Attributes:
+ *
+ * DiagLock: Diag Channel spinlock.
+ *
+ *IsChannelInitialized: 1 iff SignalInit was called for this channel; otherwise
+ *                     0, and assume the channel is not ready for use yet.
+ *
+ * Reserved: Padding to allign the fields in this structure.
+ *
+ *SubsystemSeverityFilter: Level of severity on a subsystem basis that controls
+ *                     whether events are logged.  Any event's severity for a
+ *                     particular subsystem below this level will be discarded.
+ */
+typedef struct _DIAG_CHANNEL_PROTOCOL_HEADER  {
+       volatile U32 DiagLock;
+       U8 IsChannelInitialized;
+       U8 Reserved[3];
+       U8 SubsystemSeverityFilter[64];
+} DIAG_CHANNEL_PROTOCOL_HEADER;
+
+/* The Diagram for the Diagnostic Channel: */
+/* ----------------------- */
+/* | Channel Header        |   Defined by ULTRA_CHANNEL_PROTOCOL */
+/* ----------------------- */
+/* | Signal Queue Header   |   Defined by SIGNAL_QUEUE_HEADER */
+/* ----------------------- */
+/* | DiagChannel Header    |   Defined by DIAG_CHANNEL_PROTOCOL_HEADER */
+/* ----------------------- */
+/* | Channel Event Info    |   Defined by (DIAG_CHANNEL_EVENT * MAX_EVENTS) */
+/* ----------------------- */
+/* | Reserved              |   Reserved (pad out to 4MB) */
+/* ----------------------- */
+
+/* Offsets/sizes for diagnostic channel attributes... */
+#define DIAG_CH_QUEUE_HEADER_OFFSET (sizeof(ULTRA_CHANNEL_PROTOCOL))
+#define DIAG_CH_QUEUE_HEADER_SIZE (sizeof(SIGNAL_QUEUE_HEADER))
+#define DIAG_CH_PROTOCOL_HEADER_OFFSET \
+       (DIAG_CH_QUEUE_HEADER_OFFSET + DIAG_CH_QUEUE_HEADER_SIZE)
+#define DIAG_CH_PROTOCOL_HEADER_SIZE (sizeof(DIAG_CHANNEL_PROTOCOL_HEADER))
+#define DIAG_CH_EVENT_OFFSET \
+       (DIAG_CH_PROTOCOL_HEADER_OFFSET + DIAG_CH_PROTOCOL_HEADER_SIZE)
+#define DIAG_CH_SIZE (4096 * 1024)
+
+/* For Control and Idle Partitions with larger (8 MB) diagnostic(root)
+ * channels */
+#define DIAG_CH_LRG_SIZE (2 * DIAG_CH_SIZE)    /* 8 MB */
+
+/*
+ * Structure: ULTRA_DIAG_CHANNEL_PROTOCOL
+ *
+ * Purpose: Contains attributes that make up the DIAG_CHANNEL memory.
+ *
+ * Attributes:
+ *
+ * CommonChannelHeader:        Header info common to all channels.
+ *
+ * QueueHeader: Queue header common to all channels - used to determine where to
+ * store event.
+ *
+ * DiagChannelHeader: Diagnostic channel header info (see
+ * DIAG_CHANNEL_PROTOCOL_HEADER comments).
+ *
+ * Events: Area where diagnostic events (up to MAX_EVENTS) are written.
+ *
+ *Reserved: Reserved area to allow for correct channel size padding.
+*/
+typedef struct _ULTRA_DIAG_CHANNEL_PROTOCOL  {
+       ULTRA_CHANNEL_PROTOCOL CommonChannelHeader;
+       SIGNAL_QUEUE_HEADER QueueHeader;
+       DIAG_CHANNEL_PROTOCOL_HEADER DiagChannelHeader;
+       DIAG_CHANNEL_EVENT Events[(DIAG_CH_SIZE - DIAG_CH_EVENT_OFFSET) /
+                                  sizeof(DIAG_CHANNEL_EVENT)];
+}
+ULTRA_DIAG_CHANNEL_PROTOCOL;
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/channels/iochannel.h b/drivers/staging/unisys/common-spar/include/channels/iochannel.h
new file mode 100644 (file)
index 0000000..94e4b2a
--- /dev/null
@@ -0,0 +1,938 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION */
+/* All rights reserved. */
+#ifndef __IOCHANNEL_H__
+#define __IOCHANNEL_H__
+
+/*
+* Everything needed for IOPart-GuestPart communication is define in
+* this file.  Note: Everything is OS-independent because this file is
+* used by Windows, Linux and possible EFI drivers.  */
+
+
+/*
+* Communication flow between the IOPart and GuestPart uses the channel headers
+* channel state.  The following states are currently being used:
+*       UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED
+*
+* additional states will be used later.  No locking is needed to switch between
+* states due to the following rules:
+*
+*      1.  IOPart is only the only partition allowed to change from UNIT
+*      2.  IOPart is only the only partition allowed to change from
+*              CHANNEL_ATTACHING
+*      3.  GuestPart is only the only partition allowed to change from
+*              CHANNEL_ATTACHED
+*
+* The state changes are the following: IOPart sees the channel is in UNINIT,
+*        UNINIT -> CHANNEL_ATTACHING (performed only by IOPart)
+*        CHANNEL_ATTACHING -> CHANNEL_ATTACHED (performed only by IOPart)
+*        CHANNEL_ATTACHED -> CHANNEL_OPENED (performed only by GuestPart)
+*/
+
+#include "commontypes.h"
+#include "vmcallinterface.h"
+
+#define _ULTRA_CONTROLVM_CHANNEL_INLINE_
+#include "controlvmchannel.h"
+#include "vbuschannel.h"
+#undef _ULTRA_CONTROLVM_CHANNEL_INLINE_
+#include "channel.h"
+
+/*
+ * CHANNEL Guids
+ */
+
+#include "channel_guid.h"
+
+#define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE \
+       ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+
+/* Must increment these whenever you insert or delete fields within this channel
+* struct.  Also increment whenever you change the meaning of fields within this
+* channel struct so as to break pre-existing software.  Note that you can
+* usually add fields to the END of the channel struct withOUT needing to
+* increment this. */
+#define ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID 2
+#define ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID 2
+#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID 1
+
+#define ULTRA_VHBA_CHANNEL_OK_CLIENT(pChannel, logCtx)                 \
+       (ULTRA_check_channel_client(pChannel, UltraVhbaChannelProtocolGuid, \
+                                   "vhba", MIN_IO_CHANNEL_SIZE,        \
+                                   ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID, \
+                                   ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE, \
+                                   __FILE__, __LINE__, logCtx))
+#define ULTRA_VHBA_CHANNEL_OK_SERVER(actualBytes, logCtx)              \
+       (ULTRA_check_channel_server(UltraVhbaChannelProtocolGuid,       \
+                                   "vhba", MIN_IO_CHANNEL_SIZE, actualBytes, \
+                                   __FILE__, __LINE__, logCtx))
+#define ULTRA_VNIC_CHANNEL_OK_CLIENT(pChannel, logCtx)                 \
+       (ULTRA_check_channel_client(pChannel, UltraVnicChannelProtocolGuid, \
+                                   "vnic", MIN_IO_CHANNEL_SIZE,        \
+                                   ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID, \
+                                   ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE, \
+                                   __FILE__, __LINE__, logCtx))
+#define ULTRA_VNIC_CHANNEL_OK_SERVER(actualBytes, logCtx)              \
+       (ULTRA_check_channel_server(UltraVnicChannelProtocolGuid,       \
+                                   "vnic", MIN_IO_CHANNEL_SIZE, actualBytes, \
+                                   __FILE__, __LINE__, logCtx))
+#define ULTRA_VSWITCH_CHANNEL_OK_CLIENT(pChannel, logCtx)              \
+       (ULTRA_check_channel_client(pChannel, UltraVswitchChannelProtocolGuid, \
+                                   "vswitch", MIN_IO_CHANNEL_SIZE,     \
+                                   ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID, \
+                                   ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE, \
+                                   __FILE__, __LINE__, logCtx))
+#define ULTRA_VSWITCH_CHANNEL_OK_SERVER(actualBytes, logCtx)          \
+       (ULTRA_check_channel_server(UltraVswitchChannelProtocolGuid,    \
+                                   "vswitch", MIN_IO_CHANNEL_SIZE,     \
+                                   actualBytes,                    \
+                                   __FILE__, __LINE__, logCtx))
+/*
+* Everything necessary to handle SCSI & NIC traffic between Guest Partition and
+* IO Partition is defined below.  */
+
+
+/*
+* Defines and enums.
+*/
+
+#define MINNUM(a, b) (((a) < (b)) ? (a) : (b))
+#define MAXNUM(a, b) (((a) > (b)) ? (a) : (b))
+
+/* these define the two queues per data channel between iopart and
+ * ioguestparts */
+#define IOCHAN_TO_IOPART 0 /* used by ioguestpart to 'insert' signals to
+                           * iopart */
+#define IOCHAN_FROM_GUESTPART 0 /* used by iopart to 'remove' signals from
+                                * ioguestpart - same queue as previous queue */
+
+#define IOCHAN_TO_GUESTPART 1 /* used by iopart to 'insert' signals to
+                              * ioguestpart */
+#define IOCHAN_FROM_IOPART 1 /* used by ioguestpart to 'remove' signals from
+                             * iopart - same queue as previous queue */
+
+/* these define the two queues per control channel between controlpart and "its"
+ * guests, which includes the iopart  */
+#define CTRLCHAN_TO_CTRLGUESTPART 0 /* used by ctrlguestpart to 'insert' signals
+                                    * to ctrlpart */
+#define CTLRCHAN_FROM_CTRLPART 0 /* used by ctrlpart to 'remove' signals from
+                                 * ctrlquestpart - same queue as previous
+                                 * queue */
+
+#define CTRLCHAN_TO_CTRLPART 1 /* used by ctrlpart to 'insert' signals to
+                               * ctrlguestpart */
+#define CTRLCHAN_FROM_CTRLGUESTPART 1 /* used by ctrguestpart to 'remove'
+                                      * signals from ctrlpart - same queue as
+                                      * previous queue */
+
+/* these define the Event & Ack queues per control channel Events are generated
+* by CTRLGUESTPART and sent to CTRLPART; Acks are generated by CTRLPART and sent
+* to CTRLGUESTPART. */
+#define CTRLCHAN_EVENT_TO_CTRLPART 2 /* used by ctrlguestpart to 'insert' Events
+                                     * to ctrlpart */
+#define CTRLCHAN_EVENT_FROM_CTRLGUESTPART 2 /* used by ctrlpart to 'remove'
+                                            * Events from ctrlguestpart */
+
+#define CTRLCHAN_ACK_TO_CTRLGUESTPART 3        /* used by ctrlpart to 'insert' Acks to
+                                        * ctrlguestpart */
+#define CTRLCHAN_ACK_FROM_CTRLPART 3 /* used by ctrlguestpart to 'remove' Events
+                                     * from ctrlpart */
+
+/* size of cdb - i.e., scsi cmnd */
+#define MAX_CMND_SIZE 16
+enum dma_data_dir {
+       DMA_DIR_BIDIR = 0,
+       DMA_DIR_TO_DEV,
+       DMA_DIR_FROM_DEV,
+       DMA_DIR_NONE
+};
+
+#define MAX_SENSE_SIZE 64
+
+#define MAX_PHYS_INFO 64
+
+/* Because GuestToGuestCopy is limited to 4KiB segments, and we have limited the
+* Emulex Driver to 256 scatter list segments via the lpfc_sg_seg_cnt parameter
+* to 256, the maximum I/O size is limited to 256 * 4 KiB = 1 MB */
+#define MAX_IO_SIZE   (1024*1024)      /* 1 MB */
+
+/* NOTE 1: lpfc defines its support for segments in
+* #define LPFC_SG_SEG_CNT 64
+*
+* NOTE 2: In Linux, frags array in skb is currently allocated to be
+* MAX_SKB_FRAGS size, which is 18 which is smaller than MAX_PHYS_INFO for
+* now.  */
+
+#ifndef MAX_SERIAL_NUM
+#define MAX_SERIAL_NUM         32
+#endif                         /* MAX_SERIAL_NUM */
+
+#define MAX_SCSI_BUSES         1
+#define MAX_SCSI_TARGETS       8
+#define MAX_SCSI_LUNS          16
+#define MAX_SCSI_FROM_HOST     0xFFFFFFFF      /* Indicator to use Physical HBA
+                                                * SCSI Host value */
+
+/* various types of network packets that can be sent in cmdrsp */
+typedef enum { NET_RCV_POST = 0,       /* submit buffer to hold receiving
+                                        * incoming packet */
+       /* virtnic -> uisnic */
+       NET_RCV,                /* incoming packet received */
+       /* uisnic -> virtpci */
+       NET_XMIT,               /* for outgoing net packets      */
+       /* virtnic -> uisnic */
+       NET_XMIT_DONE,          /* outgoing packet xmitted */
+       /* uisnic -> virtpci */
+       NET_RCV_ENBDIS,         /* enable/disable packet reception */
+       /* virtnic -> uisnic */
+       NET_RCV_ENBDIS_ACK,     /* acknowledge enable/disable packet
+                                * reception */
+       /* uisnic -> virtnic */
+       NET_RCV_PROMISC,        /* enable/disable promiscuous mode */
+       /* virtnic -> uisnic */
+       NET_CONNECT_STATUS,     /* indicate the loss or restoration of a network
+                                * connection */
+       /* uisnic -> virtnic */
+       NET_MACADDR,            /* indicates the client has requested to update
+                                * its MAC addr */
+       NET_MACADDR_ACK,        /* Mac addres  */
+
+} NET_TYPES;
+
+#define                ETH_HEADER_SIZE 14      /* size of ethernet header */
+
+#define                ETH_MIN_DATA_SIZE 46    /* minimum eth data size */
+#define                ETH_MIN_PACKET_SIZE (ETH_HEADER_SIZE + ETH_MIN_DATA_SIZE)
+
+#define     ETH_DEF_DATA_SIZE 1500     /* default data size */
+#define     ETH_DEF_PACKET_SIZE (ETH_HEADER_SIZE + ETH_DEF_DATA_SIZE)
+
+#define                ETH_MAX_MTU 16384       /* maximum data size */
+
+#ifndef MAX_MACADDR_LEN
+#define MAX_MACADDR_LEN 6      /* number of bytes in MAC address */
+#endif                         /* MAX_MACADDR_LEN */
+
+#define ETH_IS_LOCALLY_ADMINISTERED(Address) \
+       (((U8 *) (Address))[0] & ((U8) 0x02))
+#define NIC_VENDOR_ID 0x0008000B
+
+/* various types of scsi task mgmt commands  */
+typedef enum { TASK_MGMT_ABORT_TASK =
+           1, TASK_MGMT_BUS_RESET, TASK_MGMT_LUN_RESET,
+           TASK_MGMT_TARGET_RESET,
+} TASK_MGMT_TYPES;
+
+/* various types of vdisk mgmt commands  */
+typedef enum { VDISK_MGMT_ACQUIRE = 1, VDISK_MGMT_RELEASE,
+} VDISK_MGMT_TYPES;
+
+/* this is used in the vdest field  */
+#define VDEST_ALL 0xFFFF
+
+#define MIN_NUMSIGNALS 64
+#define MAX_NUMSIGNALS 4096
+
+/* MAX_NET_RCV_BUF specifies the number of rcv buffers that are created by each
+* guest's virtnic and posted to uisnic.  Uisnic, for each channel, keeps the rcv
+* buffers posted and uses them to receive data on behalf of the guest's virtnic.
+* NOTE: the num_rcv_bufs is configurable for each VNIC. So the following is
+* simply an upperlimit on what each VNIC can provide.  Setting it to half of the
+* NUMSIGNALS to prevent queue full deadlocks */
+#define MAX_NET_RCV_BUFS (MIN_NUMSIGNALS / 2)
+
+/*
+ * structs with pragma pack  */
+
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+
+#pragma pack(push, 1)
+
+struct guest_phys_info {
+       U64 address;
+       U64 length;
+};
+
+#define GPI_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct guest_phys_info))
+
+struct uisscsi_dest {
+       U32 channel;            /* channel == bus number */
+       U32 id;                 /* id == target number */
+       U32 lun;                /* lun == logical unit number */
+};
+
+struct vhba_wwnn {
+       U32 wwnn1;
+       U32 wwnn2;
+};
+
+/* WARNING: Values stired in this structure must contain maximum counts (not
+ * maximum values). */
+struct vhba_config_max {       /* 20 bytes */
+       U32 max_channel;        /* maximum channel for devices attached to this
+                                * bus */
+       U32 max_id;             /* maximum SCSI ID for devices attached to this
+                                * bus */
+       U32 max_lun;            /* maximum SCSI LUN for devices attached to this
+                                * bus */
+       U32 cmd_per_lun;        /* maximum number of outstanding commands per
+                                * lun that are allowed at one time */
+       U32 max_io_size;        /* maximum io size for devices attached to this
+                                * bus */
+       /* max io size is often determined by the resource of the hba. e.g */
+       /* max scatter gather list length * page size / sector size */
+};
+
+struct uiscmdrsp_scsi {
+       void *scsicmd;          /* the handle to the cmd that was received -
+                                * send it back as is in the rsp packet.  */
+       U8 cmnd[MAX_CMND_SIZE]; /* the cdb for the command */
+       U32 bufflen;            /* length of data to be transferred out or in */
+       U16 guest_phys_entries; /* Number of entries in scatter-gather (sg)
+                                * list */
+       struct guest_phys_info gpi_list[MAX_PHYS_INFO]; /* physical address
+                                                        * information for each
+                                                        * fragment */
+       enum dma_data_dir data_dir;     /* direction of the data, if any */
+       struct uisscsi_dest vdest;      /* identifies the virtual hba, id,
+                                        * channel, lun to which cmd was sent */
+
+           /* the following fields are needed to queue the rsp back to cmd
+            * originator */
+       int linuxstat;          /* the original Linux status - for use by linux
+                                * vdisk code */
+       U8 scsistat;            /* the scsi status */
+       U8 addlstat;            /* non-scsi status - covers cases like timeout
+                                * needed by windows guests */
+#define ADDL_RESET             1
+#define ADDL_TIMEOUT           2
+#define ADDL_INTERNAL_ERROR    3
+#define ADDL_SEL_TIMEOUT       4
+#define ADDL_CMD_TIMEOUT       5
+#define ADDL_BAD_TARGET                6
+#define ADDL_RETRY             7
+
+       /* the following fields are need to determine the result of command */
+        U8 sensebuf[MAX_SENSE_SIZE];   /* sense info in case cmd failed; */
+       /* it holds the sense_data struct; */
+       /* see that struct for details. */
+       void *vdisk; /* contains pointer to the vdisk so that we can clean up
+                     * when the IO completes. */
+       int no_disk_result;     /* used to return no disk inquiry result */
+       /* when no_disk_result is set to 1,  */
+       /* scsi.scsistat is SAM_STAT_GOOD */
+       /* scsi.addlstat is 0 */
+       /* scsi.linuxstat is SAM_STAT_GOOD */
+       /* That is, there is NO error. */
+};
+
+/*
+* Defines to support sending correct inquiry result when no disk is
+* configured.  */
+
+/* From SCSI SPC2 -
+ *
+ * If the target is not capable of supporting a device on this logical unit, the
+ * device server shall set this field to 7Fh (PERIPHERAL QUALIFIER set to 011b
+ * and PERIPHERAL DEVICE TYPE set to 1Fh).
+ *
+ *The device server is capable of supporting the specified peripheral device
+ *type on this logical unit. However, the physical device is not currently
+ *connected to this logical unit.
+ */
+
+#define DEV_NOT_PRESENT 0x7f   /* old name - compatibility */
+#define DEV_NOT_CAPABLE 0x7f   /* peripheral qualifier of 0x3  */
+    /* peripheral type of 0x1f */
+    /* specifies no device but target present */
+
+#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 /* peripheral qualifier of 0x1 */
+    /* peripheral type of 0 - disk */
+    /* specifies device capable, but not present */
+
+#define DEV_PROC_CAPABLE_NOT_PRESENT 0x23 /* peripheral qualifier of 0x1 */
+    /* peripheral type of 3 - processor */
+    /* specifies device capable, but not present */
+
+#define DEV_HISUPPORT 0x10;    /* HiSup = 1; shows support for report luns */
+    /* must be returned for lun 0. */
+
+/* NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length
+* in buf[4] some linux code accesses bytes beyond 5 to retrieve vendor, product
+* & revision.  Yikes! So let us always send back 36 bytes, the minimum for
+* inquiry result. */
+#define NO_DISK_INQUIRY_RESULT_LEN 36
+
+#define MIN_INQUIRY_RESULT_LEN 5 /* we need at least 5 bytes minimum for inquiry
+                                 * result */
+
+/* SCSI device version for no disk inquiry result */
+#define SCSI_SPC2_VER 4                /* indicates SCSI SPC2 (SPC3 is 5) */
+
+/* Windows and Linux want different things for a non-existent lun. So, we'll let
+ * caller pass in the peripheral qualifier and type.
+ * NOTE:[4] SCSI returns (n-4); so we return length-1-4 or length-5. */
+
+#define SET_NO_DISK_INQUIRY_RESULT(buf, len, lun, lun0notpresent, notpresent) \
+       do {                                                            \
+               MEMSET(buf, 0,                                          \
+                      MINNUM(len,                                      \
+                             (unsigned int) NO_DISK_INQUIRY_RESULT_LEN)); \
+               buf[2] = (U8) SCSI_SPC2_VER;                            \
+               if (lun == 0) {                                         \
+                       buf[0] = (U8) lun0notpresent;                   \
+                       buf[3] = (U8) DEV_HISUPPORT;                    \
+               } else                                                  \
+                       buf[0] = (U8) notpresent;                       \
+               buf[4] = (U8) (                                         \
+                       MINNUM(len,                                     \
+                              (unsigned int) NO_DISK_INQUIRY_RESULT_LEN) - 5); \
+               if (len >= NO_DISK_INQUIRY_RESULT_LEN) {                \
+                       buf[8] = 'D';                                   \
+                       buf[9] = 'E';                                   \
+                       buf[10] = 'L';                                  \
+                       buf[11] = 'L';                                  \
+                       buf[16] = 'P';                                  \
+                       buf[17] = 'S';                                  \
+                       buf[18] = 'E';                                  \
+                       buf[19] = 'U';                                  \
+                       buf[20] = 'D';                                  \
+                       buf[21] = 'O';                                  \
+                       buf[22] = ' ';                                  \
+                       buf[23] = 'D';                                  \
+                       buf[24] = 'E';                                  \
+                       buf[25] = 'V';                                  \
+                       buf[26] = 'I';                                  \
+                       buf[27] = 'C';                                  \
+                       buf[28] = 'E';                                  \
+                       buf[30] = ' ';                                  \
+                       buf[31] = '.';                                  \
+               }                                                       \
+       } while (0)
+
+
+/*
+* Struct & Defines to support sense information.
+*/
+
+
+/* The following struct is returned in sensebuf field in uiscmdrsp_scsi.  It is
+* initialized in exactly the manner that is recommended in Windows (hence the
+* odd values).
+* When set, these fields will have the following values:
+* ErrorCode = 0x70             indicates current error
+* Valid = 1                    indicates sense info is valid
+* SenseKey                     contains sense key as defined by SCSI specs.
+* AdditionalSenseCode          contains sense key as defined by SCSI specs.
+* AdditionalSenseCodeQualifier contains qualifier to sense code as defined by
+*                              scsi docs.
+* AdditionalSenseLength                contains will be sizeof(sense_data)-8=10.
+*/
+struct sense_data {
+       U8 ErrorCode:7;
+       U8 Valid:1;
+       U8 SegmentNumber;
+       U8 SenseKey:4;
+       U8 Reserved:1;
+       U8 IncorrectLength:1;
+       U8 EndOfMedia:1;
+       U8 FileMark:1;
+       U8 Information[4];
+       U8 AdditionalSenseLength;
+       U8 CommandSpecificInformation[4];
+       U8 AdditionalSenseCode;
+       U8 AdditionalSenseCodeQualifier;
+       U8 FieldReplaceableUnitCode;
+       U8 SenseKeySpecific[3];
+};
+
+/* some SCSI ADSENSE codes */
+#ifndef SCSI_ADSENSE_LUN_NOT_READY
+#define SCSI_ADSENSE_LUN_NOT_READY 0x04
+#endif /*  */
+#ifndef SCSI_ADSENSE_ILLEGAL_COMMAND
+#define SCSI_ADSENSE_ILLEGAL_COMMAND 0x20
+#endif /*  */
+#ifndef SCSI_ADSENSE_ILLEGAL_BLOCK
+#endif /*  */
+#ifndef SCSI_ADSENSE_ILLEGAL_BLOCK
+#define SCSI_ADSENSE_ILLEGAL_BLOCK  0x21
+#endif /*  */
+#ifndef SCSI_ADSENSE_INVALID_CDB
+#define SCSI_ADSENSE_INVALID_CDB    0x24
+#endif /*  */
+#ifndef SCSI_ADSENSE_INVALID_LUN
+#define SCSI_ADSENSE_INVALID_LUN    0x25
+#endif /*  */
+#ifndef SCSI_ADWRITE_PROTECT
+#define SCSI_ADWRITE_PROTECT        0x27
+#endif /*  */
+#ifndef SCSI_ADSENSE_MEDIUM_CHANGED
+#define SCSI_ADSENSE_MEDIUM_CHANGED 0x28
+#endif /*  */
+#ifndef SCSI_ADSENSE_BUS_RESET
+#define SCSI_ADSENSE_BUS_RESET      0x29
+#endif /*  */
+#ifndef SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
+#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE 0x3a
+#endif /*  */
+
+struct net_pkt_xmt {
+       int len;        /* full length of data in the packet */
+       int num_frags;  /* number of fragments in frags containing data */
+       struct phys_info frags[MAX_PHYS_INFO];  /* physical page information for
+                                                * each fragment */
+       char ethhdr[ETH_HEADER_SIZE];   /* the ethernet header  */
+       struct {
+
+                   /* these are needed for csum at uisnic end */
+               U8 valid;       /* 1 = rest of this struct is valid - else
+                                * ignore */
+               U8 hrawoffv;    /* 1 = hwrafoff is valid */
+               U8 nhrawoffv;   /* 1 = nhwrafoff is valid */
+               U16 protocol;   /* specifies packet protocol */
+               U32 csum;       /* value used to set skb->csum at IOPart */
+               U32 hrawoff;    /* value used to set skb->h.raw at IOPart */
+               /* hrawoff points to the start of the TRANSPORT LAYER HEADER */
+               U32 nhrawoff;   /* value used to set skb->nh.raw at IOPart */
+               /* nhrawoff points to the start of the NETWORK LAYER HEADER */
+       } lincsum;
+
+           /* **** NOTE ****
+            * The full packet is described in frags but the ethernet header is
+            * separately kept in ethhdr so that uisnic doesn't have "MAP" the
+            * guest memory to get to the header. uisnic needs ethhdr to
+            * determine how to route the packet.
+            */
+};
+
+struct net_pkt_xmtdone {
+       U32 xmt_done_result;    /* result of NET_XMIT */
+#define XMIT_SUCCESS 0
+#define XMIT_FAILED 1
+};
+
+/* RCVPOST_BUF_SIZe must be at most page_size(4096) - cache_line_size (64) The
+* reason is because dev_skb_alloc which is used to generate RCV_POST skbs in
+* virtnic requires that there is "overhead" in the buffer, and pads 16 bytes.  I
+* prefer to use 1 full cache line size for "overhead" so that transfers are
+* better.  IOVM requires that a buffer be represented by 1 phys_info structure
+* which can only cover page_size. */
+#define RCVPOST_BUF_SIZE 4032
+#define MAX_NET_RCV_CHAIN \
+       ((ETH_MAX_MTU+ETH_HEADER_SIZE + RCVPOST_BUF_SIZE-1) / RCVPOST_BUF_SIZE)
+
+struct net_pkt_rcvpost {
+           /* rcv buf size must be large enough to include ethernet data len +
+           * ethernet header len - we are choosing 2K because it is guaranteed
+           * to be describable */
+           struct phys_info frag;      /* physical page information for the
+                                        * single fragment 2K rcv buf */
+           U64 UniqueNum;              /* This is used to make sure that
+                                        * receive posts are returned to  */
+           /* the Adapter which sent them origonally. */
+};
+
+struct net_pkt_rcv {
+
+       /* the number of receive buffers that can be chained  */
+       /* is based on max mtu and size of each rcv buf */
+       U32 rcv_done_len;       /* length of received data */
+       U8 numrcvbufs;          /* number of receive buffers that contain the */
+       /* incoming data; guest end MUST chain these together. */
+       void *rcvbuf[MAX_NET_RCV_CHAIN];        /* the list of receive buffers
+                                                * that must be chained; */
+       /* each entry is a receive buffer provided by NET_RCV_POST. */
+       /* NOTE: first rcvbuf in the chain will also be provided in net.buf. */
+       U64 UniqueNum;
+       U32 RcvsDroppedDelta;
+};
+
+struct net_pkt_enbdis {
+       void *context;
+       U16 enable;             /* 1 = enable, 0 = disable */
+};
+
+struct net_pkt_macaddr {
+       void *context;
+       U8 macaddr[MAX_MACADDR_LEN];    /* 6 bytes */
+};
+
+/* cmd rsp packet used for VNIC network traffic  */
+struct uiscmdrsp_net {
+       NET_TYPES type;
+       void *buf;
+       union {
+               struct net_pkt_xmt xmt; /* used for NET_XMIT */
+               struct net_pkt_xmtdone xmtdone; /* used for NET_XMIT_DONE */
+               struct net_pkt_rcvpost rcvpost; /* used for NET_RCV_POST */
+               struct net_pkt_rcv rcv; /* used for NET_RCV */
+               struct net_pkt_enbdis enbdis;   /* used for NET_RCV_ENBDIS, */
+               /* NET_RCV_ENBDIS_ACK,  */
+               /* NET_RCV_PROMSIC, */
+               /* and NET_CONNECT_STATUS */
+               struct net_pkt_macaddr macaddr;
+       };
+};
+
+struct uiscmdrsp_scsitaskmgmt {
+       TASK_MGMT_TYPES tasktype;
+
+           /* the type of task */
+       struct uisscsi_dest vdest;
+
+           /* the vdisk for which this task mgmt is generated */
+       void *scsicmd;
+
+           /* This is some handle that the guest has saved off for its own use.
+           * Its value is preserved by iopart & returned as is in the task mgmt
+           * rsp. */
+       void *notify;
+
+           /* For linux guests, this is a pointer to wait_queue_head that a
+           * thread is waiting on to see if the taskmgmt command has completed.
+           * For windows guests, this is a pointer to a location that a waiting
+           * thread is testing to see if the taskmgmt command has completed.
+           * When the rsp is received by guest, the thread receiving the
+           * response uses this to notify the the thread waiting for taskmgmt
+           * command completion.  Its value is preserved by iopart & returned
+           * as is in the task mgmt rsp. */
+       void *notifyresult;
+
+           /* this is a handle to location in guest where the result of the
+           * taskmgmt command (result field) is to saved off when the response
+           * is handled.  Its value is preserved by iopart & returned as is in
+           * the task mgmt rsp. */
+       char result;
+
+           /* result of taskmgmt command - set by IOPart - values are: */
+#define TASK_MGMT_FAILED  0
+#define TASK_MGMT_SUCCESS 1
+};
+
+/* The following is used by uissd to send disk add/remove notifications to
+ * Guest */
+/* Note that the vHba pointer is not used by the Client/Guest side. */
+struct uiscmdrsp_disknotify {
+       U8 add;         /* 0-remove, 1-add */
+       void *vHba;             /* Pointer to vhba_info for channel info to
+                                * route msg */
+       U32 channel, id, lun;   /* SCSI Path of Disk to added or removed */
+};
+
+/* The following is used by virthba/vSCSI to send the Acquire/Release commands
+* to the IOVM.  */
+struct uiscmdrsp_vdiskmgmt {
+       VDISK_MGMT_TYPES vdisktype;
+
+           /* the type of task */
+       struct uisscsi_dest vdest;
+
+           /* the vdisk for which this task mgmt is generated */
+       void *scsicmd;
+
+           /* This is some handle that the guest has saved off for its own use.
+           * Its value is preserved by iopart & returned as is in the task mgmt
+           * rsp. */
+       void *notify;
+
+           /* For linux guests, this is a pointer to wait_queue_head that a
+           * thread is waiting on to see if the taskmgmt command has completed.
+           * For windows guests, this is a pointer to a location that a waiting
+           * thread is testing to see if the taskmgmt command has completed.
+           * When the rsp is received by guest, the thread receiving the
+           * response uses this to notify the the thread waiting for taskmgmt
+           * command completion.  Its value is preserved by iopart & returned
+           * as is in the task mgmt rsp. */
+       void *notifyresult;
+
+           /* this is a handle to location in guest where the result of the
+           * taskmgmt command (result field) is to saved off when the response
+           * is handled.  Its value is preserved by iopart & returned as is in
+           * the task mgmt rsp. */
+       char result;
+
+           /* result of taskmgmt command - set by IOPart - values are: */
+#define VDISK_MGMT_FAILED  0
+#define VDISK_MGMT_SUCCESS 1
+};
+
+/* keeping cmd & rsp info in one structure for now cmd rsp packet for scsi */
+struct uiscmdrsp {
+       char cmdtype;
+
+           /* describes what type of information is in the struct */
+#define CMD_SCSI_TYPE          1
+#define CMD_NET_TYPE           2
+#define CMD_SCSITASKMGMT_TYPE  3
+#define CMD_NOTIFYGUEST_TYPE   4
+#define CMD_VDISKMGMT_TYPE     5
+       union {
+               struct uiscmdrsp_scsi scsi;
+               struct uiscmdrsp_net net;
+               struct uiscmdrsp_scsitaskmgmt scsitaskmgmt;
+               struct uiscmdrsp_disknotify disknotify;
+               struct uiscmdrsp_vdiskmgmt vdiskmgmt;
+       };
+       void *private_data;     /* used to send the response when the cmd is
+                                * done (scsi & scsittaskmgmt).  */
+       struct uiscmdrsp *next; /* General Purpose Queue Link */
+       struct uiscmdrsp *activeQ_next; /* Used to track active commands */
+       struct uiscmdrsp *activeQ_prev; /* Used to track active commands  */
+};
+
+/* This is just the header of the IO channel.  It is assumed that directly after
+* this header there is a large region of memory which contains the command and
+* response queues as specified in cmdQ and rspQ SIGNAL_QUEUE_HEADERS. */
+typedef struct _ULTRA_IO_CHANNEL_PROTOCOL {
+       CHANNEL_HEADER ChannelHeader;
+       SIGNAL_QUEUE_HEADER cmdQ;
+       SIGNAL_QUEUE_HEADER rspQ;
+       union {
+               struct {
+                       struct vhba_wwnn wwnn;  /* 8 bytes */
+                       struct vhba_config_max max;     /* 20 bytes */
+               } vhba;         /* 28 */
+               struct {
+                       U8 macaddr[MAX_MACADDR_LEN];    /* 6 bytes */
+                       U32 num_rcv_bufs;       /* 4 */
+                       U32 mtu;        /* 4 */
+                       GUID zoneGuid;  /* 16 */
+               } vnic;         /* total     30 */
+       };
+
+#define MAX_CLIENTSTRING_LEN 1024
+        U8 clientString[MAX_CLIENTSTRING_LEN]; /* NULL terminated - so holds
+                                                * max - 1 bytes */
+} ULTRA_IO_CHANNEL_PROTOCOL;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* define offsets to members of struct uiscmdrsp */
+#define OFFSET_CMDTYPE OFFSETOF(struct uiscmdrsp, cmdtype)
+#define OFFSET_SCSI OFFSETOF(struct uiscmdrsp, scsi)
+#define OFFSET_NET OFFSETOF(struct uiscmdrsp, net)
+#define OFFSET_SCSITASKMGMT OFFSETOF(struct uiscmdrsp, scsitaskmgmt)
+#define OFFSET_NEXT OFFSETOF(struct uiscmdrsp, next)
+
+/* define offsets to members of struct uiscmdrsp_net */
+#define OFFSET_TYPE OFFSETOF(struct uiscmdrsp_net, type)
+#define OFFSET_BUF OFFSETOF(struct uiscmdrsp_net, buf)
+#define OFFSET_XMT OFFSETOF(struct uiscmdrsp_net, xmt)
+#define OFFSET_XMT_DONE_RESULT OFFSETOF(struct uiscmdrsp_net, xmtdone)
+#define OFFSET_RCVPOST OFFSETOF(struct uiscmdrsp_net, rcvpost)
+#define OFFSET_RCV_DONE_LEN OFFSETOF(struct uiscmdrsp_net, rcv)
+#define OFFSET_ENBDIS OFFSETOF(struct uiscmdrsp_net, enbdis)
+
+/* define offsets to members of struct net_pkt_rcvpost */
+#define OFFSET_TOTALLEN OFFSETOF(struct net_pkt_rcvpost, totallen)
+#define        OFFSET_FRAG OFFSETOF(struct net_pkt_rcvpost, frag)
+
+/*
+* INLINE functions for initializing and accessing I/O data channels
+*/
+
+
+#define NUMSIGNALS(x, q) (((ULTRA_IO_CHANNEL_PROTOCOL *)(x))->q.MaxSignalSlots)
+#define SIZEOF_PROTOCOL (COVER(sizeof(ULTRA_IO_CHANNEL_PROTOCOL), 64))
+#define SIZEOF_CMDRSP (COVER(sizeof(struct uiscmdrsp), 64))
+
+#define IO_CHANNEL_SIZE(x) COVER(SIZEOF_PROTOCOL + \
+                                (NUMSIGNALS(x, cmdQ) + \
+                                 NUMSIGNALS(x, rspQ)) * SIZEOF_CMDRSP, 4096)
+#define MIN_IO_CHANNEL_SIZE COVER(SIZEOF_PROTOCOL + \
+                                 2 * MIN_NUMSIGNALS * SIZEOF_CMDRSP, 4096)
+#ifdef __GNUC__
+/* These defines should only ever be used in service partitons */
+/* because they rely on the size of uiscmdrsp */
+#define QSLOTSFROMBYTES(bytes) (((bytes-SIZEOF_PROTOCOL)/2)/SIZEOF_CMDRSP)
+#define QSIZEFROMBYTES(bytes) (QSLOTSFROMBYTES(bytes)*SIZEOF_CMDRSP)
+#define SignalQInit(x)                                         \
+       do {                                                    \
+               x->cmdQ.Size = QSIZEFROMBYTES(x->ChannelHeader.Size);   \
+               x->cmdQ.oSignalBase = SIZEOF_PROTOCOL -                 \
+                       OFFSETOF(ULTRA_IO_CHANNEL_PROTOCOL, cmdQ);      \
+               x->cmdQ.SignalSize = SIZEOF_CMDRSP;                     \
+               x->cmdQ.MaxSignalSlots =                                \
+                       QSLOTSFROMBYTES(x->ChannelHeader.Size);         \
+               x->cmdQ.MaxSignals = x->cmdQ.MaxSignalSlots - 1;        \
+               x->rspQ.Size = QSIZEFROMBYTES(x->ChannelHeader.Size);   \
+               x->rspQ.oSignalBase =                                   \
+                       (SIZEOF_PROTOCOL + x->cmdQ.Size) -              \
+                       OFFSETOF(ULTRA_IO_CHANNEL_PROTOCOL, rspQ);      \
+               x->rspQ.SignalSize = SIZEOF_CMDRSP;                     \
+               x->rspQ.MaxSignalSlots =                                \
+                       QSLOTSFROMBYTES(x->ChannelHeader.Size);         \
+               x->rspQ.MaxSignals = x->rspQ.MaxSignalSlots - 1;        \
+               x->ChannelHeader.oChannelSpace =                        \
+                       OFFSETOF(ULTRA_IO_CHANNEL_PROTOCOL, cmdQ);      \
+       } while (0)
+
+#define INIT_CLIENTSTRING(chan, type, clientStr, clientStrLen) \
+       do {                                                            \
+               if (clientStr) {                                        \
+                       chan->ChannelHeader.oClientString =             \
+                               OFFSETOF(type, clientString);           \
+                       MEMCPY(chan->clientString, clientStr,           \
+                              MINNUM(clientStrLen,                     \
+                                     (U32) (MAX_CLIENTSTRING_LEN - 1))); \
+                       chan->clientString[MINNUM(clientStrLen,         \
+                                                 (U32) (MAX_CLIENTSTRING_LEN \
+                                                        - 1))]         \
+                               = '\0';                                 \
+               }                                                       \
+               else                                                    \
+                       if (clientStrLen > 0)                           \
+                               return 0;                               \
+       } while (0)
+
+
+#define ULTRA_IO_CHANNEL_SERVER_READY(x, chanId, logCtx) \
+       ULTRA_CHANNEL_SERVER_TRANSITION(x, chanId, SrvState, CHANNELSRV_READY, \
+                                       logCtx);
+
+#define ULTRA_IO_CHANNEL_SERVER_NOTREADY(x, chanId, logCtx)    \
+       ULTRA_CHANNEL_SERVER_TRANSITION(x, chanId, SrvState, \
+                                       CHANNELSRV_UNINITIALIZED, logCtx);
+
+static inline int ULTRA_VHBA_init_channel(ULTRA_IO_CHANNEL_PROTOCOL *x,
+                                             struct vhba_wwnn *wwnn,
+                                             struct vhba_config_max *max,
+                                             unsigned char *clientStr,
+                                             U32 clientStrLen, U64 bytes)  {
+       MEMSET(x, 0, sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
+       x->ChannelHeader.VersionId = ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID;
+       x->ChannelHeader.Signature = ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE;
+       x->ChannelHeader.SrvState = CHANNELSRV_UNINITIALIZED;
+       x->ChannelHeader.HeaderSize = sizeof(x->ChannelHeader);
+       x->ChannelHeader.Size = COVER(bytes, 4096);
+       x->ChannelHeader.Type = UltraVhbaChannelProtocolGuid;
+       x->ChannelHeader.ZoneGuid = Guid0;
+       x->vhba.wwnn = *wwnn;
+       x->vhba.max = *max;
+       INIT_CLIENTSTRING(x, ULTRA_IO_CHANNEL_PROTOCOL, clientStr,
+                         clientStrLen);
+       SignalQInit(x);
+       if ((x->cmdQ.MaxSignalSlots > MAX_NUMSIGNALS) ||
+            (x->rspQ.MaxSignalSlots > MAX_NUMSIGNALS)) {
+               return 0;
+       }
+       if ((x->cmdQ.MaxSignalSlots < MIN_NUMSIGNALS) ||
+            (x->rspQ.MaxSignalSlots < MIN_NUMSIGNALS)) {
+               return 0;
+       }
+       return 1;
+}
+
+static inline void ULTRA_VHBA_set_max(ULTRA_IO_CHANNEL_PROTOCOL *x,
+                                     struct vhba_config_max *max)  {
+       x->vhba.max = *max;
+}
+
+static inline int ULTRA_VNIC_init_channel(ULTRA_IO_CHANNEL_PROTOCOL *x,
+                                                unsigned char *macaddr,
+                                                U32 num_rcv_bufs, U32 mtu,
+                                                GUID zoneGuid,
+                                                unsigned char *clientStr,
+                                                U32 clientStrLen,
+                                                U64 bytes)  {
+       MEMSET(x, 0, sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
+       x->ChannelHeader.VersionId = ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID;
+       x->ChannelHeader.Signature = ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE;
+       x->ChannelHeader.SrvState = CHANNELSRV_UNINITIALIZED;
+       x->ChannelHeader.HeaderSize = sizeof(x->ChannelHeader);
+       x->ChannelHeader.Size = COVER(bytes, 4096);
+       x->ChannelHeader.Type = UltraVnicChannelProtocolGuid;
+       x->ChannelHeader.ZoneGuid = Guid0;
+       MEMCPY(x->vnic.macaddr, macaddr, MAX_MACADDR_LEN);
+       x->vnic.num_rcv_bufs = num_rcv_bufs;
+       x->vnic.mtu = mtu;
+       x->vnic.zoneGuid = zoneGuid;
+       INIT_CLIENTSTRING(x, ULTRA_IO_CHANNEL_PROTOCOL, clientStr,
+                          clientStrLen);
+       SignalQInit(x);
+       if ((x->cmdQ.MaxSignalSlots > MAX_NUMSIGNALS) ||
+            (x->rspQ.MaxSignalSlots > MAX_NUMSIGNALS)) {
+               return 0;
+       }
+       if ((x->cmdQ.MaxSignalSlots < MIN_NUMSIGNALS) ||
+            (x->rspQ.MaxSignalSlots < MIN_NUMSIGNALS)) {
+               return 0;
+       }
+       return 1;
+}
+
+#endif /* __GNUC__ */
+
+/*
+* INLINE function for expanding a guest's pfn-off-size into multiple 4K page
+* pfn-off-size entires.
+*/
+
+
+/* we deal with 4K page sizes when we it comes to passing page information
+ * between */
+/* Guest and IOPartition. */
+#define PI_PAGE_SIZE  0x1000
+#define PI_PAGE_MASK  0x0FFF
+#define PI_PAGE_SHIFT 12
+
+/* returns next non-zero index on success or zero on failure (i.e. out of
+ * room)
+ */
+static INLINE  U16
+add_physinfo_entries(U32 inp_pfn,      /* input - specifies the pfn to be used
+                                        * to add entries */
+                    U16 inp_off,       /* input - specifies the off to be used
+                                        * to add entries */
+                    U32 inp_len,       /* input - specifies the len to be used
+                                        * to add entries */
+                    U16 index,         /* input - index in array at which new
+                                        * entries are added */
+                    U16 max_pi_arr_entries,    /* input - specifies the maximum
+                                                * entries pi_arr can hold */
+                    struct phys_info pi_arr[]) /* input & output - array to
+                                                 * which entries are added */
+{
+       U32 len;
+       U16 i, firstlen;
+
+       firstlen = PI_PAGE_SIZE - inp_off;
+       if (inp_len <= firstlen) {
+
+               /* the input entry spans only one page - add as is */
+               if (index >= max_pi_arr_entries)
+                       return 0;
+               pi_arr[index].pi_pfn = inp_pfn;
+               pi_arr[index].pi_off = (U16) inp_off;
+               pi_arr[index].pi_len = (U16) inp_len;
+                   return index + 1;
+       }
+
+           /* this entry spans multiple pages */
+           for (len = inp_len, i = 0; len;
+                len -= pi_arr[index + i].pi_len, i++) {
+               if (index + i >= max_pi_arr_entries)
+                       return 0;
+               pi_arr[index + i].pi_pfn = inp_pfn + i;
+               if (i == 0) {
+                       pi_arr[index].pi_off = inp_off;
+                       pi_arr[index].pi_len = firstlen;
+               }
+
+               else {
+                       pi_arr[index + i].pi_off = 0;
+                       pi_arr[index + i].pi_len =
+                           (U16) MINNUM(len, (U32) PI_PAGE_SIZE);
+               }
+
+       }
+       return index + i;
+}
+
+#endif                         /* __IOCHANNEL_H__ */
diff --git a/drivers/staging/unisys/common-spar/include/channels/vbuschannel.h b/drivers/staging/unisys/common-spar/include/channels/vbuschannel.h
new file mode 100644 (file)
index 0000000..ec5a8c0
--- /dev/null
@@ -0,0 +1,127 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VBUSCHANNEL_H__
+#define __VBUSCHANNEL_H__
+
+/*  The vbus channel is the channel area provided via the BUS_CREATE controlvm
+ *  message for each virtual bus.  This channel area is provided to both server
+ *  and client ends of the bus.  The channel header area is initialized by
+ *  the server, and the remaining information is filled in by the client.
+ *  We currently use this for the client to provide various information about
+ *  the client devices and client drivers for the server end to see.
+ */
+#include "commontypes.h"
+#include "vbusdeviceinfo.h"
+#include "channel.h"
+
+/* {193b331b-c58f-11da-95a9-00e08161165f} */
+#define ULTRA_VBUS_CHANNEL_PROTOCOL_GUID \
+       {0x193b331b, 0xc58f, 0x11da, \
+               {0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f} }
+static const GUID UltraVbusChannelProtocolGuid =
+       ULTRA_VBUS_CHANNEL_PROTOCOL_GUID;
+
+#define ULTRA_VBUS_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+
+/* Must increment this whenever you insert or delete fields within this channel
+* struct.  Also increment whenever you change the meaning of fields within this
+* channel struct so as to break pre-existing software.  Note that you can
+* usually add fields to the END of the channel struct withOUT needing to
+* increment this. */
+#define ULTRA_VBUS_CHANNEL_PROTOCOL_VERSIONID 1
+
+#define ULTRA_VBUS_CHANNEL_OK_CLIENT(pChannel, logCtx)       \
+       (ULTRA_check_channel_client(pChannel,                           \
+                                   UltraVbusChannelProtocolGuid,       \
+                                   "vbus",                             \
+                                   sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL), \
+                                   ULTRA_VBUS_CHANNEL_PROTOCOL_VERSIONID, \
+                                   ULTRA_VBUS_CHANNEL_PROTOCOL_SIGNATURE, \
+                                   __FILE__, __LINE__, logCtx))
+
+#define ULTRA_VBUS_CHANNEL_OK_SERVER(actualBytes, logCtx)    \
+       (ULTRA_check_channel_server(UltraVbusChannelProtocolGuid,       \
+                                   "vbus",                             \
+                                   sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL), \
+                                   actualBytes,                        \
+                                   __FILE__, __LINE__, logCtx))
+
+
+#pragma pack(push, 1)          /* both GCC and VC now allow this pragma */
+typedef struct _ULTRA_VBUS_HEADERINFO {
+       U32 structBytes;        /* size of this struct in bytes */
+       U32 deviceInfoStructBytes;      /* sizeof(ULTRA_VBUS_DEVICEINFO) */
+       U32 devInfoCount;       /* num of items in DevInfo member */
+       /* (this is the allocated size) */
+       U32 chpInfoByteOffset;  /* byte offset from beginning of this struct */
+       /* to the the ChpInfo struct (below) */
+       U32 busInfoByteOffset;  /* byte offset from beginning of this struct */
+       /* to the the BusInfo struct (below) */
+       U32 devInfoByteOffset;  /* byte offset from beginning of this struct */
+       /* to the the DevInfo array (below) */
+       U8 reserved[104];
+} ULTRA_VBUS_HEADERINFO;
+
+typedef struct _ULTRA_VBUS_CHANNEL_PROTOCOL {
+       ULTRA_CHANNEL_PROTOCOL ChannelHeader;   /* initialized by server */
+       ULTRA_VBUS_HEADERINFO HdrInfo;  /* initialized by server */
+       /* the remainder of this channel is filled in by the client */
+       ULTRA_VBUS_DEVICEINFO ChpInfo;  /* describes client chipset device and
+                                        * driver */
+       ULTRA_VBUS_DEVICEINFO BusInfo;  /* describes client bus device and
+                                        * driver */
+       ULTRA_VBUS_DEVICEINFO DevInfo[0];       /* describes client device and
+                                                * driver for */
+       /* each device on the bus */
+} ULTRA_VBUS_CHANNEL_PROTOCOL;
+
+#define VBUS_CH_SIZE_EXACT(MAXDEVICES) \
+       (sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL) + ((MAXDEVICES) * \
+                                               sizeof(ULTRA_VBUS_DEVICEINFO)))
+#define VBUS_CH_SIZE(MAXDEVICES) COVER(VBUS_CH_SIZE_EXACT(MAXDEVICES), 4096)
+
+static INLINE void
+ULTRA_VBUS_init_channel(ULTRA_VBUS_CHANNEL_PROTOCOL *x, int bytesAllocated)
+{
+       /* Please note that the memory at <x> does NOT necessarily have space
+       * for DevInfo structs allocated at the end, which is why we do NOT use
+       * <bytesAllocated> to clear. */
+       MEMSET(x, 0, sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL));
+       if (bytesAllocated < (int) sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL))
+               return;
+       x->ChannelHeader.VersionId = ULTRA_VBUS_CHANNEL_PROTOCOL_VERSIONID;
+       x->ChannelHeader.Signature = ULTRA_VBUS_CHANNEL_PROTOCOL_SIGNATURE;
+       x->ChannelHeader.SrvState = CHANNELSRV_READY;
+       x->ChannelHeader.HeaderSize = sizeof(x->ChannelHeader);
+       x->ChannelHeader.Size = bytesAllocated;
+       x->ChannelHeader.Type = UltraVbusChannelProtocolGuid;
+       x->ChannelHeader.ZoneGuid = Guid0;
+       x->HdrInfo.structBytes = sizeof(ULTRA_VBUS_HEADERINFO);
+       x->HdrInfo.chpInfoByteOffset = sizeof(ULTRA_VBUS_HEADERINFO);
+       x->HdrInfo.busInfoByteOffset = x->HdrInfo.chpInfoByteOffset
+           + sizeof(ULTRA_VBUS_DEVICEINFO);
+       x->HdrInfo.devInfoByteOffset = x->HdrInfo.busInfoByteOffset
+           + sizeof(ULTRA_VBUS_DEVICEINFO);
+       x->HdrInfo.deviceInfoStructBytes = sizeof(ULTRA_VBUS_DEVICEINFO);
+       bytesAllocated -= (sizeof(ULTRA_CHANNEL_PROTOCOL)
+                          + x->HdrInfo.devInfoByteOffset);
+       x->HdrInfo.devInfoCount =
+           bytesAllocated / x->HdrInfo.deviceInfoStructBytes;
+}
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/controlvmcompletionstatus.h b/drivers/staging/unisys/common-spar/include/controlvmcompletionstatus.h
new file mode 100644 (file)
index 0000000..de30d32
--- /dev/null
@@ -0,0 +1,92 @@
+/* controlvmcompletionstatus.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*  Defines for all valid values returned in the response message header
+ *  completionStatus field.  See controlvmchannel.h for description of
+ *  the header: _CONTROLVM_MESSAGE_HEADER.
+ */
+
+#ifndef __CONTROLVMCOMPLETIONSTATUS_H__
+#define __CONTROLVMCOMPLETIONSTATUS_H__
+
+/* General Errors------------------------------------------------------[0-99] */
+#define CONTROLVM_RESP_SUCCESS                                  0
+#define CONTROLVM_RESP_ERROR_ALREADY_DONE                       1
+#define CONTROLVM_RESP_ERROR_IOREMAP_FAILED                     2
+#define CONTROLVM_RESP_ERROR_KMALLOC_FAILED                     3
+#define CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN                 4
+#define CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT      5
+
+/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */
+#define CONTROLVM_RESP_ERROR_CLIENT_SWITCHCOUNT_NONZERO         100
+#define CONTROLVM_RESP_ERROR_EXPECTED_CHIPSET_INIT              101
+
+/* Maximum Limit----------------------------------------------------[200-299] */
+#define CONTROLVM_RESP_ERROR_MAX_BUSES         201     /* BUS_CREATE */
+#define CONTROLVM_RESP_ERROR_MAX_DEVICES        202    /* DEVICE_CREATE */
+/* Payload and Parameter Related------------------------------------[400-499] */
+#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID   400     /* SWITCH_ATTACHEXTPORT,
+                                                        * DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401   /* Multiple */
+#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */
+/* Specified[Packet Structure] Value-------------------------------[500-599] */
+#define CONTROLVM_RESP_ERROR_BUS_INVALID       500     /* SWITCH_ATTACHINTPORT,
+                                                        * BUS_CONFIGURE,
+                                                        * DEVICE_CREATE,
+                                                        * DEVICE_CONFIG
+                                                        * DEVICE_DESTROY */
+#define CONTROLVM_RESP_ERROR_DEVICE_INVALID    501 /* SWITCH_ATTACHINTPORT */
+                                                   /* DEVICE_CREATE,
+                                                    * DEVICE_CONFIGURE,
+                                                    * DEVICE_DESTROY */
+#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID   502 /* DEVICE_CREATE,
+                                                    * DEVICE_CONFIGURE */
+/* Partition Driver Callback Interface----------------------[600-699] */
+#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604        /* BUS_CREATE,
+                                                        * BUS_DESTROY,
+                                                        * DEVICE_CREATE,
+                                                        * DEVICE_DESTROY */
+/* Unable to invoke VIRTPCI callback */
+#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605 /* BUS_CREATE,
+                                                               * BUS_DESTROY,
+                                                               * DEVICE_CREATE,
+                                                               * DEVICE_DESTROY */
+/* VIRTPCI Callback returned error */
+#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606 /* SWITCH_ATTACHEXTPORT,
+                                                               * SWITCH_DETACHEXTPORT
+                                                               * DEVICE_CONFIGURE */
+
+/* generic device callback returned error */
+/* Bus Related------------------------------------------------------[700-799] */
+#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700   /* BUS_DESTROY */
+/* Channel Related--------------------------------------------------[800-899] */
+#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800  /* GET_CHANNELINFO,
+                                                        * DEVICE_DESTROY */
+#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801        /* DEVICE_CREATE */
+/* Chipset Shutdown Related---------------------------------------[1000-1099] */
+#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED            1000
+#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_ALREADY_ACTIVE    1001
+
+/* Chipset Stop Related-------------------------------------------[1100-1199] */
+#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS            1100
+#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_SWITCH         1101
+
+/* Device Related-------------------------------------------------[1400-1499] */
+#define CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT                1400
+
+#endif /* __CONTROLVMCOMPLETIONSTATUS_H__ not defined */
diff --git a/drivers/staging/unisys/common-spar/include/diagnostics/appos_subsystems.h b/drivers/staging/unisys/common-spar/include/diagnostics/appos_subsystems.h
new file mode 100644 (file)
index 0000000..4c6294d
--- /dev/null
@@ -0,0 +1,310 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* Please note that this file is to be used ONLY for defining diagnostic
+ * subsystem values for the appos (sPAR Linux service partitions) component.
+ */
+#ifndef __APPOS_SUBSYSTEMS_H__
+#define __APPOS_SUBSYSTEMS_H__
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+
+static inline char *
+subsys_unknown_to_s(int subsys, char *s, int n)
+{
+       snprintf(s, n, "SUBSYS-%-2.2d", subsys);
+       s[n - 1] = '\0';
+       return s;
+}
+
+#define SUBSYS_TO_MASK(subsys)      (1ULL << (subsys))
+
+/* The first SUBSYS_APPOS_MAX subsystems are the same for each AppOS type
+ * (IOVM, SMS, etc.) The rest have unique values for each AppOS type.
+ */
+#define SUBSYS_APPOS_MAX 16
+
+#define        SUBSYS_APPOS_DEFAULT         1  /* or "other" */
+#define SUBSYS_APPOS_CHIPSET         2 /* controlvm and other */
+                                       /* low-level sPAR activity */
+#define SUBSYS_APPOS_BUS             3 /* sPAR bus */
+/* DAK #define SUBSYS_APPOS_DIAG            4  // diagnostics and dump */
+#define SUBSYS_APPOS_CHANNELACCESS   5 /* generic channel access */
+#define SUBSYS_APPOS_NICCLIENT       6 /* virtual NIC client */
+#define SUBSYS_APPOS_HBACLIENT       7 /* virtual HBA client */
+#define SUBSYS_APPOS_CONSOLESERIAL   8 /* sPAR virtual serial console */
+#define SUBSYS_APPOS_UISLIB          9 /*  */
+#define SUBSYS_APPOS_VRTCUPDD       10 /*  */
+#define SUBSYS_APPOS_WATCHDOG       11 /* watchdog timer and healthcheck */
+#define SUBSYS_APPOS_13             13 /* available */
+#define SUBSYS_APPOS_14             14 /* available */
+#define SUBSYS_APPOS_15             15 /* available */
+#define SUBSYS_APPOS_16             16 /* available */
+static inline char *
+subsys_generic_to_s(int subsys, char *s, int n)
+{
+       switch (subsys) {
+       case SUBSYS_APPOS_DEFAULT:
+               strncpy(s, "APPOS_DEFAULT", n);
+               break;
+       case SUBSYS_APPOS_CHIPSET:
+               strncpy(s, "APPOS_CHIPSET", n);
+               break;
+       case SUBSYS_APPOS_BUS:
+               strncpy(s, "APPOS_BUS", n);
+               break;
+       case SUBSYS_APPOS_CHANNELACCESS:
+               strncpy(s, "APPOS_CHANNELACCESS", n);
+               break;
+       case SUBSYS_APPOS_NICCLIENT:
+               strncpy(s, "APPOS_NICCLIENT", n);
+               break;
+       case SUBSYS_APPOS_HBACLIENT:
+               strncpy(s, "APPOS_HBACLIENT", n);
+               break;
+       case SUBSYS_APPOS_CONSOLESERIAL:
+               strncpy(s, "APPOS_CONSOLESERIAL", n);
+               break;
+       case SUBSYS_APPOS_UISLIB:
+               strncpy(s, "APPOS_UISLIB", n);
+               break;
+       case SUBSYS_APPOS_VRTCUPDD:
+               strncpy(s, "APPOS_VRTCUPDD", n);
+               break;
+       case SUBSYS_APPOS_WATCHDOG:
+               strncpy(s, "APPOS_WATCHDOG", n);
+               break;
+       case SUBSYS_APPOS_13:
+               strncpy(s, "APPOS_13", n);
+               break;
+       case SUBSYS_APPOS_14:
+               strncpy(s, "APPOS_14", n);
+               break;
+       case SUBSYS_APPOS_15:
+               strncpy(s, "APPOS_15", n);
+               break;
+       case SUBSYS_APPOS_16:
+               strncpy(s, "APPOS_16", n);
+               break;
+       default:
+               subsys_unknown_to_s(subsys, s, n);
+               break;
+       }
+       s[n - 1] = '\0';
+       return s;
+}
+
+/* CONSOLE */
+
+#define SUBSYS_CONSOLE_VIDEO        (SUBSYS_APPOS_MAX + 1)     /* 17 */
+#define SUBSYS_CONSOLE_KBDMOU       (SUBSYS_APPOS_MAX + 2)     /* 18 */
+#define SUBSYS_CONSOLE_04           (SUBSYS_APPOS_MAX + 4)
+#define SUBSYS_CONSOLE_05           (SUBSYS_APPOS_MAX + 5)
+#define SUBSYS_CONSOLE_06           (SUBSYS_APPOS_MAX + 6)
+#define SUBSYS_CONSOLE_07           (SUBSYS_APPOS_MAX + 7)
+#define SUBSYS_CONSOLE_08           (SUBSYS_APPOS_MAX + 8)
+#define SUBSYS_CONSOLE_09           (SUBSYS_APPOS_MAX + 9)
+#define SUBSYS_CONSOLE_10           (SUBSYS_APPOS_MAX + 10)
+#define SUBSYS_CONSOLE_11           (SUBSYS_APPOS_MAX + 11)
+#define SUBSYS_CONSOLE_12           (SUBSYS_APPOS_MAX + 12)
+#define SUBSYS_CONSOLE_13           (SUBSYS_APPOS_MAX + 13)
+#define SUBSYS_CONSOLE_14           (SUBSYS_APPOS_MAX + 14)
+#define SUBSYS_CONSOLE_15           (SUBSYS_APPOS_MAX + 15)
+#define SUBSYS_CONSOLE_16           (SUBSYS_APPOS_MAX + 16)
+#define SUBSYS_CONSOLE_17           (SUBSYS_APPOS_MAX + 17)
+#define SUBSYS_CONSOLE_18           (SUBSYS_APPOS_MAX + 18)
+#define SUBSYS_CONSOLE_19           (SUBSYS_APPOS_MAX + 19)
+#define SUBSYS_CONSOLE_20           (SUBSYS_APPOS_MAX + 20)
+#define SUBSYS_CONSOLE_21           (SUBSYS_APPOS_MAX + 21)
+#define SUBSYS_CONSOLE_22           (SUBSYS_APPOS_MAX + 22)
+#define SUBSYS_CONSOLE_23           (SUBSYS_APPOS_MAX + 23)
+#define SUBSYS_CONSOLE_24           (SUBSYS_APPOS_MAX + 24)
+#define SUBSYS_CONSOLE_25           (SUBSYS_APPOS_MAX + 25)
+#define SUBSYS_CONSOLE_26           (SUBSYS_APPOS_MAX + 26)
+#define SUBSYS_CONSOLE_27           (SUBSYS_APPOS_MAX + 27)
+#define SUBSYS_CONSOLE_28           (SUBSYS_APPOS_MAX + 28)
+#define SUBSYS_CONSOLE_29           (SUBSYS_APPOS_MAX + 29)
+#define SUBSYS_CONSOLE_30           (SUBSYS_APPOS_MAX + 30)
+#define SUBSYS_CONSOLE_31           (SUBSYS_APPOS_MAX + 31)
+#define SUBSYS_CONSOLE_32           (SUBSYS_APPOS_MAX + 32)
+#define SUBSYS_CONSOLE_33           (SUBSYS_APPOS_MAX + 33)
+#define SUBSYS_CONSOLE_34           (SUBSYS_APPOS_MAX + 34)
+#define SUBSYS_CONSOLE_35           (SUBSYS_APPOS_MAX + 35)
+#define SUBSYS_CONSOLE_36           (SUBSYS_APPOS_MAX + 36)
+#define SUBSYS_CONSOLE_37           (SUBSYS_APPOS_MAX + 37)
+#define SUBSYS_CONSOLE_38           (SUBSYS_APPOS_MAX + 38)
+#define SUBSYS_CONSOLE_39           (SUBSYS_APPOS_MAX + 39)
+#define SUBSYS_CONSOLE_40           (SUBSYS_APPOS_MAX + 40)
+#define SUBSYS_CONSOLE_41           (SUBSYS_APPOS_MAX + 41)
+#define SUBSYS_CONSOLE_42           (SUBSYS_APPOS_MAX + 42)
+#define SUBSYS_CONSOLE_43           (SUBSYS_APPOS_MAX + 43)
+#define SUBSYS_CONSOLE_44           (SUBSYS_APPOS_MAX + 44)
+#define SUBSYS_CONSOLE_45           (SUBSYS_APPOS_MAX + 45)
+#define SUBSYS_CONSOLE_46           (SUBSYS_APPOS_MAX + 46)
+
+static inline char *
+subsys_console_to_s(int subsys, char *s, int n)
+{
+       switch (subsys) {
+       case SUBSYS_CONSOLE_VIDEO:
+               strncpy(s, "CONSOLE_VIDEO", n);
+               break;
+       case SUBSYS_CONSOLE_KBDMOU:
+               strncpy(s, "CONSOLE_KBDMOU", n);
+               break;
+       case SUBSYS_CONSOLE_04:
+               strncpy(s, "CONSOLE_04", n);
+               break;
+       case SUBSYS_CONSOLE_05:
+               strncpy(s, "CONSOLE_05", n);
+               break;
+       case SUBSYS_CONSOLE_06:
+               strncpy(s, "CONSOLE_06", n);
+               break;
+       case SUBSYS_CONSOLE_07:
+               strncpy(s, "CONSOLE_07", n);
+               break;
+       case SUBSYS_CONSOLE_08:
+               strncpy(s, "CONSOLE_08", n);
+               break;
+       case SUBSYS_CONSOLE_09:
+               strncpy(s, "CONSOLE_09", n);
+               break;
+       case SUBSYS_CONSOLE_10:
+               strncpy(s, "CONSOLE_10", n);
+               break;
+       case SUBSYS_CONSOLE_11:
+               strncpy(s, "CONSOLE_11", n);
+               break;
+       case SUBSYS_CONSOLE_12:
+               strncpy(s, "CONSOLE_12", n);
+               break;
+       case SUBSYS_CONSOLE_13:
+               strncpy(s, "CONSOLE_13", n);
+               break;
+       case SUBSYS_CONSOLE_14:
+               strncpy(s, "CONSOLE_14", n);
+               break;
+       case SUBSYS_CONSOLE_15:
+               strncpy(s, "CONSOLE_15", n);
+               break;
+       case SUBSYS_CONSOLE_16:
+               strncpy(s, "CONSOLE_16", n);
+               break;
+       case SUBSYS_CONSOLE_17:
+               strncpy(s, "CONSOLE_17", n);
+               break;
+       case SUBSYS_CONSOLE_18:
+               strncpy(s, "CONSOLE_18", n);
+               break;
+       case SUBSYS_CONSOLE_19:
+               strncpy(s, "CONSOLE_19", n);
+               break;
+       case SUBSYS_CONSOLE_20:
+               strncpy(s, "CONSOLE_20", n);
+               break;
+       case SUBSYS_CONSOLE_21:
+               strncpy(s, "CONSOLE_21", n);
+               break;
+       case SUBSYS_CONSOLE_22:
+               strncpy(s, "CONSOLE_22", n);
+               break;
+       case SUBSYS_CONSOLE_23:
+               strncpy(s, "CONSOLE_23", n);
+               break;
+       case SUBSYS_CONSOLE_24:
+               strncpy(s, "CONSOLE_24", n);
+               break;
+       case SUBSYS_CONSOLE_25:
+               strncpy(s, "CONSOLE_25", n);
+               break;
+       case SUBSYS_CONSOLE_26:
+               strncpy(s, "CONSOLE_26", n);
+               break;
+       case SUBSYS_CONSOLE_27:
+               strncpy(s, "CONSOLE_27", n);
+               break;
+       case SUBSYS_CONSOLE_28:
+               strncpy(s, "CONSOLE_28", n);
+               break;
+       case SUBSYS_CONSOLE_29:
+               strncpy(s, "CONSOLE_29", n);
+               break;
+       case SUBSYS_CONSOLE_30:
+               strncpy(s, "CONSOLE_30", n);
+               break;
+       case SUBSYS_CONSOLE_31:
+               strncpy(s, "CONSOLE_31", n);
+               break;
+       case SUBSYS_CONSOLE_32:
+               strncpy(s, "CONSOLE_32", n);
+               break;
+       case SUBSYS_CONSOLE_33:
+               strncpy(s, "CONSOLE_33", n);
+               break;
+       case SUBSYS_CONSOLE_34:
+               strncpy(s, "CONSOLE_34", n);
+               break;
+       case SUBSYS_CONSOLE_35:
+               strncpy(s, "CONSOLE_35", n);
+               break;
+       case SUBSYS_CONSOLE_36:
+               strncpy(s, "CONSOLE_36", n);
+               break;
+       case SUBSYS_CONSOLE_37:
+               strncpy(s, "CONSOLE_37", n);
+               break;
+       case SUBSYS_CONSOLE_38:
+               strncpy(s, "CONSOLE_38", n);
+               break;
+       case SUBSYS_CONSOLE_39:
+               strncpy(s, "CONSOLE_39", n);
+               break;
+       case SUBSYS_CONSOLE_40:
+               strncpy(s, "CONSOLE_40", n);
+               break;
+       case SUBSYS_CONSOLE_41:
+               strncpy(s, "CONSOLE_41", n);
+               break;
+       case SUBSYS_CONSOLE_42:
+               strncpy(s, "CONSOLE_42", n);
+               break;
+       case SUBSYS_CONSOLE_43:
+               strncpy(s, "CONSOLE_43", n);
+               break;
+       case SUBSYS_CONSOLE_44:
+               strncpy(s, "CONSOLE_44", n);
+               break;
+       case SUBSYS_CONSOLE_45:
+               strncpy(s, "CONSOLE_45", n);
+               break;
+       case SUBSYS_CONSOLE_46:
+               strncpy(s, "CONSOLE_46", n);
+               break;
+       default:
+               subsys_unknown_to_s(subsys, s, n);
+               break;
+       }
+       s[n - 1] = '\0';
+       return s;
+}
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/iovmcall_gnuc.h b/drivers/staging/unisys/common-spar/include/iovmcall_gnuc.h
new file mode 100644 (file)
index 0000000..7304e9a
--- /dev/null
@@ -0,0 +1,53 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* Linux GCC Version (32-bit and 64-bit) */
+static inline unsigned long
+__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx,
+                    unsigned long reg_ecx)
+{
+       unsigned long result = 0;
+
+       unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
+       cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
+       if (cpuid_ecx & 0x80000000) {
+             __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+                                  "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)
+                                     );
+       } else {
+               result = -1;
+       }
+       return result;
+}
+
+static inline unsigned long
+__unisys_extended_vmcall_gnuc(unsigned long long tuple,
+                             unsigned long long reg_ebx,
+                             unsigned long long reg_ecx,
+                             unsigned long long reg_edx)
+{
+       unsigned long result = 0;
+
+       unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
+       cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
+       if (cpuid_ecx & 0x80000000) {
+             __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+                                  "a"(tuple), "b"(reg_ebx), "c"(reg_ecx),
+                                  "d"(reg_edx));
+       } else {
+               result = -1;
+       }
+       return result;
+       }
diff --git a/drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h b/drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h
new file mode 100644 (file)
index 0000000..3736779
--- /dev/null
@@ -0,0 +1,209 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VBUSDEVICEINFO_H__
+#define __VBUSDEVICEINFO_H__
+
+#include "commontypes.h"
+
+#pragma pack(push, 1)          /* both GCC and VC now allow this pragma */
+
+/* An array of this struct is present in the channel area for each vbus.
+ * (See vbuschannel.h.)
+ * It is filled in by the client side to provide info about the device
+ * and driver from the client's perspective.
+ */
+typedef struct _ULTRA_VBUS_DEVICEINFO {
+       U8 devType[16];         /* short string identifying the device type */
+       U8 drvName[16];         /* driver .sys file name */
+       U8 infoStrings[96];     /* sequence of tab-delimited id strings: */
+       /* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */
+       U8 reserved[128];       /* pad size to 256 bytes */
+} ULTRA_VBUS_DEVICEINFO;
+
+#pragma pack(pop)
+
+/* Reads chars from the buffer at <src> for <srcmax> bytes, and writes to
+ * the buffer at <p>, which is <remain> bytes long, ensuring never to
+ * overflow the buffer at <p>, using the following rules:
+ * - printable characters are simply copied from the buffer at <src> to the
+ *   buffer at <p>
+ * - intervening streaks of non-printable characters in the buffer at <src>
+ *   are replaced with a single space in the buffer at <p>
+ * Note that we pay no attention to '\0'-termination.
+ * Returns the number of bytes written to <p>.
+ *
+ * Pass <p> == NULL and <remain> == 0 for this special behavior.  In this
+ * case, we simply return the number of bytes that WOULD HAVE been written
+ * to a buffer at <p>, had it been infinitely big.
+ */
+static inline int
+VBUSCHANNEL_sanitize_buffer(char *p, int remain, char *src, int srcmax)
+{
+       int chars = 0;
+       int nonprintable_streak = 0;
+       while (srcmax > 0) {
+               if ((*src >= ' ') && (*src < 0x7f)) {
+                       if (nonprintable_streak) {
+                               if (remain > 0) {
+                                       *p = ' ';
+                                       p++;
+                                       remain--;
+                                       chars++;
+                               } else if (p == NULL)
+                                       chars++;
+                               nonprintable_streak = 0;
+                       }
+                       if (remain > 0) {
+                               *p = *src;
+                               p++;
+                               remain--;
+                               chars++;
+                       } else if (p == NULL)
+                               chars++;
+               } else
+                       nonprintable_streak = 1;
+               src++;
+               srcmax--;
+       }
+       return chars;
+}
+
+#define VBUSCHANNEL_ADDACHAR(ch, p, remain, chars) \
+       do {                                       \
+               if (remain <= 0)                   \
+                       break;                     \
+               *p = ch;                           \
+               p++;  chars++;  remain--;          \
+       } while (0)
+
+/* Converts the non-negative value at <num> to an ascii decimal string
+ * at <p>, writing at most <remain> bytes.  Note there is NO '\0' termination
+ * written to <p>.
+ *
+ * Returns the number of bytes written to <p>.
+ *
+ * Note that we create this function because we need to do this operation in
+ * an environment-independent way (since we are in a common header file).
+ */
+static inline int
+VBUSCHANNEL_itoa(char *p, int remain, int num)
+{
+       int digits = 0;
+       char s[32];
+       int i;
+
+       if (num == 0) {
+               /* '0' is a special case */
+               if (remain <= 0)
+                       return 0;
+               *p = '0';
+               return 1;
+       }
+       /* form a backwards decimal ascii string in <s> */
+       while (num > 0) {
+               if (digits >= (int) sizeof(s))
+                       return 0;
+               s[digits++] = (num % 10) + '0';
+               num = num / 10;
+       }
+       if (remain < digits) {
+               /* not enough room left at <p> to hold number, so fill with
+                * '?' */
+               for (i = 0; i < remain; i++, p++)
+                       *p = '?';
+               return remain;
+       }
+       /* plug in the decimal ascii string representing the number, by */
+       /* reversing the string we just built in <s> */
+       i = digits;
+       while (i > 0) {
+               i--;
+               *p = s[i];
+               p++;
+       }
+       return digits;
+}
+
+/* Reads <devInfo>, and converts its contents to a printable string at <p>,
+ * writing at most <remain> bytes.  Note there is NO '\0' termination
+ * written to <p>.
+ *
+ * Pass <devix> >= 0 if you want a device index presented.
+ *
+ * Returns the number of bytes written to <p>.
+ */
+static inline int
+VBUSCHANNEL_devInfoToStringBuffer(ULTRA_VBUS_DEVICEINFO devInfo,
+                                 char *p, int remain, int devix)
+{
+       char *psrc;
+       int nsrc, x, i, pad;
+       int chars = 0;
+
+       psrc = &(devInfo.devType[0]);
+       nsrc = sizeof(devInfo.devType);
+       if (VBUSCHANNEL_sanitize_buffer(NULL, 0, psrc, nsrc) <= 0)
+               return 0;
+
+       /* emit device index */
+       if (devix >= 0) {
+               VBUSCHANNEL_ADDACHAR('[', p, remain, chars);
+               x = VBUSCHANNEL_itoa(p, remain, devix);
+               p += x;
+               remain -= x;
+               chars += x;
+               VBUSCHANNEL_ADDACHAR(']', p, remain, chars);
+       } else {
+               VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+               VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+               VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+       }
+
+       /* emit device type */
+       x = VBUSCHANNEL_sanitize_buffer(p, remain, psrc, nsrc);
+       p += x;
+       remain -= x;
+       chars += x;
+       pad = 15 - x;           /* pad device type to be exactly 15 chars */
+       for (i = 0; i < pad; i++)
+               VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+       VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+
+       /* emit driver name */
+       psrc = &(devInfo.drvName[0]);
+       nsrc = sizeof(devInfo.drvName);
+       x = VBUSCHANNEL_sanitize_buffer(p, remain, psrc, nsrc);
+       p += x;
+       remain -= x;
+       chars += x;
+       pad = 15 - x;           /* pad driver name to be exactly 15 chars */
+       for (i = 0; i < pad; i++)
+               VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+       VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+
+       /* emit strings */
+       psrc = &(devInfo.infoStrings[0]);
+       nsrc = sizeof(devInfo.infoStrings);
+       x = VBUSCHANNEL_sanitize_buffer(p, remain, psrc, nsrc);
+       p += x;
+       remain -= x;
+       chars += x;
+       VBUSCHANNEL_ADDACHAR('\n', p, remain, chars);
+
+       return chars;
+}
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/version.h b/drivers/staging/unisys/common-spar/include/version.h
new file mode 100644 (file)
index 0000000..00b0ebb
--- /dev/null
@@ -0,0 +1,46 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* version.h */
+
+/*  Common version/release info needed by all components goes here.
+ *  (This file must compile cleanly in all environments.)
+ *  Ultimately, this will be combined with defines generated dynamically as
+ *  part of the sysgen, and some of the defines below may in fact end up
+ *  being replaced with dynamically generated ones.
+ */
+#ifndef __VERSION_H__
+#define __VERSION_H__
+
+#define SPARVER1 "1"
+#define SPARVER2 "0"
+#define SPARVER3 "0"
+#define SPARVER4 "0"
+
+#define  VERSION        SPARVER1 "." SPARVER2 "." SPARVER3 "." SPARVER4
+#define  VERSIONDATE    __DATE__
+
+/* Here are various version forms needed in Windows environments.
+ */
+#define VISOR_PRODUCTVERSION      SPARVERCOMMA
+#define VISOR_PRODUCTVERSION_STR  SPARVER1 "." SPARVER2 "." SPARVER3 "." \
+       SPARVER4
+#define VISOR_OBJECTVERSION_STR   SPARVER1 "," SPARVER2 "," SPARVER3 "," \
+       SPARVER4
+
+#define  COPYRIGHT      "Unisys Corporation"
+#define  COPYRIGHTDATE  "2010 - 2013"
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/vmcallinterface.h b/drivers/staging/unisys/common-spar/include/vmcallinterface.h
new file mode 100644 (file)
index 0000000..bd8944a
--- /dev/null
@@ -0,0 +1,167 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __IOMONINTF_H__
+#define __IOMONINTF_H__
+
+/*
+* This file contains all structures needed to support the VMCALLs for IO
+* Virtualization.  The VMCALLs are provided by Monitor and used by IO code
+* running on IO Partitions.
+*/
+
+#ifdef __GNUC__
+#include "iovmcall_gnuc.h"
+#endif /*  */
+#include "diagchannel.h"
+
+#ifdef VMCALL_IO_CONTROLVM_ADDR
+#undef VMCALL_IO_CONTROLVM_ADDR
+#endif /*  */
+
+/* define subsystem number for AppOS, used in uislib driver  */
+#define MDS_APPOS 0x4000000000000000   /* subsystem = 62 - AppOS */
+typedef enum {         /* VMCALL identification tuples  */
+           /* Note: when a new VMCALL is added:
+            * - the 1st 2 hex digits correspond to one of the
+            *   VMCALL_MONITOR_INTERFACE types and
+            * - the next 2 hex digits are the nth relative instance of within a
+            *   type
+            * E.G. for VMCALL_VIRTPART_RECYCLE_PART,
+            * - the 0x02 identifies it as a VMCALL_VIRTPART type and
+            * - the 0x01 identifies it as the 1st instance of a VMCALL_VIRTPART
+            *   type of VMCALL
+            */
+
+       VMCALL_IO_CONTROLVM_ADDR = 0x0501,      /* used by all Guests, not just
+                                                * IO */
+       VMCALL_IO_DIAG_ADDR = 0x0508,
+       VMCALL_IO_VISORSERIAL_ADDR = 0x0509,
+       VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708, /* Allow caller to
+                                                         * query virtual time
+                                                         * offset */
+       VMCALL_CHANNEL_VERSION_MISMATCH = 0x0709,
+       VMCALL_POST_CODE_LOGEVENT = 0x070B,     /* LOGEVENT Post Code (RDX) with
+                                                * specified subsystem mask (RCX
+                                                * - monitor_subsystems.h) and
+                                                * severity (RDX) */
+       VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER = 0x0802, /* Yield the
+                                                           * remainder & all
+                                                           * future quantums of
+                                                           * the caller */
+       VMCALL_MEASUREMENT_DO_NOTHING = 0x0901,
+       VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02    /* Allow
+                                                * ULTRA_SERVICE_CAPABILITY_TIME
+                                                * capable guest to make
+                                                * VMCALL */
+} VMCALL_MONITOR_INTERFACE_METHOD_TUPLE;
+
+#define VMCALL_SUCCESS 0
+#define VMCALL_SUCCESSFUL(result)      (result == 0)
+
+#ifdef __GNUC__
+#define unisys_vmcall(tuple, reg_ebx, reg_ecx) \
+       __unisys_vmcall_gnuc(tuple, reg_ebx, reg_ecx)
+#define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \
+       __unisys_extended_vmcall_gnuc(tuple, reg_ebx, reg_ecx, reg_edx)
+#define ISSUE_IO_VMCALL(InterfaceMethod, param, result) \
+       (result = unisys_vmcall(InterfaceMethod, (param) & 0xFFFFFFFF,  \
+                               (param) >> 32))
+#define ISSUE_IO_EXTENDED_VMCALL(InterfaceMethod, param1, param2,      \
+                                param3, result)                        \
+       (result = unisys_extended_vmcall(InterfaceMethod, param1,       \
+                                        param2, param3))
+
+    /* The following uses VMCALL_POST_CODE_LOGEVENT interface but is currently
+     * not used much */
+#define ISSUE_IO_VMCALL_POSTCODE_SEVERITY(postcode, severity)          \
+do {                                                                   \
+       U32 _tempresult = VMCALL_SUCCESS;                               \
+       ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity,   \
+                                MDS_APPOS, postcode, _tempresult);     \
+} while (0)
+#endif
+
+/* Structures for IO VMCALLs */
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+struct phys_info {
+       U64 pi_pfn;
+       U16 pi_off;
+       U16 pi_len;
+};
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+typedef struct phys_info IO_DATA_STRUCTURE;
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+/* Parameters to VMCALL_IO_CONTROLVM_ADDR interface */
+typedef struct _VMCALL_IO_CONTROLVM_ADDR_PARAMS {
+           /* The Guest-relative physical address of the ControlVm channel.
+           * This VMCall fills this in with the appropriate address. */
+       U64 ChannelAddress;     /* contents provided by this VMCALL (OUT) */
+           /* the size of the ControlVm channel in bytes This VMCall fills this
+           * in with the appropriate address. */
+       U32 ChannelBytes;       /* contents provided by this VMCALL (OUT) */
+       U8 Unused[4];           /* Unused Bytes in the 64-Bit Aligned Struct */
+} VMCALL_IO_CONTROLVM_ADDR_PARAMS;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+/* Parameters to VMCALL_IO_DIAG_ADDR interface */
+typedef struct _VMCALL_IO_DIAG_ADDR_PARAMS {
+           /* The Guest-relative physical address of the diagnostic channel.
+           * This VMCall fills this in with the appropriate address. */
+       U64 ChannelAddress;     /* contents provided by this VMCALL (OUT) */
+} VMCALL_IO_DIAG_ADDR_PARAMS;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+/* Parameters to VMCALL_IO_VISORSERIAL_ADDR interface */
+typedef struct _VMCALL_IO_VISORSERIAL_ADDR_PARAMS {
+           /* The Guest-relative physical address of the serial console
+           * channel.  This VMCall fills this in with the appropriate
+           * address. */
+       U64 ChannelAddress;     /* contents provided by this VMCALL (OUT) */
+} VMCALL_IO_VISORSERIAL_ADDR_PARAMS;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* Parameters to VMCALL_CHANNEL_MISMATCH interface */
+typedef struct _VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS {
+       U8 ChannelName[32];     /* Null terminated string giving name of channel
+                                * (IN) */
+       U8 ItemName[32];        /* Null terminated string giving name of
+                                * mismatched item (IN) */
+       U32 SourceLineNumber;   /* line# where invoked. (IN) */
+       U8 SourceFileName[36];  /* source code where invoked - Null terminated
+                                * string (IN) */
+} VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS;
+
+#endif /* __IOMONINTF_H__ */
diff --git a/drivers/staging/unisys/include/commontypes.h b/drivers/staging/unisys/include/commontypes.h
new file mode 100644 (file)
index 0000000..ae46bed
--- /dev/null
@@ -0,0 +1,166 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _COMMONTYPES_H_
+#define _COMMONTYPES_H_
+
+/* define the following to prevent include nesting in kernel header files of
+ * similar abreviated content */
+#define _SUPERVISOR_COMMONTYPES_H_
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/version.h>
+#else
+#include <stdint.h>
+#include <syslog.h>
+#endif
+
+#define U8  uint8_t
+#define U16 uint16_t
+#define U32 uint32_t
+#define U64 uint64_t
+#define S8  int8_t
+#define S16 int16_t
+#define S32 int32_t
+#define S64 int64_t
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_X86_32
+#define UINTN U32
+#else
+#define UINTN U64
+#endif
+
+#else
+
+#include <stdint.h>
+#if __WORDSIZE == 32
+#define UINTN U32
+#elif __WORDSIZE == 64
+#define UINTN U64
+#else
+#error Unsupported __WORDSIZE
+#endif
+
+#endif
+
+typedef struct {
+       U32 data1;
+       U16 data2;
+       U16 data3;
+       U8 data4[8];
+} __attribute__ ((__packed__)) GUID;
+
+#ifndef GUID0
+#define GUID0 {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }
+#endif
+typedef U64 GUEST_PHYSICAL_ADDRESS;
+
+#define MEMSET(ptr, val, len) memset(ptr, val, len)
+#define MEMCMP(m1, m2, len) memcmp(m1, m2, len)
+#define STRLEN(s) ((UINTN)strlen((const char *)s))
+#define STRCPY(d, s) (strcpy((char *)d, (const char *)s))
+
+#define INLINE inline
+#define OFFSETOF offsetof
+
+#ifdef __KERNEL__
+#define MEMORYBARRIER mb()
+#define MEMCPY(dest, src, len) memcpy(dest, src, len)
+
+#define CHANNEL_GUID_MISMATCH(chType, chName, field, expected, actual, fil, \
+                             lin, logCtx)                              \
+       do {                                                            \
+               char s1[50], s2[50], s3[50];                            \
+               pr_err("Channel mismatch on channel=%s(%s) field=%s expected=%s actual=%s @%s:%d\n", \
+                      chName, GUID_format2(&chType, s1), field,        \
+                      GUID_format2(&expected, s2), GUID_format2(&actual, s3), \
+                      fil, lin);                                       \
+       } while (0)
+#define CHANNEL_U32_MISMATCH(chType, chName, field, expected, actual, fil, \
+                            lin, logCtx)                               \
+       do {                                                            \
+               char s1[50];                                            \
+               pr_err("Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8lx actual=0x%-8.8lx @%s:%d\n", \
+                      chName, GUID_format2(&chType, s1), field,        \
+                      (unsigned long)expected, (unsigned long)actual,  \
+                      fil, lin);                                       \
+       } while (0)
+
+#define CHANNEL_U64_MISMATCH(chType, chName, field, expected, actual, fil, \
+                            lin, logCtx)                               \
+       do {                                                            \
+               char s1[50];                                            \
+               pr_err("Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8Lx actual=0x%-8.8Lx @%s:%d\n", \
+                      chName, GUID_format2(&chType, s1), field,        \
+                      (unsigned long long)expected,                    \
+                      (unsigned long long)actual,                      \
+                      fil, lin);                                       \
+       } while (0)
+
+#define UltraLogEvent(logCtx, EventId, Severity, SubsystemMask, pFunctionName, \
+                     LineNumber, Str, args...)                         \
+       pr_info(Str, ## args)
+
+#else
+#define MEMCPY(dest, src, len) memcpy(dest, src, len)
+
+#define MEMORYBARRIER mb()
+
+#define CHANNEL_GUID_MISMATCH(chType, chName, field, expected, actual, fil, \
+                             lin, logCtx)                              \
+       do {                                                            \
+               char s1[50], s2[50], s3[50];                            \
+               syslog(LOG_USER | LOG_ERR,                              \
+                      "Channel mismatch on channel=%s(%s) field=%s expected=%s actual=%s @%s:%d", \
+                      chName, GUID_format2(&chType, s1), field,        \
+                      GUID_format2(&expected, s2), GUID_format2(&actual, s3), \
+                      fil, lin);                                       \
+       } while (0)
+
+#define CHANNEL_U32_MISMATCH(chType, chName, field, expected, actual, fil, \
+                            lin, logCtx)                               \
+       do {                                                            \
+               char s1[50];                                            \
+               syslog(LOG_USER | LOG_ERR,                              \
+                      "Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8lx actual=0x%-8.8lx @%s:%d", \
+                      chName, GUID_format2(&chType, s1), field,        \
+                      (unsigned long)expected, (unsigned long)actual,  \
+                      fil, lin);                                       \
+       } while (0)
+
+#define CHANNEL_U64_MISMATCH(chType, chName, field, expected, actual, fil, \
+                            lin, logCtx)                               \
+       do {                                                            \
+               char s1[50];                                            \
+               syslog(LOG_USER | LOG_ERR,                              \
+                      "Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8Lx actual=0x%-8.8Lx @%s:%d", \
+                      chName, GUID_format2(&chType, s1), field,        \
+                      (unsigned long long)expected,                    \
+                      (unsigned long long)actual,                      \
+                      fil, lin);                                       \
+       } while (0)
+
+#define UltraLogEvent(logCtx, EventId, Severity, SubsystemMask, pFunctionName, \
+                     LineNumber, Str, args...)                         \
+       syslog(LOG_USER | LOG_INFO, Str, ## args)
+#endif
+
+#define VolatileBarrier() MEMORYBARRIER
+
+#endif
+#include "guidutils.h"
diff --git a/drivers/staging/unisys/include/guestlinuxdebug.h b/drivers/staging/unisys/include/guestlinuxdebug.h
new file mode 100644 (file)
index 0000000..c3de849
--- /dev/null
@@ -0,0 +1,182 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __GUESTLINUXDEBUG_H__
+#define __GUESTLINUXDEBUG_H__
+
+/*
+* This file contains supporting interface for "vmcallinterface.h", particuarly
+* regarding adding additional structure and functionality to linux
+* ISSUE_IO_VMCALL_POSTCODE_SEVERITY */
+
+
+/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/
+#include "vmcallinterface.h"
+typedef enum {         /* POSTCODE driver identifier tuples */
+       /* visorchipset driver files */
+       VISOR_CHIPSET_PC = 0xA0,
+       VISOR_CHIPSET_PC_controlvm_c = 0xA1,
+       VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2,
+       VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3,
+       VISOR_CHIPSET_PC_file_c = 0xA4,
+       VISOR_CHIPSET_PC_parser_c = 0xA5,
+       VISOR_CHIPSET_PC_testing_c = 0xA6,
+       VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7,
+       VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8,
+       /* visorbus driver files */
+       VISOR_BUS_PC = 0xB0,
+       VISOR_BUS_PC_businst_attr_c = 0xB1,
+       VISOR_BUS_PC_channel_attr_c = 0xB2,
+       VISOR_BUS_PC_devmajorminor_attr_c = 0xB3,
+       VISOR_BUS_PC_visorbus_main_c = 0xB4,
+       /* visorclientbus driver files */
+       VISOR_CLIENT_BUS_PC = 0xC0,
+       VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1,
+       /* virt hba driver files */
+       VIRT_HBA_PC = 0xC2,
+       VIRT_HBA_PC_virthba_c = 0xC3,
+       /* virtpci driver files */
+       VIRT_PCI_PC = 0xC4,
+       VIRT_PCI_PC_virtpci_c = 0xC5,
+       /* virtnic driver files */
+       VIRT_NIC_PC = 0xC6,
+       VIRT_NIC_P_virtnic_c = 0xC7,
+       /* uislib driver files */
+       UISLIB_PC = 0xD0,
+       UISLIB_PC_uislib_c = 0xD1,
+       UISLIB_PC_uisqueue_c = 0xD2,
+       UISLIB_PC_uisthread_c = 0xD3,
+       UISLIB_PC_uisutils_c = 0xD4,
+} DRIVER_PC;
+
+typedef enum {                 /* POSTCODE event identifier tuples */
+       ATTACH_PORT_ENTRY_PC = 0x001,
+       ATTACH_PORT_FAILURE_PC = 0x002,
+       ATTACH_PORT_SUCCESS_PC = 0x003,
+       BUS_FAILURE_PC = 0x004,
+       BUS_CREATE_ENTRY_PC = 0x005,
+       BUS_CREATE_FAILURE_PC = 0x006,
+       BUS_CREATE_EXIT_PC = 0x007,
+       BUS_CONFIGURE_ENTRY_PC = 0x008,
+       BUS_CONFIGURE_FAILURE_PC = 0x009,
+       BUS_CONFIGURE_EXIT_PC = 0x00A,
+       CHIPSET_INIT_ENTRY_PC = 0x00B,
+       CHIPSET_INIT_SUCCESS_PC = 0x00C,
+       CHIPSET_INIT_FAILURE_PC = 0x00D,
+       CHIPSET_INIT_EXIT_PC = 0x00E,
+       CREATE_WORKQUEUE_PC = 0x00F,
+       CREATE_WORKQUEUE_FAILED_PC = 0x0A0,
+       CONTROLVM_INIT_FAILURE_PC = 0x0A1,
+       DEVICE_CREATE_ENTRY_PC = 0x0A2,
+       DEVICE_CREATE_FAILURE_PC = 0x0A3,
+       DEVICE_CREATE_SUCCESS_PC = 0x0A4,
+       DEVICE_CREATE_EXIT_PC = 0x0A5,
+       DEVICE_ADD_PC = 0x0A6,
+       DEVICE_REGISTER_FAILURE_PC = 0x0A7,
+       DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8,
+       DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9,
+       DEVICE_CHANGESTATE_EXIT_PC = 0x0AA,
+       DRIVER_ENTRY_PC = 0x0AB,
+       DRIVER_EXIT_PC = 0x0AC,
+       MALLOC_FAILURE_PC = 0x0AD,
+       QUEUE_DELAYED_WORK_PC = 0x0AE,
+       UISLIB_THREAD_FAILURE_PC = 0x0B7,
+       VBUS_CHANNEL_ENTRY_PC = 0x0B8,
+       VBUS_CHANNEL_FAILURE_PC = 0x0B9,
+       VBUS_CHANNEL_EXIT_PC = 0x0BA,
+       VHBA_CREATE_ENTRY_PC = 0x0BB,
+       VHBA_CREATE_FAILURE_PC = 0x0BC,
+       VHBA_CREATE_EXIT_PC = 0x0BD,
+       VHBA_CREATE_SUCCESS_PC = 0x0BE,
+       VHBA_COMMAND_HANDLER_PC = 0x0BF,
+       VHBA_PROBE_ENTRY_PC = 0x0C0,
+       VHBA_PROBE_FAILURE_PC = 0x0C1,
+       VHBA_PROBE_EXIT_PC = 0x0C2,
+       VNIC_CREATE_ENTRY_PC = 0x0C3,
+       VNIC_CREATE_FAILURE_PC = 0x0C4,
+       VNIC_CREATE_SUCCESS_PC = 0x0C5,
+       VNIC_PROBE_ENTRY_PC = 0x0C6,
+       VNIC_PROBE_FAILURE_PC = 0x0C7,
+       VNIC_PROBE_EXIT_PC = 0x0C8,
+       VPCI_CREATE_ENTRY_PC = 0x0C9,
+       VPCI_CREATE_FAILURE_PC = 0x0CA,
+       VPCI_CREATE_EXIT_PC = 0x0CB,
+       VPCI_PROBE_ENTRY_PC = 0x0CC,
+       VPCI_PROBE_FAILURE_PC = 0x0CD,
+       VPCI_PROBE_EXIT_PC = 0x0CE,
+       CRASH_DEV_ENTRY_PC = 0x0CF,
+       CRASH_DEV_EXIT_PC = 0x0D0,
+       CRASH_DEV_HADDR_NULL = 0x0D1,
+       CRASH_DEV_CONTROLVM_NULL = 0x0D2,
+       CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3,
+       CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4,
+       CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5,
+       CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6,
+       CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7,
+       CRASH_DEV_COUNT_FAILURE_PC = 0x0D8,
+       SAVE_MSG_BUS_FAILURE_PC = 0x0D9,
+       SAVE_MSG_DEV_FAILURE_PC = 0x0DA,
+       CALLHOME_INIT_FAILURE_PC = 0x0DB
+} EVENT_PC;
+
+#ifdef __GNUC__
+
+#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR
+#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING
+#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT     /* TODO-> Info currently
+                                                        * doesnt show, so we
+                                                        * set info=warning */
+/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR);
+ * Please also note that the resulting postcode is in hex, so if you are
+ * searching for the __LINE__ number, convert it first to decimal.  The line
+ * number combined with driver and type of call, will allow you to track down
+ * exactly what line an error occured on, or where the last driver
+ * entered/exited from.
+ */
+
+/* BASE FUNCTIONS */
+#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity)       \
+do {                                                                   \
+       unsigned long long post_code_temp;                              \
+       post_code_temp = (((U64)DRIVER_PC) << 56) | (((U64)EVENT_PC) << 44) | \
+               ((((U64)__LINE__) & 0xFFF) << 32) |                     \
+               (((U64)pc32bit) & 0xFFFFFFFF);                          \
+       ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity);    \
+} while (0)
+
+#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \
+do {                                                                   \
+       unsigned long long post_code_temp;                              \
+       post_code_temp = (((U64)DRIVER_PC) << 56) | (((U64)EVENT_PC) << 44) | \
+               ((((U64)__LINE__) & 0xFFF) << 32) |                     \
+               ((((U64)pc16bit1) & 0xFFFF) << 16) |                    \
+               (((U64)pc16bit2) & 0xFFFF);                             \
+       ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity);    \
+} while (0)
+
+/* MOST COMMON */
+#define POSTCODE_LINUX_2(EVENT_PC, severity)                           \
+       POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity);
+
+#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity)                  \
+       POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity);
+
+
+#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity)       \
+       POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1,           \
+                        pc16bit2, severity);
+
+#endif
+#endif
diff --git a/drivers/staging/unisys/include/guidutils.h b/drivers/staging/unisys/include/guidutils.h
new file mode 100644 (file)
index 0000000..75caf92
--- /dev/null
@@ -0,0 +1,203 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* guidutils.h
+ *
+ * These are GUID manipulation inlines that can be used from either
+ * kernel-mode or user-mode.
+ *
+ */
+#ifndef __GUIDUTILS_H__
+#define __GUIDUTILS_H__
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#define GUID_STRTOUL kstrtoul
+#else
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define GUID_STRTOUL strtoul
+#endif
+
+static inline char *
+GUID_format1(const GUID *guid, char *s)
+{
+       sprintf(s, "{%-8.8lx-%-4.4x-%-4.4x-%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x}",
+               (ulong) guid->data1,
+               guid->data2,
+               guid->data3,
+               guid->data4[0],
+               guid->data4[1],
+               guid->data4[2],
+               guid->data4[3],
+               guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+       return s;
+}
+
+/** Format a GUID in Microsoft's 'what in the world were they thinking'
+ *  format.
+ */
+static inline char *
+GUID_format2(const GUID *guid, char *s)
+{
+       sprintf(s, "{%-8.8lx-%-4.4x-%-4.4x-%-2.2x%-2.2x-%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x}",
+               (ulong) guid->data1,
+               guid->data2,
+               guid->data3,
+               guid->data4[0],
+               guid->data4[1],
+               guid->data4[2],
+               guid->data4[3],
+               guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+       return s;
+}
+
+/**
+ * Like GUID_format2 but without the curly braces and the
+ * hex digits in upper case
+ */
+static inline char *
+GUID_format3(const GUID *guid, char *s)
+{
+       sprintf(s, "%-8.8lX-%-4.4X-%-4.4X-%-2.2X%-2.2X-%-2.2X%-2.2X%-2.2X%-2.2X%-2.2X%-2.2X",
+               (ulong) guid->data1,
+               guid->data2,
+               guid->data3,
+               guid->data4[0],
+               guid->data4[1],
+               guid->data4[2],
+               guid->data4[3],
+               guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+       return s;
+}
+
+/** Parse a guid string in any of these forms:
+ *      {11111111-2222-3333-4455-66778899aabb}
+ *      {11111111-2222-3333-445566778899aabb}
+ *      11111111-2222-3333-4455-66778899aabb
+ *      11111111-2222-3333-445566778899aabb
+ */
+static inline GUID
+GUID_scan(U8 *p)
+{
+       GUID guid = GUID0;
+       U8 x[33];
+       int count = 0;
+       int c, i = 0;
+       U8 cdata1[9];
+       U8 cdata2[5];
+       U8 cdata3[5];
+       U8 cdata4[3];
+       int dashcount = 0;
+       int brace = 0;
+       unsigned long uldata;
+
+       if (!p)
+               return guid;
+       if (*p == '{') {
+               p++;
+               brace = 1;
+       }
+       while (count < 32) {
+               if (*p == '}')
+                       return guid;
+               if (*p == '\0')
+                       return guid;
+               c = toupper(*p);
+               p++;
+               if (c == '-') {
+                       switch (dashcount) {
+                       case 0:
+                               if (i != 8)
+                                       return guid;
+                               break;
+                       case 1:
+                               if (i != 4)
+                                       return guid;
+                               break;
+                       case 2:
+                               if (i != 4)
+                                       return guid;
+                               break;
+                       case 3:
+                               if (i != 4)
+                                       return guid;
+                               break;
+                       default:
+                               return guid;
+                       }
+                       dashcount++;
+                       i = 0;
+                       continue;
+               }
+               if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
+                       i++;
+               else
+                       return guid;
+               x[count++] = c;
+       }
+       x[count] = '\0';
+       if (brace) {
+               if (*p == '}')
+                       p++;
+               else
+                       return guid;
+       }
+       if (dashcount == 3 || dashcount == 4)
+               ;
+       else
+               return guid;
+       memset(cdata1, 0, sizeof(cdata1));
+       memset(cdata2, 0, sizeof(cdata2));
+       memset(cdata3, 0, sizeof(cdata3));
+       memset(cdata4, 0, sizeof(cdata4));
+       memcpy(cdata1, x + 0, 8);
+       memcpy(cdata2, x + 8, 4);
+       memcpy(cdata3, x + 12, 4);
+
+       if (GUID_STRTOUL((char *) cdata1, 16, &uldata) == 0)
+               guid.data1 = (U32)uldata;
+       if (GUID_STRTOUL((char *) cdata2, 16, &uldata) == 0)
+               guid.data2 = (U16)uldata;
+       if (GUID_STRTOUL((char *) cdata3, 16, &uldata) == 0)
+               guid.data3 = (U16)uldata;
+
+       for (i = 0; i < 8; i++) {
+               memcpy(cdata4, x + 16 + (i * 2), 2);
+               if (GUID_STRTOUL((char *) cdata4, 16, &uldata) == 0)
+                       guid.data4[i] = (U8) uldata;
+       }
+
+       return guid;
+}
+
+static inline char *
+GUID_sanitize(char *inputGuidStr, char *outputGuidStr)
+{
+       GUID g;
+       GUID guid0 = GUID0;
+       *outputGuidStr = '\0';
+       g = GUID_scan((U8 *) inputGuidStr);
+       if (memcmp(&g, &guid0, sizeof(GUID)) == 0)
+               return outputGuidStr;   /* bad GUID format */
+       return GUID_format1(&g, outputGuidStr);
+}
+
+#endif
diff --git a/drivers/staging/unisys/include/periodic_work.h b/drivers/staging/unisys/include/periodic_work.h
new file mode 100644 (file)
index 0000000..6e725df
--- /dev/null
@@ -0,0 +1,40 @@
+/* periodic_work.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __PERIODIC_WORK_H__
+#define __PERIODIC_WORK_H__
+
+#include "timskmod.h"
+
+
+
+/* PERIODIC_WORK an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct PERIODIC_WORK_Tag PERIODIC_WORK;
+
+PERIODIC_WORK *periodic_work_create(ulong jiffy_interval,
+                                    struct workqueue_struct *workqueue,
+                                    void (*workfunc)(void *),
+                                    void *workfuncarg,
+                                    const char *devnam);
+void            periodic_work_destroy(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_nextperiod(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_start(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_stop(PERIODIC_WORK *periodic_work);
+
+#endif
diff --git a/drivers/staging/unisys/include/procobjecttree.h b/drivers/staging/unisys/include/procobjecttree.h
new file mode 100644 (file)
index 0000000..d3b69f4
--- /dev/null
@@ -0,0 +1,48 @@
+/* procobjecttree.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes the interfaces necessary for creating a tree of types,
+ *  objects, and properties in /proc.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __PROCOBJECTTREE_H__
+#define __PROCOBJECTTREE_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+/* These are opaque structures to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct MYPROCOBJECT_Tag MYPROCOBJECT;
+typedef struct MYPROCTYPE_Tag   MYPROCTYPE;
+
+MYPROCOBJECT *proc_CreateObject(MYPROCTYPE *type, const char *name,
+                               void *context);
+void          proc_DestroyObject(MYPROCOBJECT *obj);
+MYPROCTYPE   *proc_CreateType(struct proc_dir_entry *procRootDir,
+                             const char **name,
+                             const char **propertyNames,
+                             void (*show_property)(struct seq_file *,
+                                                   void *, int));
+void          proc_DestroyType(MYPROCTYPE *type);
+
+#endif
diff --git a/drivers/staging/unisys/include/sparstop.h b/drivers/staging/unisys/include/sparstop.h
new file mode 100644 (file)
index 0000000..3603ac6
--- /dev/null
@@ -0,0 +1,30 @@
+/* sparstop.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __SPARSTOP_H__
+#define __SPARSTOP_H__
+
+#include "timskmod.h"
+#include "version.h"
+#include <linux/ctype.h>
+
+typedef void (*SPARSTOP_COMPLETE_FUNC) (void *context, int status);
+
+int sp_stop(void *context, SPARSTOP_COMPLETE_FUNC get_complete_func);
+void test_remove_stop_device(void);
+
+#endif
diff --git a/drivers/staging/unisys/include/timskmod.h b/drivers/staging/unisys/include/timskmod.h
new file mode 100644 (file)
index 0000000..0d0b29c
--- /dev/null
@@ -0,0 +1,558 @@
+/* timskmod.h
+ *
+ * Copyright ï¿½ 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __TIMSKMOD_H__
+#define __TIMSKMOD_H__
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/cdev.h>
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/dma.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+/* #define EXPORT_SYMTAB */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/fcntl.h>
+#include <linux/aio.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+
+/* #define DEBUG */
+#ifndef BOOL
+#define BOOL    int
+#endif
+#define FALSE   0
+#define TRUE    1
+#if !defined SUCCESS
+#define SUCCESS 0
+#endif
+#define FAILURE (-1)
+#define DRIVERNAMEMAX 50
+#define MIN(a, b)     (((a) < (b)) ? (a) : (b))
+#define MAX(a, b)     (((a) > (b)) ? (a) : (b))
+#define STRUCTSEQUAL(x, y) (memcmp(&x, &y, sizeof(x)) == 0)
+#ifndef HOSTADDRESS
+#define HOSTADDRESS unsigned long long
+#endif
+
+typedef long VMMIO;  /**< Virtual MMIO address (returned from ioremap), which
+    *   is a virtual address pointer to a memory-mapped region.
+    *   These are declared as "long" instead of u32* to force you to
+    *   use readb()/writeb()/memcpy_fromio()/etc to access them.
+    *   (On x86 we could probably get away with treating them as
+    *   pointers.)
+    */
+typedef long VMMIO8; /**< #VMMIO pointing to  8-bit data */
+typedef long VMMIO16;/**< #VMMIO pointing to 16-bit data */
+typedef long VMMIO32;/**< #VMMIO pointing to 32-bit data */
+
+#define LOCKSEM(sem)                   down_interruptible(sem)
+#define LOCKSEM_UNINTERRUPTIBLE(sem)   down(sem)
+#define UNLOCKSEM(sem)                 up(sem)
+
+/** lock read/write semaphore for reading.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to lock
+ */
+#define LOCKREADSEM(sem)               down_read(sem)
+
+/** unlock read/write semaphore for reading.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to unlock
+ */
+#define UNLOCKREADSEM(sem)             up_read(sem)
+
+/** lock read/write semaphore for writing.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to lock
+ */
+#define LOCKWRITESEM(sem)              down_write(sem)
+
+/** unlock read/write semaphore for writing.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to unlock
+ */
+#define UNLOCKWRITESEM(sem)            up_write(sem)
+
+#ifdef ENABLE_RETURN_TRACE
+#define RETTRACE(x)                                            \
+       do {                                                   \
+               if (1) {                                       \
+                       INFODRV("RET 0x%lx in %s",             \
+                               (ulong)(x), __func__);     \
+               }                                          \
+       } while (0)
+#else
+#define RETTRACE(x)
+#endif
+
+/** return from a void function, using a common exit point "Away" */
+#define RETVOID    do { RETTRACE(0); goto Away; } while (0)
+/** return from an int function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETINT(x)  do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** return from a void* function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETPTR(x)  do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** return from a BOOL function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETBOOL(x) do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** Given a typedef/struct/union and a member field name,
+ *  return the number of bytes occupied by that field.
+ *  @param TYPE     the typedef name, or "struct xx" or "union xx"
+ *  @param MEMBER   the name of the member field whose size is to be determined
+ *  @return         the size of the field in bytes
+ */
+#define FAIL(msg, status) do {          \
+               ERRDRV("'%s'"                                         \
+                      ": error (status=%d)\n",                       \
+                      msg, status);                                  \
+               RETINT(status);                                       \
+       } while (0)
+#define FAIL_WPOSTCODE_1(msg, status, EVENT_PC) do {          \
+               ERRDRV("'%s'"                                         \
+                      ": error (status=%d)\n",                       \
+                      msg, status);                                    \
+               POSTCODE_LINUX_2(EVENT_PC, DIAG_SEVERITY_ERR);          \
+               RETINT(status);                                         \
+       } while (0)
+#define FAIL_WPOSTCODE_2(msg, status, EVENT_PC, pcval32bit) do {          \
+               ERRDRV("'%s'"                                           \
+                      ": error (status=%d)\n",                         \
+                      msg, status);                                    \
+               POSTCODE_LINUX_3(EVENT_PC, pcval32bit, DIAG_SEVERITY_ERR); \
+               RETINT(status);                                         \
+       } while (0)
+#define FAIL_WPOSTCODE_3(msg, status, EVENT_PC, pcval16bit1, pcval16bit2) \
+       do {                                                            \
+               ERRDRV("'%s'"                                           \
+                      ": error (status=%d)\n",                         \
+                      msg, status);                                    \
+               POSTCODE_LINUX_4(EVENT_PC, pcval16bit1, pcval16bit2,    \
+                                DIAG_SEVERITY_ERR);                    \
+               RETINT(status);                                         \
+       } while (0)
+/** Try to evaulate the provided expression, and do a RETINT(x) iff
+ *  the expression evaluates to < 0.
+ *  @param x the expression to try
+ */
+#define TRY(x) do { int status = (x);                          \
+               if (status < 0)                                \
+                       FAIL(__stringify(x), status);          \
+       } while (0)
+
+#define TRY_WPOSTCODE_1(x, EVENT_PC) do { \
+               int status = (x);         \
+               if (status < 0)                                         \
+                       FAIL_WPOSTCODE_1(__stringify(x), status, EVENT_PC); \
+       } while (0)
+
+#define TRY_WPOSTCODE_2(x, EVENT_PC, pcval32bit) do { \
+               int status = (x);                     \
+               if (status < 0)                                         \
+                       FAIL_WPOSTCODE_2(__stringify(x), status, EVENT_PC, \
+                                        pcval32bit);                   \
+       } while (0)
+
+#define TRY_WPOSTCODE_3(x, EVENT_PC, pcval16bit1, pcval16bit2) do { \
+               int status = (x);                                   \
+               if (status < 0)                                         \
+                       FAIL_WPOSTCODE_3(__stringify(x), status, EVENT_PC, \
+                                        pcval16bit1, pcval16bit2);     \
+       } while (0)
+
+#define ASSERT(cond)                                           \
+       do { if (!(cond))                                      \
+                       HUHDRV("ASSERT failed - %s",           \
+                              __stringify(cond));             \
+       } while (0)
+
+#define sizeofmember(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
+/** "Covered quotient" function */
+#define COVQ(v, d)  (((v) + (d) - 1) / (d))
+#define SWAPPOINTERS(p1, p2)                           \
+       do {                                            \
+               void *SWAPPOINTERS_TEMP = (void *)p1;   \
+               (void *)(p1) = (void *)(p2);            \
+               (void *)(p2) = SWAPPOINTERS_TEMP;       \
+       } while (0)
+
+/**
+ *  @addtogroup driverlogging
+ *  @{
+ */
+
+#define PRINTKDRV(fmt, args...) LOGINF(fmt, ## args)
+#define TBDDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define HUHDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define ERRDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define WARNDRV(fmt, args...)   LOGWRN(fmt, ## args)
+#define SECUREDRV(fmt, args...) LOGWRN(fmt, ## args)
+#define INFODRV(fmt, args...)   LOGINF(fmt, ## args)
+#define DEBUGDRV(fmt, args...)  DBGINF(fmt, ## args)
+
+#define PRINTKDEV(devname, fmt, args...)  LOGINFDEV(devname, fmt, ## args)
+#define TBDDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define HUHDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define ERRDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define ERRDEVX(devno, fmt, args...)     LOGERRDEVX(devno, fmt, ## args)
+#define WARNDEV(devname, fmt, args...)    LOGWRNDEV(devname, fmt, ## args)
+#define SECUREDEV(devname, fmt, args...)  LOGWRNDEV(devname, fmt, ## args)
+#define INFODEV(devname, fmt, args...)    LOGINFDEV(devname, fmt, ## args)
+#define INFODEVX(devno, fmt, args...)     LOGINFDEVX(devno, fmt, ## args)
+#define DEBUGDEV(devname, fmt, args...)   DBGINFDEV(devname, fmt, ## args)
+
+
+/* @} */
+
+/** Used to add a single line to the /proc filesystem buffer */
+#define ADDPROCLINE(buf, bufsize, line, linelen, totallen) \
+       {                                                  \
+               if ((totallen) + (linelen) >= bufsize)     \
+                       RETINT(totallen);                  \
+               if (linelen > 0) {                         \
+                       strcat(buf, line);                 \
+                       totallen += linelen;               \
+               }                                          \
+       }
+
+
+
+/** Verifies the consistency of your PRIVATEDEVICEDATA structure using
+ *  conventional "signature" fields:
+ *  <p>
+ *  - sig1 should contain the size of the structure
+ *  - sig2 should contain a pointer to the beginning of the structure
+ */
+#define DDLOOKSVALID(dd)                                 \
+               ((dd != NULL)                             &&    \
+                ((dd)->sig1 == sizeof(PRIVATEDEVICEDATA)) &&   \
+                ((dd)->sig2 == dd))
+
+/** Verifies the consistency of your PRIVATEFILEDATA structure using
+ *  conventional "signature" fields:
+ *  <p>
+ *  - sig1 should contain the size of the structure
+ *  - sig2 should contain a pointer to the beginning of the structure
+ */
+#define FDLOOKSVALID(fd)                               \
+       ((fd != NULL)                           &&     \
+        ((fd)->sig1 == sizeof(PRIVATEFILEDATA)) &&    \
+        ((fd)->sig2 == fd))
+
+/** Verifies the consistency of a PRIVATEDEVICEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKDDX(dd, x) (                                           \
+                       if (!DDLOOKSVALID((dd))) {         \
+                               PRINTKDRV("bad device structure");      \
+                               RETINT(x);                              \
+                       })
+
+/** Verifies the consistency of a PRIVATEDEVICEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKDD(dd) (                                                    \
+                       if (!DDLOOKSVALID(dd)) {                        \
+                               PRINTKDRV("bad device structure");      \
+                               RETVOID;                                \
+                       })
+
+/** Verifies the consistency of a PRIVATEFILEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKFDX(fd, x) (                                           \
+               if (!FDLOOKSVALID(fd)) {                   \
+                       PRINTKDRV("bad file structure");   \
+                       RETINT(x);                         \
+               })
+
+/** Verifies the consistency of a PRIVATEFILEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKFD(fd) (                                      \
+               if (!FDLOOKSVALID(fd)) {                  \
+                       PRINTKDRV("bad file structure");  \
+                       RETVOID;                          \
+               })
+
+/** Converts a device index #devix into #devData, after checking for validity.
+ *  Can only be called from functions returning void.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMID(devix, devData, where, dbg)                          \
+       {                                                               \
+               if (devix >= MAXDEVICES) {                              \
+                       PRINTKDRV("bad devix passed to %s()", where);   \
+                       RETVOID;                                        \
+               }                                                       \
+               if (dbg)                                                \
+                       DEBUGDEV(devix, "%s", where);                   \
+               if (devix >= MAXDEVICES) {                              \
+                       DEBUGDEV(devix, "%s - bad devix %d",            \
+                                where, devix);                         \
+                       RETVOID;                                        \
+               }                                                       \
+               devData = DevData[devix];                               \
+               CHKDD(devData);                                         \
+       }
+
+/** Converts a device index #devix into #devData, after checking for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMIDX(devix, devData, errcode, where, dbg)                        \
+       {                                                               \
+               if (devix >= MAXDEVICES) {                              \
+                       PRINTKDRV("bad devix passed to %s()", where);   \
+                       RETINT(errcode);                                \
+               }                                                       \
+               if (dbg)                                                \
+                       DEBUGDEV(devix, "%s", where);                   \
+               if (devix >= MAXDEVICES) {                              \
+                       DEBUGDEV(devix, "%s - bad devix %d",            \
+                                where, devix);                         \
+                       RETINT(-ENODEV);                                \
+               }                                                       \
+               devData = DevData[devix];                               \
+               CHKDDX(devData, -EIO);                                  \
+       }
+
+/** Converts an inode pointer #inode into a #devix and #devData, after
+ *  checking for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param inode input inode pointer
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMINODE(devix, devData, inode, errcode, where, dbg)       \
+       {                                                               \
+               if (inode == NULL) {                                    \
+                       PRINTKDRV("bad inode passed to %s()", where);   \
+                       RETINT(errcode);                                \
+               }                                                       \
+               devix = MINOR(inode->i_rdev);                           \
+               if (dbg)                                                \
+                       DEBUGDEV(devix, "%s", where);                   \
+               if (devix >= MAXDEVICES) {                              \
+                       DEBUGDEV(devix, "%s - bad devix %d",            \
+                                where, devix);                         \
+                       RETINT(-ENODEV);                                \
+               }                                                       \
+               devData = DevData[devix];                               \
+               CHKDDX(devData, -EIO);                                  \
+       }
+
+/** Converts a file pointer #file into a #devix and #devData, after checking
+ *  for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param file input file pointer
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMFILE(devix, devData, fileData, file, errcode, where, dbg) \
+               {                                                       \
+               if (file == NULL) {                                     \
+                       PRINTKDRV("bad file passed to %s()", where);    \
+                       RETINT(errcode);                                \
+               }                                                       \
+               CHKFDX((PRIVATEFILEDATA *)(file->private_data), -EIO);  \
+               fileData = file->private_data;                          \
+               devix = fileData->devix;                                \
+               if (dbg)                                                \
+                       DEBUGDEV(devix, "%s %p", where, file);          \
+               if (devix >= MAXDEVICES) {                              \
+                       DEBUGDEV(devix, "%s - bad devix %d",            \
+                                where, devix);                         \
+                       RETINT(-ENODEV);                                \
+               }                                                       \
+               devData = DevData[devix];                               \
+               CHKDDX(devData, -EIO);                                  \
+       }
+
+/** Locks dd->lockDev if you havn't already locked it */
+#define LOCKDEV(dd)                                                    \
+       {                                                              \
+               if (!lockedDev) {                                      \
+                       spin_lock(&dd->lockDev);                       \
+                       lockedDev = TRUE;                              \
+               }                                                      \
+       }
+
+/** Unlocks dd->lockDev if you previously locked it */
+#define UNLOCKDEV(dd)                                                  \
+       {                                                              \
+               if (lockedDev) {                                       \
+                       spin_unlock(&dd->lockDev);                     \
+                       lockedDev = FALSE;                             \
+               }                                                      \
+       }
+
+/** Locks dd->lockDevISR if you havn't already locked it */
+#define LOCKDEVISR(dd)                                                 \
+       {                                                              \
+               if (!lockedDevISR) {                                   \
+                       spin_lock_irqsave(&dd->lockDevISR, flags);     \
+                       lockedDevISR = TRUE;                           \
+               }                                                      \
+       }
+
+/** Unlocks dd->lockDevISR if you previously locked it */
+#define UNLOCKDEVISR(dd)                                               \
+       {                                                               \
+               if (lockedDevISR) {                                     \
+                       spin_unlock_irqrestore(&dd->lockDevISR, flags); \
+                       lockedDevISR = FALSE;                           \
+               }                                                       \
+       }
+
+/** Locks LockGlobalISR if you havn't already locked it */
+#define LOCKGLOBALISR                                                  \
+       {                                                              \
+               if (!lockedGlobalISR) {                                \
+                       spin_lock_irqsave(&LockGlobalISR, flags);      \
+                       lockedGlobalISR = TRUE;                        \
+               }                                                      \
+       }
+
+/** Unlocks LockGlobalISR if you previously locked it */
+#define UNLOCKGLOBALISR                                                \
+       {                                                              \
+               if (lockedGlobalISR) {                                 \
+                       spin_unlock_irqrestore(&LockGlobalISR, flags); \
+                       lockedGlobalISR = FALSE;                       \
+               }                                                      \
+       }
+
+/** Locks LockGlobal if you havn't already locked it */
+#define LOCKGLOBAL                                                     \
+       {                                                              \
+               if (!lockedGlobal) {                                   \
+                       spin_lock(&LockGlobal);                        \
+                       lockedGlobal = TRUE;                           \
+               }                                                      \
+       }
+
+/** Unlocks LockGlobal if you previously locked it */
+#define UNLOCKGLOBAL                                                   \
+       {                                                              \
+               if (lockedGlobal) {                                    \
+                       spin_unlock(&LockGlobal);                      \
+                       lockedGlobal = FALSE;                          \
+               }                                                      \
+       }
+
+/** Use this at the beginning of functions where you intend to
+ *  use #LOCKDEV/#UNLOCKDEV, #LOCKDEVISR/#UNLOCKDEVISR,
+ *  #LOCKGLOBAL/#UNLOCKGLOBAL, #LOCKGLOBALISR/#UNLOCKGLOBALISR.
+ *
+ *  Note that __attribute__((unused)) is how you tell GNU C to suppress
+ *  any warning messages about the variable being unused.
+ */
+#define LOCKPREAMBLE                                                   \
+       ulong flags __attribute__((unused)) = 0;                        \
+       BOOL lockedDev __attribute__((unused)) = FALSE;                 \
+       BOOL lockedDevISR __attribute__((unused)) = FALSE;              \
+       BOOL lockedGlobal __attribute__((unused)) = FALSE;              \
+       BOOL lockedGlobalISR __attribute__((unused)) = FALSE
+
+
+
+/** Sleep for an indicated number of seconds (for use in kernel mode).
+ *  @param x the number of seconds to sleep.
+ */
+#define SLEEP(x)                                            \
+       do { current->state = TASK_INTERRUPTIBLE;            \
+               schedule_timeout((x)*HZ);                    \
+       } while (0)
+
+/** Sleep for an indicated number of jiffies (for use in kernel mode).
+ *  @param x the number of jiffies to sleep.
+ */
+#define SLEEPJIFFIES(x)                                                    \
+       do { current->state = TASK_INTERRUPTIBLE;                   \
+               schedule_timeout(x);                                \
+       } while (0)
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a):(b))
+#endif
+
+static inline struct cdev *cdev_alloc_init(struct module *owner,
+                                          const struct file_operations *fops)
+{
+       struct cdev *cdev = NULL;
+       cdev = cdev_alloc();
+       if (!cdev)
+               return NULL;
+       cdev->ops = fops;
+       cdev->owner = owner;
+
+       /* Note that the memory allocated for cdev will be deallocated
+        * when the usage count drops to 0, because it is controlled
+        * by a kobject of type ktype_cdev_dynamic.  (This
+        * deallocation could very well happen outside of our kernel
+        * module, like via the cdev_put in __fput() for example.)
+        */
+       return cdev;
+}
+
+#include "timskmodutils.h"
+
+#endif
diff --git a/drivers/staging/unisys/include/timskmodutils.h b/drivers/staging/unisys/include/timskmodutils.h
new file mode 100644 (file)
index 0000000..ad4175e
--- /dev/null
@@ -0,0 +1,194 @@
+/* timskmodutils.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __TIMSKMODUTILS_H__
+#define __TIMSKMODUTILS_H__
+
+#include "timskmod.h"
+
+void *kmalloc_kernel(size_t siz);
+void *kmalloc_kernel_dma(size_t siz);
+void  kfree_kernel(const void *p, size_t siz);
+void *vmalloc_kernel(size_t siz);
+void  vfree_kernel(const void *p, size_t siz);
+void *pgalloc_kernel(size_t siz);
+void  pgfree_kernel(const void *p, size_t siz);
+void  myprintk(const char *myDrvName, const char *devname,
+               const char *template, ...);
+void  myprintkx(const char *myDrvName, int devno, const char *template, ...);
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  @param dest               the print buffer where text characters will be
+ *                            written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                            to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                            hex-dumped
+ *  @param srcLen             the number of bytes at #src to be hex-dumped
+ *  @param bytesToDumpPerLine output will be formatted such that at most this
+ *                            many of the input data bytes will be represented
+ *                            on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int   hexDumpToBuffer(char *dest,
+                     int destSize,
+                     char *prefix,
+                     char *src,
+                     int srcLen,
+                     int bytesToDumpPerLine);
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  Assume the data buffer contains 32-bit words in little-endian format,
+ *  and dump the words with MSB first and LSB last.
+ *  @param dest               the print buffer where text characters will be
+ *                            written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                            to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                            hex-dumped
+ *  @param srcWords           the number of 32-bit words at #src to be
+ &                            hex-dumped
+ *  @param wordsToDumpPerLine output will be formatted such that at most this
+ *                            many of the input data words will be represented
+ *                            on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int   hexDumpWordsToBuffer(char *dest,
+                          int destSize,
+                          char *prefix,
+                          uint32_t *src,
+                          int srcWords,
+                          int wordsToDumpPerLine);
+
+
+/** Use printk to print the hexadecimal contents of a data buffer.
+ *  See #INFOHEXDRV and #INFOHEXDEV for info.
+ *  @ingroup internal
+ */
+int myPrintkHexDump(char *myDrvName,
+                   char *devname,
+                   char *prefix,
+                   char *src,
+                   int srcLen,
+                   int bytesToDumpPerLine);
+
+/** Given as input a number of seconds in #seconds, creates text describing
+ *  the time within #s.  Also breaks down the number of seconds into component
+ *  days, hours, minutes, and seconds, and stores to *#days, *#hours,
+ *  *#minutes, and *#secondsx.
+ *  @param seconds input number of seconds
+ *  @param days    points to a long value where the days component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param hours   points to a long value where the hours component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param minutes points to a long value where the minutes component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param secondsx points to a long value where the seconds component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param s       points to a character buffer where a text representation of
+ *                 the #seconds value will be stored.  This buffer MUST be
+ *                 large enough to hold the resulting string; to be safe it
+ *                 should be at least 100 bytes long.
+ */
+void  expandSeconds(time_t seconds,
+                   long *days, long *hours,
+                   long *minutes,
+                   long *secondsx,
+                   char *s);
+
+/*--------------------------------*
+ *---  GENERAL MESSAGEQ STUFF  ---*
+ *--------------------------------*/
+
+struct MessageQEntry;
+
+/** the data structure used to hold an arbitrary data item that you want
+ *  to place on a #MESSAGEQ.  Declare and initialize as follows:
+ *  @code
+ *      MESSAGEQENTRY myEntry;
+ *      initMessageQEntry (&myEntry, pointerToMyDataItem);
+ *  @endcode
+ *  This structure should be considered opaque; the client using it should
+ *  never access the fields directly.
+ *  Refer to these functions for more info:
+ *  - initMessageQ()
+ *  - initMessageQEntry()
+ *  - enqueueMessage()
+ *  - dequeueMessage()
+ *  - dequeueMessageNoBlock()
+ *  - getQueueCount()
+ *
+ *  @ingroup messageq
+ */
+typedef struct MessageQEntry {
+       void *data;
+       struct MessageQEntry *qNext;
+       struct MessageQEntry *qPrev;
+} MESSAGEQENTRY;
+
+/** the data structure used to hold a FIFO queue of #MESSAGEQENTRY<b></b>s.
+ *  Declare and initialize as follows:
+ *  @code
+ *      MESSAGEQ myQueue;
+ *      initMessageQ (&myQueue);
+ *  @endcode
+ *  This structure should be considered opaque; the client using it should
+ *  never access the fields directly.
+ *  Refer to these functions for more info:
+ *  - initMessageQ()
+ *  - initMessageQEntry()
+ *  - enqueueMessage()
+ *  - dequeueMessage()
+ *  - dequeueMessageNoBlock()
+ *  - getQueueCount()
+ *
+ *  @ingroup messageq
+ */
+typedef struct MessageQ {
+       MESSAGEQENTRY *qHead;
+       MESSAGEQENTRY *qTail;
+       struct semaphore nQEntries;
+       spinlock_t       queueLock;
+} MESSAGEQ;
+
+char *cyclesToSeconds(u64 cycles, u64 cyclesPerSecond,
+                     char *buf, size_t bufsize);
+char *cyclesToIterationSeconds(u64 cycles, u64 cyclesPerSecond,
+                              u64 iterations, char *buf, size_t bufsize);
+char *cyclesToSomethingsPerSecond(u64 cycles, u64 cyclesPerSecond,
+                                 u64 somethings, char *buf, size_t bufsize);
+void initMessageQ(MESSAGEQ *q);
+void initMessageQEntry(MESSAGEQENTRY *p, void *data);
+MESSAGEQENTRY *dequeueMessage(MESSAGEQ *q);
+MESSAGEQENTRY *dequeueMessageNoBlock(MESSAGEQ *q);
+void enqueueMessage(MESSAGEQ *q, MESSAGEQENTRY *pEntry);
+size_t getQueueCount(MESSAGEQ *q);
+int waitQueueLen(wait_queue_head_t *q);
+void debugWaitQ(wait_queue_head_t *q);
+struct seq_file *seq_file_new_buffer(void *buf, size_t buf_size);
+void seq_file_done_buffer(struct seq_file *m);
+void seq_hexdump(struct seq_file *seq, u8 *pfx, void *buf, ulong nbytes);
+
+#endif
diff --git a/drivers/staging/unisys/include/uisqueue.h b/drivers/staging/unisys/include/uisqueue.h
new file mode 100644 (file)
index 0000000..a9d95d3
--- /dev/null
@@ -0,0 +1,472 @@
+/* uisqueue.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys IO Virtualization header NOTE: This file contains only Linux
+ * specific structs.  All OS-independent structs are in iochannel.h.xx
+ */
+
+#ifndef __UISQUEUE_H__
+#define __UISQUEUE_H__
+
+#include "linux/version.h"
+#include "iochannel.h"
+#include "uniklog.h"
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+
+#include "controlvmchannel.h"
+#include "controlvmcompletionstatus.h"
+
+struct uisqueue_info {
+
+       pCHANNEL_HEADER chan;
+       /* channel containing queues in which scsi commands &
+        * responses are queued
+        */
+       U64 packets_sent;
+       U64 packets_received;
+       U64 interrupts_sent;
+       U64 interrupts_received;
+       U64 max_not_empty_cnt;
+       U64 total_wakeup_cnt;
+       U64 non_empty_wakeup_cnt;
+
+       struct {
+               SIGNAL_QUEUE_HEADER Reserved1;  /*  */
+               SIGNAL_QUEUE_HEADER Reserved2;  /*  */
+       } safe_uis_queue;
+       unsigned int (*send_int_if_needed)(struct uisqueue_info *info,
+                                          unsigned int whichcqueue,
+                                          unsigned char issueInterruptIfEmpty,
+                                          U64 interruptHandle,
+                                          unsigned char io_termination);
+};
+
+/* uisqueue_put_cmdrsp_with_lock_client queues a commmand or response
+ * to the specified queue, at the tail if the queue is full but
+ * oktowait == 0, then it return 0 indicating failure.  otherwise it
+ * wait for the queue to become non-full. If command is queued, return
+ * 1 for success.
+ */
+#define DONT_ISSUE_INTERRUPT 0
+#define ISSUE_INTERRUPT                 1
+
+#define DONT_WAIT                       0
+#define OK_TO_WAIT                      1
+#define UISLIB_LOCK_PREFIX \
+               ".section .smp_locks,\"a\"\n"   \
+               _ASM_ALIGN "\n"                 \
+               _ASM_PTR "661f\n" /* address */ \
+               ".previous\n"                   \
+               "661:\n\tlock; "
+
+unsigned long long uisqueue_InterlockedOr(volatile unsigned long long *Target,
+                                         unsigned long long Set);
+unsigned long long uisqueue_InterlockedAnd(volatile unsigned long long *Target,
+                                          unsigned long long Set);
+
+unsigned int uisqueue_send_int_if_needed(struct uisqueue_info *pqueueinfo,
+                                        unsigned int whichqueue,
+                                        unsigned char issueInterruptIfEmpty,
+                                        U64 interruptHandle,
+                                        unsigned char io_termination);
+
+int uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
+                                        struct uiscmdrsp *cmdrsp,
+                                        unsigned int queue,
+                                        void *insertlock,
+                                        unsigned char issueInterruptIfEmpty,
+                                        U64 interruptHandle,
+                                        char oktowait,
+                                        U8 *channelId);
+
+/* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
+ * and copies it to the area pointed by cmdrsp param.
+ * returns 0 if queue is empty, 1 otherwise
+ */
+int
+
+uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo, void *cmdrsp,
+                   unsigned int queue);
+
+#define MAX_NAME_SIZE_UISQUEUE 64
+
+struct extport_info {
+       U8 valid:1;
+       /* if 1, indicates this extport slot is occupied
+        * if 0, indicates that extport slot is unoccupied */
+
+       U32 num_devs_using;
+       /* When extport is added, this is set to 0.  For exports
+       * located in NETWORK switches:
+       * Each time a VNIC, i.e., intport, is added to the switch this
+       * is used to assign a pref_pnic for the VNIC and when assigned
+       * to a VNIC this counter is incremented. When a VNIC is
+       * deleted, the extport corresponding to the VNIC's pref_pnic
+       * is located and its num_devs_using is decremented. For VNICs,
+       * num_devs_using is basically used to load-balance transmit
+       * traffic from VNICs.
+       */
+
+       struct switch_info *swtch;
+       struct PciId pci_id;
+       char name[MAX_NAME_SIZE_UISQUEUE];
+       union {
+               struct vhba_wwnn wwnn;
+               unsigned char macaddr[MAX_MACADDR_LEN];
+       };
+};
+
+struct device_info {
+       void *chanptr;
+       U64 channelAddr;
+       U64 channelBytes;
+       GUID channelTypeGuid;
+       GUID devInstGuid;
+       struct InterruptInfo intr;
+       struct switch_info *swtch;
+       char devid[30];         /* "vbus<busno>:dev<devno>" */
+       U16 polling;
+       struct semaphore interrupt_callback_lock;
+       U32 busNo;
+       U32 devNo;
+       int (*interrupt)(void *);
+       void *interrupt_context;
+       void *private_data;
+       struct list_head list_polling_device_channels;
+       unsigned long long moved_to_tail_cnt;
+       unsigned long long first_busy_cnt;
+       unsigned long long last_on_list_cnt;
+};
+
+typedef enum {
+       RECOVERY_LAN = 1,
+       IB_LAN = 2
+} SWITCH_TYPE;
+
+struct bus_info {
+       U32 busNo, deviceCount;
+       struct device_info **device;
+       U64 guestHandle, recvBusInterruptHandle;
+       GUID busInstGuid;
+       ULTRA_VBUS_CHANNEL_PROTOCOL *pBusChannel;
+       int busChannelBytes;
+       struct proc_dir_entry *proc_dir;        /* proc/uislib/vbus/<x> */
+       struct proc_dir_entry *proc_info;       /* proc/uislib/vbus/<x>/info */
+       char name[25];
+       char partitionName[99];
+       struct bus_info *next;
+       U8 localVnic;           /* 1 if local vnic created internally
+                                * by IOVM; 0 otherwise... */
+};
+
+#define DEDICATED_SWITCH(pSwitch) ((pSwitch->extPortCount == 1) &&     \
+                                  (pSwitch->intPortCount == 1))
+
+struct sn_list_entry {
+       struct uisscsi_dest pdest;      /* scsi bus, target, lun for
+                                        * phys disk */
+       U8 sernum[MAX_SERIAL_NUM];      /* serial num of physical
+                                        * disk.. The length is always
+                                        * MAX_SERIAL_NUM, padded with
+                                        * spaces */
+       struct sn_list_entry *next;
+};
+
+struct networkPolicy {
+       U32 promiscuous:1;
+       U32 macassign:1;
+       U32 peerforwarding:1;
+       U32 nonotify:1;
+       U32 standby:1;
+       U32 callhome:2;
+       char ip_addr[30];
+};
+
+/*
+ * IO messages sent to UisnicControlChanFunc & UissdControlChanFunc by
+ * code that processes the ControlVm channel messages.
+ */
+
+
+typedef enum {
+       IOPART_ADD_VNIC,
+       IOPART_DEL_VNIC,
+       IOPART_DEL_ALL_VNICS,
+       IOPART_ADD_VHBA,
+       IOPART_ADD_VDISK,
+       IOPART_DEL_VHBA,
+       IOPART_DEL_VDISK,
+       IOPART_DEL_ALL_VDISKS_FOR_VHBA,
+       IOPART_DEL_ALL_VHBAS,
+       IOPART_ATTACH_PHBA,
+       IOPART_DETACH_PHBA,     /* 10 */
+       IOPART_ATTACH_PNIC,
+       IOPART_DETACH_PNIC,
+       IOPART_DETACH_VHBA,
+       IOPART_DETACH_VNIC,
+       IOPART_PAUSE_VDISK,
+       IOPART_RESUME_VDISK,
+       IOPART_ADD_DEVICE,      /* add generic device */
+       IOPART_DEL_DEVICE,      /* del generic device */
+} IOPART_MSG_TYPE;
+
+struct add_virt_iopart {
+       void *chanptr;          /* pointer to data channel */
+       U64 guestHandle;        /* used to convert guest physical
+                                * address to real physical address
+                                * for DMA, for ex. */
+       U64 recvBusInterruptHandle;     /* used to register to receive
+                                        * bus level interrupts. */
+       struct InterruptInfo intr;      /* contains recv & send
+                                        * interrupt info */
+       /* recvInterruptHandle is used to register to receive
+       * interrupts on the data channel. Used by GuestLinux/Windows
+       * IO drivers to connect to interrupt.  sendInterruptHandle is
+       * used by IOPart drivers as parameter to
+       * Issue_VMCALL_IO_QUEUE_TRANSITION to interrupt thread in
+       * guest linux/windows IO drivers when data channel queue for
+       * vhba/vnic goes from EMPTY to NON-EMPTY. */
+       struct switch_info *swtch;      /* pointer to the virtual
+                                        * switch to which the vnic is
+                                        * connected */
+
+       U8 useG2GCopy;          /* Used to determine if a virtual HBA
+                                * needs to use G2G copy. */
+       U8 Filler[7];
+
+       U32 busNo;
+       U32 devNo;
+       char *params;
+       ulong params_bytes;
+
+};
+
+struct add_vdisk_iopart {
+       void *chanptr;                /* pointer to data channel */
+       int implicit;
+       struct uisscsi_dest vdest;    /* scsi bus, target, lun for virt disk */
+       struct uisscsi_dest pdest;    /* scsi bus, target, lun for phys disk */
+       U8 sernum[MAX_SERIAL_NUM];    /* serial num of physical disk */
+       U32 serlen;                   /* length of serial num */
+       U32 busNo;
+       U32 devNo;
+};
+
+struct del_vdisk_iopart {
+       void *chanptr;               /* pointer to data channel */
+       struct uisscsi_dest vdest;   /* scsi bus, target, lun for virt disk */
+       U32 busNo;
+       U32 devNo;
+};
+
+struct del_virt_iopart {
+       void *chanptr;               /* pointer to data channel */
+       U32 busNo;
+       U32 devNo;
+};
+
+struct det_virt_iopart {            /* detach internal port */
+       void *chanptr;               /* pointer to data channel */
+       struct switch_info *swtch;
+};
+
+struct paures_vdisk_iopart {
+       void *chanptr;               /* pointer to data channel */
+       struct uisscsi_dest vdest;   /* scsi bus, target, lun for virt disk */
+};
+
+struct add_switch_iopart {          /* add switch */
+       struct switch_info *swtch;
+       char *params;
+       ulong params_bytes;
+};
+
+struct del_switch_iopart {          /* destroy switch */
+       struct switch_info *swtch;
+};
+
+struct io_msgs {
+
+       IOPART_MSG_TYPE msgtype;
+
+       /* additional params needed by some messages */
+       union {
+               struct add_virt_iopart add_vhba;
+               struct add_virt_iopart add_vnic;
+               struct add_vdisk_iopart add_vdisk;
+               struct del_virt_iopart del_vhba;
+               struct del_virt_iopart del_vnic;
+               struct det_virt_iopart det_vhba;
+               struct det_virt_iopart det_vnic;
+               struct del_vdisk_iopart del_vdisk;
+               struct del_virt_iopart del_all_vdisks_for_vhba;
+               struct add_virt_iopart add_device;
+               struct del_virt_iopart del_device;
+               struct det_virt_iopart det_intport;
+               struct add_switch_iopart add_switch;
+               struct del_switch_iopart del_switch;
+               struct extport_info *extPort;   /* for attach or detach
+                                                * pnic/generic delete all
+                                                * vhbas/allvnics need no
+                                                * parameters */
+               struct paures_vdisk_iopart paures_vdisk;
+       };
+};
+
+/*
+* Guest messages sent to VirtControlChanFunc by code that processes
+* the ControlVm channel messages.
+*/
+
+typedef enum {
+       GUEST_ADD_VBUS,
+       GUEST_ADD_VHBA,
+       GUEST_ADD_VNIC,
+       GUEST_DEL_VBUS,
+       GUEST_DEL_VHBA,
+       GUEST_DEL_VNIC,
+       GUEST_DEL_ALL_VHBAS,
+       GUEST_DEL_ALL_VNICS,
+       GUEST_DEL_ALL_VBUSES,   /* deletes all vhbas & vnics on all
+                                * buses and deletes all buses */
+       GUEST_PAUSE_VHBA,
+       GUEST_PAUSE_VNIC,
+       GUEST_RESUME_VHBA,
+       GUEST_RESUME_VNIC
+} GUESTPART_MSG_TYPE;
+
+struct add_vbus_guestpart {
+       void *chanptr;          /* pointer to data channel for bus -
+                                * NOT YET USED */
+       U32 busNo;              /* bus number to be created/deleted */
+       U32 deviceCount;        /* max num of devices on bus */
+       GUID busTypeGuid;       /* indicates type of bus */
+       GUID busInstGuid;       /* instance guid for device */
+};
+
+struct del_vbus_guestpart {
+       U32 busNo;              /* bus number to be deleted */
+       /* once we start using the bus's channel, add can dump busNo
+       * into the channel header and then delete will need only one
+       * parameter, chanptr. */
+};
+
+struct add_virt_guestpart {
+       void *chanptr;          /* pointer to data channel */
+       U32 busNo;              /* bus number for the operation */
+       U32 deviceNo;           /* number of device on the bus */
+       GUID devInstGuid;       /* instance guid for device */
+       struct InterruptInfo intr;      /* recv/send interrupt info */
+       /* recvInterruptHandle contains info needed in order to
+        * register to receive interrupts on the data channel.
+        * sendInterruptHandle contains handle which is provided to
+        * monitor VMCALL that will cause an interrupt to be generated
+        * for the other end.
+        */
+};
+
+struct pause_virt_guestpart {
+       void *chanptr;          /* pointer to data channel */
+};
+
+struct resume_virt_guestpart {
+       void *chanptr;          /* pointer to data channel */
+};
+
+struct del_virt_guestpart {
+       void *chanptr;          /* pointer to data channel */
+};
+
+struct init_chipset_guestpart {
+       U32 busCount;           /* indicates the max number of busses */
+       U32 switchCount;        /* indicates the max number of switches */
+};
+
+struct guest_msgs {
+
+       GUESTPART_MSG_TYPE msgtype;
+
+       /* additional params needed by messages */
+       union {
+               struct add_vbus_guestpart add_vbus;
+               struct add_virt_guestpart add_vhba;
+               struct add_virt_guestpart add_vnic;
+               struct pause_virt_guestpart pause_vhba;
+               struct pause_virt_guestpart pause_vnic;
+               struct resume_virt_guestpart resume_vhba;
+               struct resume_virt_guestpart resume_vnic;
+               struct del_vbus_guestpart del_vbus;
+               struct del_virt_guestpart del_vhba;
+               struct del_virt_guestpart del_vnic;
+               struct del_vbus_guestpart del_all_vhbas;
+               struct del_vbus_guestpart del_all_vnics;
+               /* del_all_vbuses needs no parameters */
+       };
+       struct init_chipset_guestpart init_chipset;
+
+};
+
+#ifndef __xg
+#define __xg(x) ((volatile long *)(x))
+#endif
+
+/*
+*  Below code is a copy of Linux kernel's cmpxchg function located at
+*  this place
+*  http://tcsxeon:8080/source/xref/00trunk-AppOS-linux/include/asm-x86/cmpxchg_64.h#84
+*  Reason for creating our own version of cmpxchg along with
+*  UISLIB_LOCK_PREFIX is to make the operation atomic even for non SMP
+*  guests.
+*/
+
+static inline unsigned long
+uislibcmpxchg64(volatile void *ptr, unsigned long old, unsigned long new,
+               int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+             __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgb %b1,%2":"=a"(prev)
+             :              "q"(new), "m"(*__xg(ptr)),
+                                    "0"(old)
+             :              "memory");
+               return prev;
+       case 2:
+             __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgw %w1,%2":"=a"(prev)
+             :              "r"(new), "m"(*__xg(ptr)),
+                                    "0"(old)
+             :              "memory");
+               return prev;
+       case 4:
+             __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgl %k1,%2":"=a"(prev)
+             :              "r"(new), "m"(*__xg(ptr)),
+                                    "0"(old)
+             :              "memory");
+               return prev;
+       case 8:
+             __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgq %1,%2":"=a"(prev)
+             :              "r"(new), "m"(*__xg(ptr)),
+                                    "0"(old)
+             :              "memory");
+               return prev;
+       }
+       return old;
+}
+
+#endif                         /* __UISQUEUE_H__ */
diff --git a/drivers/staging/unisys/include/uisthread.h b/drivers/staging/unisys/include/uisthread.h
new file mode 100644 (file)
index 0000000..2b1fba7
--- /dev/null
@@ -0,0 +1,46 @@
+/* uisthread.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*****************************************************************************/
+/* Unisys thread utilities header                                            */
+/*****************************************************************************/
+
+
+#ifndef __UISTHREAD_H__
+#define __UISTHREAD_H__
+
+
+#include "linux/completion.h"
+
+struct uisthread_info {
+       struct task_struct *task;
+       int id;
+       int should_stop;
+       struct completion has_stopped;
+};
+
+
+/* returns 0 for failure, 1 for success */
+int uisthread_start(
+       struct uisthread_info *thrinfo,
+       int (*threadfn)(void *),
+       void *thrcontext,
+       char *name);
+
+void uisthread_stop(struct uisthread_info *thrinfo);
+
+#endif /* __UISTHREAD_H__ */
diff --git a/drivers/staging/unisys/include/uisutils.h b/drivers/staging/unisys/include/uisutils.h
new file mode 100644 (file)
index 0000000..9fee353
--- /dev/null
@@ -0,0 +1,359 @@
+/* uisutils.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys Virtual HBA utilities header
+ */
+
+#ifndef __UISUTILS__H__
+#define __UISUTILS__H__
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/gfp.h>
+
+#include "vmcallinterface.h"
+#include "channel.h"
+#include "uisthread.h"
+#include "uisqueue.h"
+#include "diagnostics/appos_subsystems.h"
+#include "vbusdeviceinfo.h"
+#include <linux/atomic.h>
+
+/* This is the MAGIC number stuffed by virthba in host->this_id. Used to
+ * identify virtual hbas.
+ */
+#define UIS_MAGIC_VHBA 707
+
+/* global function pointers that act as callback functions into
+ * uisnicmod, uissdmod, and virtpcimod
+ */
+extern int (*UisnicControlChanFunc)(struct io_msgs *);
+extern int (*UissdControlChanFunc)(struct io_msgs *);
+extern int (*VirtControlChanFunc)(struct guest_msgs *);
+
+/* Return values of above callback functions: */
+#define CCF_ERROR        0     /* completed and failed */
+#define CCF_OK           1     /* completed successfully */
+#define CCF_PENDING      2     /* operation still pending */
+extern atomic_t UisUtils_Registered_Services;
+
+typedef unsigned int MACARRAY[MAX_MACADDR_LEN];
+typedef struct ReqHandlerInfo_struct {
+       GUID switchTypeGuid;
+       int (*controlfunc)(struct io_msgs *);
+       unsigned long min_channel_bytes;
+       int (*Server_Channel_Ok)(unsigned long channelBytes);
+       int (*Server_Channel_Init)
+        (void *x, unsigned char *clientStr, U32 clientStrLen, U64 bytes);
+       char switch_type_name[99];
+       struct list_head list_link;     /* links into ReqHandlerInfo_list */
+} ReqHandlerInfo_t;
+
+ReqHandlerInfo_t *ReqHandlerAdd(GUID switchTypeGuid,
+                               const char *switch_type_name,
+                               int (*controlfunc)(struct io_msgs *),
+                               unsigned long min_channel_bytes,
+                               int (*Server_Channel_Ok)(unsigned long
+                                                        channelBytes),
+                               int (*Server_Channel_Init)
+                                (void *x, unsigned char *clientStr,
+                                 U32 clientStrLen, U64 bytes));
+ReqHandlerInfo_t *ReqHandlerFind(GUID switchTypeGuid);
+int ReqHandlerDel(GUID switchTypeGuid);
+
+#define uislib_ioremap_cache(addr, size) \
+       dbg_ioremap_cache(addr, size, __FILE__, __LINE__)
+
+static inline void *
+dbg_ioremap_cache(U64 addr, unsigned long size, char *file, int line)
+{
+       void *new;
+       new = ioremap_cache(addr, size);
+       return new;
+}
+
+#define uislib_ioremap(addr, size) dbg_ioremap(addr, size, __FILE__, __LINE__)
+
+static inline void *
+dbg_ioremap(U64 addr, unsigned long size, char *file, int line)
+{
+       void *new;
+       new = ioremap(addr, size);
+       return new;
+}
+
+#define uislib_iounmap(addr) dbg_iounmap(addr, __FILE__, __LINE__)
+
+static inline void
+dbg_iounmap(void *addr, char *file, int line)
+{
+       iounmap(addr);
+}
+
+#define PROC_READ_BUFFER_SIZE 131072   /* size of the buffer to allocate to
+                                        * hold all of /proc/XXX/info */
+int util_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
+                         char *format, ...);
+
+int uisctrl_register_req_handler(int type, void *fptr,
+                                ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo);
+int uisctrl_register_req_handler_ex(GUID switchTypeGuid,
+                                   const char *switch_type_name,
+                                   int (*fptr)(struct io_msgs *),
+                                   unsigned long min_channel_bytes,
+                                   int (*Server_Channel_Ok)(unsigned long
+                                                            channelBytes),
+                                   int (*Server_Channel_Init)
+                                   (void *x, unsigned char *clientStr,
+                                    U32 clientStrLen, U64 bytes),
+                                   ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo);
+
+int uisctrl_unregister_req_handler_ex(GUID switchTypeGuid);
+unsigned char *util_map_virt(struct phys_info *sg);
+void util_unmap_virt(struct phys_info *sg);
+unsigned char *util_map_virt_atomic(struct phys_info *sg);
+void util_unmap_virt_atomic(void *buf);
+int uislib_server_inject_add_vnic(U32 switchNo, U32 BusNo, U32 numIntPorts,
+                                 U32 numExtPorts, MACARRAY pmac[],
+                                 pCHANNEL_HEADER **chan);
+void uislib_server_inject_del_vnic(U32 switchNo, U32 busNo, U32 numIntPorts,
+                                  U32 numExtPorts);
+int uislib_client_inject_add_bus(U32 busNo, GUID instGuid,
+                                U64 channelAddr, ulong nChannelBytes);
+int  uislib_client_inject_del_bus(U32 busNo);
+
+int uislib_client_inject_add_vhba(U32 busNo, U32 devNo,
+                                 U64 phys_chan_addr, U32 chan_bytes,
+                                 int is_test_addr, GUID instGuid,
+                                 struct InterruptInfo *intr);
+int  uislib_client_inject_pause_vhba(U32 busNo, U32 devNo);
+int  uislib_client_inject_resume_vhba(U32 busNo, U32 devNo);
+int uislib_client_inject_del_vhba(U32 busNo, U32 devNo);
+int uislib_client_inject_add_vnic(U32 busNo, U32 devNo,
+                                 U64 phys_chan_addr, U32 chan_bytes,
+                                 int is_test_addr, GUID instGuid,
+                                 struct InterruptInfo *intr);
+int uislib_client_inject_pause_vnic(U32 busNo, U32 devNo);
+int uislib_client_inject_resume_vnic(U32 busNo, U32 devNo);
+int uislib_client_inject_del_vnic(U32 busNo, U32 devNo);
+#ifdef STORAGE_CHANNEL
+U64 uislib_storage_channel(int client_id);
+#endif
+int uislib_get_owned_pdest(struct uisscsi_dest *pdest);
+
+int uislib_send_event(CONTROLVM_ID id, CONTROLVM_MESSAGE_PACKET *event);
+
+/* structure used by vhba & vnic to keep track of queue & thread info */
+struct chaninfo {
+       struct uisqueue_info *queueinfo;
+       /* this specifies the queue structures for a channel */
+       /* ALLOCATED BY THE OTHER END - WE JUST GET A POINTER TO THE MEMORY */
+       spinlock_t insertlock;
+       /* currently used only in virtnic when sending data to uisnic */
+       /* to synchronize the inserts into the signal queue */
+       struct uisthread_info threadinfo;
+       /* this specifies the thread structures used by the thread that */
+       /* handles this channel */
+};
+
+/* this is the wait code for all the threads - it is used to get
+* something from a queue choices: wait_for_completion_interruptible,
+* _timeout, interruptible_timeout
+*/
+#define UIS_THREAD_WAIT_MSEC(x) { \
+       set_current_state(TASK_INTERRUPTIBLE); \
+       schedule_timeout(msecs_to_jiffies(x)); \
+}
+#define UIS_THREAD_WAIT_USEC(x) { \
+       set_current_state(TASK_INTERRUPTIBLE); \
+       schedule_timeout(usecs_to_jiffies(x)); \
+}
+#define UIS_THREAD_WAIT UIS_THREAD_WAIT_MSEC(5)
+#define UIS_THREAD_WAIT_SEC(x) { \
+       set_current_state(TASK_INTERRUPTIBLE); \
+       schedule_timeout((x)*HZ); \
+}
+
+#define ALLOC_CMDRSP(cmdrsp) { \
+       cmdrsp = kmalloc(SIZEOF_CMDRSP, GFP_ATOMIC); \
+       if (cmdrsp != NULL) { \
+               memset(cmdrsp, 0, SIZEOF_CMDRSP); \
+       } \
+}
+
+/* This is a hack until we fix IOVM to initialize the channel header
+ * correctly at DEVICE_CREATE time, INSTEAD OF waiting until
+ * DEVICE_CONFIGURE time.
+ */
+#define WAIT_FOR_VALID_GUID(guid) \
+       do {                                               \
+               while (memcmp(&guid, &Guid0, sizeof(Guid0)) == 0) {     \
+                       LOGERR("Waiting for non-0 GUID (why???)...\n"); \
+                       UIS_THREAD_WAIT_SEC(5);                         \
+               }                                                       \
+               LOGERR("OK... GUID is non-0 now\n");                    \
+       } while (0)
+
+/* CopyFragsInfoFromSkb returns the number of entries added to frags array
+ * Returns -1 on failure.
+ */
+unsigned int util_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
+                             void *skb_in, unsigned int firstfraglen,
+                             unsigned int frags_max, struct phys_info frags[]);
+
+static inline unsigned int
+Issue_VMCALL_IO_CONTROLVM_ADDR(U64 *ControlAddress, U32 *ControlBytes)
+{
+       VMCALL_IO_CONTROLVM_ADDR_PARAMS params;
+       int result = VMCALL_SUCCESS;
+       U64 physaddr;
+
+       physaddr = virt_to_phys(&params);
+       ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result);
+       if (VMCALL_SUCCESSFUL(result)) {
+               *ControlAddress = params.ChannelAddress;
+               *ControlBytes = params.ChannelBytes;
+       }
+       return result;
+}
+
+static inline unsigned int Issue_VMCALL_IO_DIAG_ADDR(U64 *DiagChannelAddress)
+{
+       VMCALL_IO_DIAG_ADDR_PARAMS params;
+       int result = VMCALL_SUCCESS;
+       U64 physaddr;
+
+       physaddr = virt_to_phys(&params);
+       ISSUE_IO_VMCALL(VMCALL_IO_DIAG_ADDR, physaddr, result);
+       if (VMCALL_SUCCESSFUL(result))
+               *DiagChannelAddress = params.ChannelAddress;
+       return result;
+}
+
+static inline unsigned int
+Issue_VMCALL_IO_VISORSERIAL_ADDR(U64 *DiagChannelAddress)
+{
+       VMCALL_IO_VISORSERIAL_ADDR_PARAMS params;
+       int result = VMCALL_SUCCESS;
+       U64 physaddr;
+
+       physaddr = virt_to_phys(&params);
+       ISSUE_IO_VMCALL(VMCALL_IO_VISORSERIAL_ADDR, physaddr, result);
+       if (VMCALL_SUCCESSFUL(result))
+               *DiagChannelAddress = params.ChannelAddress;
+       return result;
+}
+
+static inline S64 Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET(void)
+{
+       U64 result = VMCALL_SUCCESS;
+       U64 physaddr = 0;
+
+       ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr,
+                       result);
+       return result;
+}
+
+static inline S64 Issue_VMCALL_MEASUREMENT_DO_NOTHING(void)
+{
+       U64 result = VMCALL_SUCCESS;
+       U64 physaddr = 0;
+
+       ISSUE_IO_VMCALL(VMCALL_MEASUREMENT_DO_NOTHING, physaddr, result);
+       return result;
+}
+
+struct log_info_t {
+       volatile unsigned long long last_cycles;
+       unsigned long long delta_sum[64];
+       unsigned long long delta_cnt[64];
+       unsigned long long max_delta[64];
+       unsigned long long min_delta[64];
+};
+
+static inline int Issue_VMCALL_UPDATE_PHYSICAL_TIME(U64 adjustment)
+{
+       int result = VMCALL_SUCCESS;
+
+       ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
+       return result;
+}
+
+static inline unsigned int
+Issue_VMCALL_CHANNEL_MISMATCH(const char *ChannelName,
+                             const char *ItemName,
+                             U32 SourceLineNumber, const char *path_n_fn)
+{
+       VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS params;
+       int result = VMCALL_SUCCESS;
+       U64 physaddr;
+       char *last_slash = NULL;
+
+       strncpy(params.ChannelName, ChannelName,
+               lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ChannelName));
+       strncpy(params.ItemName, ItemName,
+               lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ItemName));
+       params.SourceLineNumber = SourceLineNumber;
+
+       last_slash = strrchr(path_n_fn, '/');
+       if (last_slash != NULL) {
+               last_slash++;
+               strncpy(params.SourceFileName, last_slash,
+                       lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS,
+                                SourceFileName));
+       } else
+               strncpy(params.SourceFileName,
+                       "Cannot determine source filename",
+                       lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS,
+                                SourceFileName));
+
+       physaddr = virt_to_phys(&params);
+       ISSUE_IO_VMCALL(VMCALL_CHANNEL_VERSION_MISMATCH, physaddr, result);
+       return result;
+}
+
+static inline unsigned int Issue_VMCALL_FATAL_BYE_BYE(void)
+{
+       int result = VMCALL_SUCCESS;
+       U64 physaddr = 0;
+
+       ISSUE_IO_VMCALL(VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER, physaddr,
+                       result);
+       return result;
+}
+
+#define UIS_DAEMONIZE(nam)
+void *uislib_malloc(size_t siz, gfp_t gfp, U8 contiguous, char *fn, int ln);
+#define UISMALLOC(siz, gfp) uislib_malloc(siz, gfp, 1, __FILE__, __LINE__)
+#define UISVMALLOC(siz) uislib_malloc(siz, 0, 0, __FILE__, __LINE__)
+void uislib_free(void *p, size_t siz, U8 contiguous, char *fn, int ln);
+#define UISFREE(p, siz) uislib_free(p, siz, 1, __FILE__, __LINE__)
+#define UISVFREE(p, siz) uislib_free(p, siz, 0, __FILE__, __LINE__)
+void *uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln);
+#define UISCACHEALLOC(cur_pool) uislib_cache_alloc(cur_pool, __FILE__, __LINE__)
+void uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln);
+#define UISCACHEFREE(cur_pool, p) \
+       uislib_cache_free(cur_pool, p, __FILE__, __LINE__)
+
+void uislib_enable_channel_interrupts(U32 busNo, U32 devNo,
+                                     int (*interrupt)(void *),
+                                     void *interrupt_context);
+void uislib_disable_channel_interrupts(U32 busNo, U32 devNo);
+void uislib_force_channel_interrupt(U32 busNo, U32 devNo);
+
+#endif /* __UISUTILS__H__ */
diff --git a/drivers/staging/unisys/include/uniklog.h b/drivers/staging/unisys/include/uniklog.h
new file mode 100644 (file)
index 0000000..4d7b87c
--- /dev/null
@@ -0,0 +1,193 @@
+/* uniklog.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This module contains macros to aid developers in logging messages.
+ *
+ * This module is affected by the DEBUG compiletime option.
+ *
+ */
+#ifndef __UNIKLOG_H__
+#define __UNIKLOG_H__
+
+
+#include <linux/printk.h>
+
+/*
+ * # DBGINF
+ *
+ * \brief Log debug informational message - log a LOG_INFO message only
+ *        if DEBUG compiletime option enabled
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Log a message at the LOG_INFO level, but only if DEBUG is enabled.  If
+ * DEBUG is disabled, this expands to a no-op.
+ */
+
+/*
+ * # DBGVER
+ *
+ * \brief Log debug verbose message - log a LOG_DEBUG message only if
+ *        DEBUG compiletime option enabled
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Log a message at the LOG_DEBUG level, but only if DEBUG is enabled.  If
+ * DEBUG is disabled, this expands to a no-op.  Note also that LOG_DEBUG
+ * messages can be enabled/disabled at runtime as well.
+ */
+#define DBGINFDEV(devname, fmt, args...)        do { } while (0)
+#define DBGVERDEV(devname, fmt, args...)        do { } while (0)
+#define DBGINF(fmt, args...)                    do { } while (0)
+#define DBGVER(fmt, args...)                    do { } while (0)
+
+/*
+ * # LOGINF
+ *
+ * \brief Log informational message - logs a message at the LOG_INFO level
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Logs the specified message at the LOG_INFO level.
+ */
+
+#define LOGINF(fmt, args...) pr_info(fmt, ## args)
+#define LOGINFDEV(devname, fmt, args...) \
+       pr_info("%s " fmt, devname, ## args)
+#define LOGINFDEVX(devno, fmt, args...) \
+       pr_info("dev%d " fmt, devno, ## args)
+#define LOGINFNAME(vnic, fmt, args...)                         \
+       do {                                                            \
+               if (vnic != NULL) {                                     \
+                       pr_info("%s " fmt, vnic->name, ## args);        \
+               } else {                                                \
+                       pr_info(fmt, ## args);                          \
+               }                                                       \
+       } while (0)
+
+/*
+ * # LOGVER
+ *
+ * \brief Log verbose message - logs a message at the LOG_DEBUG level,
+ *        which can be disabled at runtime
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified message at the LOG_DEBUG level.  Note also that
+ * LOG_DEBUG messages can be enabled/disabled at runtime as well.
+ */
+#define LOGVER(fmt, args...) pr_debug(fmt, ## args)
+#define LOGVERDEV(devname, fmt, args...) \
+       pr_debug("%s " fmt, devname, ## args)
+#define LOGVERNAME(vnic, fmt, args...)                                 \
+       do {                                                            \
+               if (vnic != NULL) {                                     \
+                       pr_debug("%s " fmt, vnic->name, ## args);       \
+               } else {                                                \
+                       pr_debug(fmt, ## args);                         \
+               }                                                       \
+       } while (0)
+
+
+/*
+ * # LOGERR
+ *
+ * \brief Log error message - logs a message at the LOG_ERR level,
+ *        including source line number information
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified error message at the LOG_ERR level.  It will also
+ * include the file, line number, and function name of where the error
+ * originated in the log message.
+ */
+#define LOGERR(fmt, args...) pr_err(fmt, ## args)
+#define LOGERRDEV(devname, fmt, args...) \
+       pr_err("%s " fmt, devname, ## args)
+#define LOGERRDEVX(devno, fmt, args...) \
+       pr_err("dev%d " fmt, devno, ## args)
+#define LOGERRNAME(vnic, fmt, args...)                         \
+       do {                                                            \
+               if (vnic != NULL) {                                     \
+                       pr_err("%s " fmt, vnic->name, ## args); \
+               } else {                                                \
+                       pr_err(fmt, ## args);                           \
+               }                                                       \
+       } while (0)
+#define LOGORDUMPERR(seqfile, fmt, args...) do {               \
+               if (seqfile) {                                  \
+                       seq_printf(seqfile, fmt, ## args);      \
+               } else {                                        \
+                       LOGERR(fmt, ## args);                   \
+               }                                               \
+       } while (0)
+
+/*
+ * # LOGWRN
+ *
+ * \brief Log warning message - Logs a message at the LOG_WARNING level,
+ *        including source line number information
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified error message at the LOG_WARNING level.  It will also
+ * include the file, line number, and function name of where the error
+ * originated in the log message.
+ */
+#define LOGWRN(fmt, args...) pr_warn(fmt, ## args)
+#define LOGWRNDEV(devname, fmt, args...) \
+       pr_warn("%s " fmt, devname, ## args)
+#define LOGWRNNAME(vnic, fmt, args...) \
+       do {                                                            \
+               if (vnic != NULL) {                                     \
+                       pr_warn("%s " fmt, vnic->name, ## args);        \
+               } else {                                                \
+                       pr_warn(fmt, ## args);                          \
+               }                                                       \
+       } while (0)
+
+#endif /* __UNIKLOG_H__ */
diff --git a/drivers/staging/unisys/include/vbushelper.h b/drivers/staging/unisys/include/vbushelper.h
new file mode 100644 (file)
index 0000000..93e35f0
--- /dev/null
@@ -0,0 +1,47 @@
+/* vbushelper.h
+ *
+ * Copyright Â© 2011 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VBUSHELPER_H__
+#define __VBUSHELPER_H__
+
+#include "vbusdeviceinfo.h"
+
+/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
+ * command line */
+
+#define TARGET_HOSTNAME "linuxguest"
+
+static inline void
+BusDeviceInfo_Init(ULTRA_VBUS_DEVICEINFO *pBusDeviceInfo,
+                  const char *deviceType, const char *driverName,
+                  const char *ver, const char *verTag,
+                  const char *buildDate, const char *buildTime)
+{
+       memset(pBusDeviceInfo, 0, sizeof(ULTRA_VBUS_DEVICEINFO));
+       snprintf(pBusDeviceInfo->devType, sizeof(pBusDeviceInfo->devType),
+                "%s", (deviceType) ? deviceType : "unknownType");
+       snprintf(pBusDeviceInfo->drvName, sizeof(pBusDeviceInfo->drvName),
+                "%s", (driverName) ? driverName : "unknownDriver");
+       snprintf(pBusDeviceInfo->infoStrings,
+                sizeof(pBusDeviceInfo->infoStrings), "%s\t%s\t%s %s\t%s",
+                (ver) ? ver : "unknownVer",
+                (verTag) ? verTag : "unknownVerTag",
+                (buildDate) ? buildDate : "noBuildDate",
+                (buildTime) ? buildTime : "nobuildTime", TARGET_HOSTNAME);
+}
+
+#endif
diff --git a/drivers/staging/unisys/uislib/Kconfig b/drivers/staging/unisys/uislib/Kconfig
new file mode 100644 (file)
index 0000000..8d87d9c
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys uislib configuration
+#
+
+config UNISYS_UISLIB
+       tristate "Unisys uislib driver"
+       depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB
+       ---help---
+       If you say Y here, you will enable the Unisys uislib driver.
+
diff --git a/drivers/staging/unisys/uislib/Makefile b/drivers/staging/unisys/uislib/Makefile
new file mode 100644 (file)
index 0000000..6e44d49
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Makefile for Unisys uislib
+#
+
+obj-$(CONFIG_UNISYS_UISLIB)    += visoruislib.o
+
+visoruislib-y := uislib.o uisqueue.o  uisthread.o  uisutils.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/channels
+ccflags-y += -Idrivers/staging/unisys/visorchipset
+ccflags-y += -Idrivers/staging/unisys/sparstopdriver
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c
new file mode 100644 (file)
index 0000000..a004c9d
--- /dev/null
@@ -0,0 +1,2536 @@
+/* uislib.c
+ *
+ * Copyright ï¿½ 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* @ALL_INSPECTED */
+#define EXPORT_SYMTAB
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+
+#include "commontypes.h"
+
+#include <linux/version.h>
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "uisutils.h"
+#include "vbuschannel.h"
+
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>     /* for copy_from_user */
+#include <linux/ctype.h>       /* for toupper */
+#include <linux/list.h>
+
+#include "sparstop.h"
+#include "visorchipset.h"
+#include "chanstub.h"
+#include "version.h"
+#include "guestlinuxdebug.h"
+
+#define SET_PROC_OWNER(x, y)
+
+#define UISLIB_TEST_PROC
+#define POLLJIFFIES_NORMAL 1
+/* Choose whether or not you want to wakeup the request-polling thread
+ * after an IO termination:
+ * this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC UISLIB_PC_uislib_c
+#define __MYFILE__ "uislib.c"
+
+/* global function pointers that act as callback functions into virtpcimod */
+int (*VirtControlChanFunc)(struct guest_msgs *);
+
+static int ProcReadBufferValid;
+static char *ProcReadBuffer;   /* Note this MUST be global,
+                                        * because the contents must */
+static unsigned int chipset_inited;
+int callback_count = 0;
+#define WAIT_ON_CALLBACK(handle)       \
+       do {                    \
+               if (handle)             \
+                       break;          \
+               UIS_THREAD_WAIT;        \
+       } while (1)
+
+static struct bus_info *BusListHead;
+static rwlock_t BusListLock;
+static int BusListCount;       /* number of buses in the list */
+static int MaxBusCount;                /* maximum number of buses expected */
+static U64 PhysicalDataChan;
+static int PlatformNumber;
+
+/* This is a list of controlvm messages which could not complete
+ * immediately, but instead must be occasionally retried until they
+ * ultimately succeed/fail.  When this happens,
+ * msg->hdr.Flags.responseExpected determines whether or not we will
+ * send a controlvm response.
+ */
+struct controlvm_retry_entry {
+       CONTROLVM_MESSAGE msg;
+       struct io_msgs cmd;
+       void *obj;
+       int (*controlChanFunc)(struct io_msgs *);
+       struct list_head list_link;
+};
+LIST_HEAD(ControlVmRetryQHead);
+
+static struct uisthread_info Incoming_ThreadInfo;
+static BOOL Incoming_Thread_Started = FALSE;
+LIST_HEAD(List_Polling_Device_Channels);
+unsigned long long tot_moved_to_tail_cnt = 0;
+unsigned long long tot_wait_cnt = 0;
+unsigned long long tot_wakeup_cnt = 0;
+unsigned long long tot_schedule_cnt = 0;
+int en_smart_wakeup = 1;
+static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels); /* unlocked */
+DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels);
+static int Go_Polling_Device_Channels;
+
+static struct proc_dir_entry *uislib_proc_dir;
+static struct proc_dir_entry *uislib_proc_vbus_dir;
+static struct proc_dir_entry *vnic_proc_entry; /* Used to be "datachan" */
+static struct proc_dir_entry *ctrlchan_proc_entry;
+static struct proc_dir_entry *pmem_proc_entry;
+static struct proc_dir_entry *info_proc_entry;
+static struct proc_dir_entry *switch_proc_entry;
+static struct proc_dir_entry *extport_proc_entry;
+static struct proc_dir_entry *platformnumber_proc_entry;
+static struct proc_dir_entry *bus_proc_entry;
+static struct proc_dir_entry *dev_proc_entry;
+static struct proc_dir_entry *chipset_proc_entry;
+static struct proc_dir_entry *cycles_before_wait_proc_entry;
+static struct proc_dir_entry *reset_counts_proc_entry;
+static struct proc_dir_entry *smart_wakeup_proc_entry;
+static struct proc_dir_entry *disable_proc_entry;
+
+#define DIR_PROC_ENTRY "uislib"
+#define DIR_VBUS_PROC_ENTRY "vbus"
+#define VNIC_PROC_ENTRY_FN "vnic"      /* Used to be "datachan" */
+#define CTRLCHAN_PROC_ENTRY_FN "ctrlchan"
+#define PMEM_PROC_ENTRY_FN "phys_to_virt"
+#define INFO_PROC_ENTRY_FN "info"
+#define SWITCH_PROC_ENTRY_FN "switch"
+#define SWITCH_COUNT_PROC_ENTRY_FN "switch_count"
+#define EXTPORT_PROC_ENTRY_FN "extport"
+#define PLATFORMNUMBER_PROC_ENTRY_FN "platform"
+#define BUS_PROC_ENTRY_FN "bus"
+#define DEV_PROC_ENTRY_FN "device"
+#define CHIPSET_PROC_ENTRY_FN "chipset"
+#define CYCLES_BEFORE_WAIT_PROC_ENTRY_FN "cycles_before_wait"
+#define RESET_COUNTS_PROC_ENTRY_FN "reset_counts"
+#define SMART_WAKEUP_PROC_ENTRY_FN "smart_wakeup"
+#define CALLHOME_PROC_ENTRY_FN "callhome"
+#define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled"
+#define DISABLE_PROC_ENTRY_FN "switch_state"
+#ifdef UISLIB_TEST_PROC
+static struct proc_dir_entry *test_proc_entry;
+#define TEST_PROC_ENTRY_FN "test"
+#endif
+unsigned long long cycles_before_wait, wait_cycles;
+
+/*****************************************************/
+/* local functions                                   */
+/*****************************************************/
+
+static int proc_info_vbus_show(struct seq_file *m, void *v);
+static int
+proc_info_vbus_open(struct inode *inode, struct file *filp)
+{
+       /* proc_info_vbus_show will grab this from seq_file.private: */
+       struct bus_info *bus = PDE_DATA(inode);
+       return single_open(filp, proc_info_vbus_show, bus);
+}
+
+static const struct file_operations proc_info_vbus_fops = {
+       .open = proc_info_vbus_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static ssize_t uislib_proc_read_writeonly(struct file *file,
+                                         char __user *buffer,
+                                         size_t count, loff_t *ppos);
+
+static ssize_t vnic_proc_write(struct file *file, const char __user *buffer,
+                              size_t count, loff_t *ppos);
+
+static const struct file_operations proc_vnic_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = vnic_proc_write,
+};
+
+static ssize_t chipset_proc_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *ppos);
+
+static const struct file_operations proc_chipset_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = chipset_proc_write,
+};
+
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+                             size_t len, loff_t *offset);
+static const struct file_operations proc_info_fops = {
+       .read = info_proc_read,
+};
+
+static ssize_t platformnumber_proc_read(struct file *file, char __user *buf,
+                                       size_t len, loff_t *offset);
+static const struct file_operations proc_platformnumber_fops = {
+       .read = platformnumber_proc_read,
+};
+
+static ssize_t cycles_before_wait_proc_write(struct file *file,
+                                            const char __user *buffer,
+                                            size_t count, loff_t *ppos);
+static const struct file_operations proc_cycles_before_wait_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = cycles_before_wait_proc_write,
+};
+
+static ssize_t reset_counts_proc_write(struct file *file,
+                                      const char __user *buffer,
+                                      size_t count, loff_t *ppos);
+static const struct file_operations proc_reset_counts_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = reset_counts_proc_write,
+};
+
+static ssize_t smart_wakeup_proc_write(struct file *file,
+                                      const char __user *buffer,
+                                      size_t count, loff_t *ppos);
+static const struct file_operations proc_smart_wakeup_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = smart_wakeup_proc_write,
+};
+
+static ssize_t test_proc_write(struct file *file,
+                              const char __user *buffer,
+                              size_t count, loff_t *ppos);
+static const struct file_operations proc_test_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = test_proc_write,
+};
+
+static ssize_t bus_proc_write(struct file *file,
+                             const char __user *buffer,
+                             size_t count, loff_t *ppos);
+static const struct file_operations proc_bus_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = bus_proc_write,
+};
+
+static ssize_t dev_proc_write(struct file *file,
+                             const char __user *buffer,
+                             size_t count, loff_t *ppos);
+static const struct file_operations proc_dev_fops = {
+       .read = uislib_proc_read_writeonly,
+       .write = dev_proc_write,
+};
+
+static void
+init_msg_header(CONTROLVM_MESSAGE *msg, U32 id, uint rsp, uint svr)
+{
+       memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
+       msg->hdr.Id = id;
+       msg->hdr.Flags.responseExpected = rsp;
+       msg->hdr.Flags.server = svr;
+}
+
+static void
+create_bus_proc_entries(struct bus_info *bus)
+{
+       bus->proc_dir = proc_mkdir(bus->name, uislib_proc_vbus_dir);
+       if (!bus->proc_dir) {
+               LOGERR("failed to create /proc/uislib/vbus/%s directory",
+                      bus->name);
+               return;
+       }
+       bus->proc_info = proc_create_data("info", 0, bus->proc_dir,
+                                         &proc_info_vbus_fops, bus);
+       if (!bus->proc_info) {
+               LOGERR("failed to create /proc/uislib/vbus/%s/info", bus->name);
+               remove_proc_entry(bus->name, uislib_proc_vbus_dir);
+               bus->proc_dir = NULL;
+               return;
+       }
+       SET_PROC_OWNER(bus->proc_info, THIS_MODULE);
+
+}
+
+static void *
+init_vbus_channel(U64 channelAddr, U32 channelBytes, int isServer)
+{
+       void *rc = NULL;
+       void *pChan = uislib_ioremap_cache(channelAddr, channelBytes);
+       if (!pChan) {
+               LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
+                    (unsigned long long) channelAddr,
+                    (unsigned long long) channelBytes);
+               RETPTR(NULL);
+       }
+       if (isServer) {
+               memset(pChan, 0, channelBytes);
+               if (!ULTRA_VBUS_CHANNEL_OK_SERVER(channelBytes, NULL)) {
+                       ERRDRV("%s channel cannot be used", __func__);
+                       uislib_iounmap(pChan);
+                       RETPTR(NULL);
+               }
+               ULTRA_VBUS_init_channel(pChan, channelBytes);
+       } else {
+               if (!ULTRA_VBUS_CHANNEL_OK_CLIENT(pChan, NULL)) {
+                       ERRDRV("%s channel cannot be used", __func__);
+                       uislib_iounmap(pChan);
+                       RETPTR(NULL);
+               }
+       }
+       RETPTR(pChan);
+Away:
+       return rc;
+}
+
+static int
+create_bus(CONTROLVM_MESSAGE *msg, char *buf)
+{
+       U32 busNo, deviceCount;
+       struct bus_info *tmp, *bus;
+       size_t size;
+
+       if (MaxBusCount == BusListCount) {
+               LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n",
+                    MaxBusCount);
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount,
+                                POSTCODE_SEVERITY_ERR);
+               return CONTROLVM_RESP_ERROR_MAX_BUSES;
+       }
+
+       busNo = msg->cmd.createBus.busNo;
+       deviceCount = msg->cmd.createBus.deviceCount;
+
+       POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount,
+                        POSTCODE_SEVERITY_INFO);
+
+       size =
+           sizeof(struct bus_info) +
+           (deviceCount * sizeof(struct device_info *));
+       bus = UISMALLOC(size, GFP_ATOMIC);
+       if (!bus) {
+               LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n");
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+       }
+
+       memset(bus, 0, size);
+
+       /* Currently by default, the bus Number is the GuestHandle.
+        * Configure Bus message can override this.
+        */
+       if (msg->hdr.Flags.testMessage) {
+               /* This implies we're the IOVM so set guest handle to 0... */
+               bus->guestHandle = 0;
+               bus->busNo = busNo;
+               bus->localVnic = 1;
+       } else
+               bus->busNo = bus->guestHandle = busNo;
+       sprintf(bus->name, "%d", (int) bus->busNo);
+       bus->deviceCount = deviceCount;
+       bus->device =
+           (struct device_info **) ((char *) bus + sizeof(struct bus_info));
+       bus->busInstGuid = msg->cmd.createBus.busInstGuid;
+       bus->busChannelBytes = 0;
+       bus->pBusChannel = NULL;
+
+       /* add bus to our bus list - but check for duplicates first */
+       read_lock(&BusListLock);
+       for (tmp = BusListHead; tmp; tmp = tmp->next) {
+               if (tmp->busNo == bus->busNo)
+                       break;
+       }
+       read_unlock(&BusListLock);
+       if (tmp) {
+               /* found a bus already in the list with same busNo -
+                * reject add
+                */
+               LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n",
+                      bus->busNo);
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
+                                POSTCODE_SEVERITY_ERR);
+               UISFREE(bus, size);
+               return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+       }
+       if ((msg->cmd.createBus.channelAddr != 0)
+           && (msg->cmd.createBus.channelBytes != 0)) {
+               bus->busChannelBytes = msg->cmd.createBus.channelBytes;
+               bus->pBusChannel =
+                   init_vbus_channel(msg->cmd.createBus.channelAddr,
+                                     msg->cmd.createBus.channelBytes,
+                                     msg->hdr.Flags.server);
+       }
+       /* the msg is bound for virtpci; send guest_msgs struct to callback */
+       if (!msg->hdr.Flags.server) {
+               struct guest_msgs cmd;
+               cmd.msgtype = GUEST_ADD_VBUS;
+               cmd.add_vbus.busNo = busNo;
+               cmd.add_vbus.chanptr = bus->pBusChannel;
+               cmd.add_vbus.deviceCount = deviceCount;
+               cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
+               cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
+               if (!VirtControlChanFunc) {
+                       UISFREE(bus, size);
+                       LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
+                       POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
+                                        POSTCODE_SEVERITY_ERR);
+                       return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+               }
+               if (!VirtControlChanFunc(&cmd)) {
+                       UISFREE(bus, size);
+                       LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
+                       POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
+                                        POSTCODE_SEVERITY_ERR);
+                       return
+                           CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+               }
+       }
+       create_bus_proc_entries(bus);
+
+       /* add bus at the head of our list */
+       write_lock(&BusListLock);
+       if (!BusListHead)
+               BusListHead = bus;
+       else {
+               bus->next = BusListHead;
+               BusListHead = bus;
+       }
+       BusListCount++;
+       write_unlock(&BusListLock);
+
+       POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->busNo,
+                        POSTCODE_SEVERITY_INFO);
+       return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
+{
+       int i;
+       struct bus_info *bus, *prev = NULL;
+       U32 busNo;
+
+       busNo = msg->cmd.destroyBus.busNo;
+
+       /* find and delete the bus */
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; prev = bus, bus = bus->next) {
+               if (bus->busNo == busNo) {
+                       /* found the bus - ensure that all device
+                        * slots are NULL
+                        */
+                       for (i = 0; i < bus->deviceCount; i++) {
+                               if (bus->device[i] != NULL) {
+                                       LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
+                                            i, busNo);
+                                       read_unlock(&BusListLock);
+                                       return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
+                               }
+                       }
+                       read_unlock(&BusListLock);
+                       /* the msg is bound for virtpci; send
+                        * guest_msgs struct to callback
+                        */
+                       if (!msg->hdr.Flags.server) {
+                               struct guest_msgs cmd;
+                               cmd.msgtype = GUEST_DEL_VBUS;
+                               cmd.del_vbus.busNo = busNo;
+                               if (!VirtControlChanFunc) {
+                                       LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
+                                       return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+                               }
+                               if (!VirtControlChanFunc(&cmd)) {
+                                       LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
+                                       return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+                               }
+                       }
+                       /* remove the bus from the list */
+                       write_lock(&BusListLock);
+                       if (prev)       /* not at head */
+                               prev->next = bus->next;
+                       else
+                               BusListHead = bus->next;
+                       BusListCount--;
+                       write_unlock(&BusListLock);
+                       break;
+               }
+       }
+
+       if (!bus) {
+               LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n",
+                      busNo);
+               read_unlock(&BusListLock);
+               return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+       }
+       if (bus->proc_info) {
+               remove_proc_entry("info", bus->proc_dir);
+               bus->proc_info = NULL;
+       }
+       if (bus->proc_dir) {
+               remove_proc_entry(bus->name, uislib_proc_vbus_dir);
+               bus->proc_dir = NULL;
+       }
+       if (bus->pBusChannel) {
+               uislib_iounmap(bus->pBusChannel);
+               bus->pBusChannel = NULL;
+       }
+
+       UISFREE(bus,
+               sizeof(struct bus_info) +
+               (bus->deviceCount * sizeof(struct device_info *)));
+       return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+create_device(CONTROLVM_MESSAGE *msg, char *buf)
+{
+       struct device_info *dev;
+       struct bus_info *bus;
+       U32 busNo, devNo;
+       int result = CONTROLVM_RESP_SUCCESS;
+       U64 minSize = MIN_IO_CHANNEL_SIZE;
+       ReqHandlerInfo_t *pReqHandler;
+
+       busNo = msg->cmd.createDevice.busNo;
+       devNo = msg->cmd.createDevice.devNo;
+
+       POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+
+       dev = UISMALLOC(sizeof(struct device_info), GFP_ATOMIC);
+       if (!dev) {
+               LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n");
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+       }
+
+       memset(dev, 0, sizeof(struct device_info));
+       dev->channelTypeGuid = msg->cmd.createDevice.dataTypeGuid;
+       dev->intr = msg->cmd.createDevice.intr;
+       dev->channelAddr = msg->cmd.createDevice.channelAddr;
+       dev->busNo = busNo;
+       dev->devNo = devNo;
+       sema_init(&dev->interrupt_callback_lock, 1);    /* unlocked */
+       sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo);
+       /* map the channel memory for the device. */
+       if (msg->hdr.Flags.testMessage)
+               dev->chanptr = __va(dev->channelAddr);
+       else {
+               pReqHandler = ReqHandlerFind(dev->channelTypeGuid);
+               if (pReqHandler)
+                       /* generic service handler registered for this
+                        * channel
+                        */
+                       minSize = pReqHandler->min_channel_bytes;
+               if (minSize > msg->cmd.createDevice.channelBytes) {
+                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx",
+                            (ulong) msg->cmd.createDevice.channelBytes,
+                            (ulong) minSize);
+                       POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                        POSTCODE_SEVERITY_ERR);
+                       result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL;
+                       goto Away;
+               }
+               dev->chanptr =
+                   uislib_ioremap_cache(dev->channelAddr,
+                                        msg->cmd.createDevice.channelBytes);
+               if (!dev->chanptr) {
+                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
+                            dev->channelAddr,
+                            msg->cmd.createDevice.channelBytes);
+                       result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
+                       POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                        POSTCODE_SEVERITY_ERR);
+                       goto Away;
+               }
+       }
+       dev->devInstGuid = msg->cmd.createDevice.devInstGuid;
+       dev->channelBytes = msg->cmd.createDevice.channelBytes;
+
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; bus = bus->next) {
+               if (bus->busNo == busNo) {
+                       /* make sure the device number is valid */
+                       if (devNo >= bus->deviceCount) {
+                               LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).",
+                                    devNo, bus->deviceCount);
+                               result = CONTROLVM_RESP_ERROR_MAX_DEVICES;
+                               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
+                                                devNo, busNo,
+                                                POSTCODE_SEVERITY_ERR);
+                               read_unlock(&BusListLock);
+                               goto Away;
+                       }
+                       /* make sure this device is not already set */
+                       if (bus->device[devNo]) {
+                               LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.",
+                                    devNo);
+                               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
+                                                devNo, busNo,
+                                                POSTCODE_SEVERITY_ERR);
+                               result = CONTROLVM_RESP_ERROR_ALREADY_DONE;
+                               read_unlock(&BusListLock);
+                               goto Away;
+                       }
+                       read_unlock(&BusListLock);
+                       /* the msg is bound for virtpci; send
+                        * guest_msgs struct to callback
+                        */
+                       if (!msg->hdr.Flags.server) {
+                               struct guest_msgs cmd;
+                               if (!memcmp
+                                   (&dev->channelTypeGuid,
+                                    &UltraVhbaChannelProtocolGuid,
+                                    sizeof(GUID))) {
+                                       WAIT_FOR_VALID_GUID(((CHANNEL_HEADER
+                                                             *) (dev->
+                                                                 chanptr))->
+                                                           Type);
+                                       if (!ULTRA_VHBA_CHANNEL_OK_CLIENT
+                                           (dev->chanptr, NULL)) {
+                                               LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.",
+                                                    devNo);
+                                               POSTCODE_LINUX_4
+                                                   (DEVICE_CREATE_FAILURE_PC,
+                                                    devNo, busNo,
+                                                    POSTCODE_SEVERITY_ERR);
+                                               result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
+                                               goto Away;
+                                       }
+                                       cmd.msgtype = GUEST_ADD_VHBA;
+                                       cmd.add_vhba.chanptr = dev->chanptr;
+                                       cmd.add_vhba.busNo = busNo;
+                                       cmd.add_vhba.deviceNo = devNo;
+                                       cmd.add_vhba.devInstGuid =
+                                           dev->devInstGuid;
+                                       cmd.add_vhba.intr = dev->intr;
+                               } else
+                                   if (!memcmp
+                                       (&dev->channelTypeGuid,
+                                        &UltraVnicChannelProtocolGuid,
+                                        sizeof(GUID))) {
+                                       WAIT_FOR_VALID_GUID(((CHANNEL_HEADER
+                                                             *) (dev->
+                                                                 chanptr))->
+                                                           Type);
+                                       if (!ULTRA_VNIC_CHANNEL_OK_CLIENT
+                                           (dev->chanptr, NULL)) {
+                                               LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.",
+                                                    devNo);
+                                               POSTCODE_LINUX_4
+                                                   (DEVICE_CREATE_FAILURE_PC,
+                                                    devNo, busNo,
+                                                    POSTCODE_SEVERITY_ERR);
+                                               result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
+                                               goto Away;
+                                       }
+                                       cmd.msgtype = GUEST_ADD_VNIC;
+                                       cmd.add_vnic.chanptr = dev->chanptr;
+                                       cmd.add_vnic.busNo = busNo;
+                                       cmd.add_vnic.deviceNo = devNo;
+                                       cmd.add_vnic.devInstGuid =
+                                           dev->devInstGuid;
+                                       cmd.add_vhba.intr = dev->intr;
+                               } else {
+                                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
+                                       POSTCODE_LINUX_4
+                                           (DEVICE_CREATE_FAILURE_PC, devNo,
+                                            busNo, POSTCODE_SEVERITY_ERR);
+                                       result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+                                       goto Away;
+                               }
+
+                               if (!VirtControlChanFunc) {
+                                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered.");
+                                       POSTCODE_LINUX_4
+                                           (DEVICE_CREATE_FAILURE_PC, devNo,
+                                            busNo, POSTCODE_SEVERITY_ERR);
+                                       result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+                                       goto Away;
+                               }
+
+                               if (!VirtControlChanFunc(&cmd)) {
+                                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error.");
+                                       POSTCODE_LINUX_4
+                                           (DEVICE_CREATE_FAILURE_PC, devNo,
+                                            busNo, POSTCODE_SEVERITY_ERR);
+                                       result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+                                       goto Away;
+                               }
+                       }
+                       bus->device[devNo] = dev;
+                       POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo,
+                                        POSTCODE_SEVERITY_INFO);
+                       return CONTROLVM_RESP_SUCCESS;
+               }
+       }
+       read_unlock(&BusListLock);
+
+       LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo);
+       POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_ERR);
+       result = CONTROLVM_RESP_ERROR_BUS_INVALID;
+
+Away:
+       if (!msg->hdr.Flags.testMessage) {
+               uislib_iounmap(dev->chanptr);
+               dev->chanptr = NULL;
+       }
+
+       UISFREE(dev, sizeof(struct device_info));
+       return result;
+}
+
+static int
+pause_device(CONTROLVM_MESSAGE *msg)
+{
+       U32 busNo, devNo;
+       struct bus_info *bus;
+       struct device_info *dev;
+       struct guest_msgs cmd;
+
+       busNo = msg->cmd.deviceChangeState.busNo;
+       devNo = msg->cmd.deviceChangeState.devNo;
+
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; bus = bus->next) {
+               if (bus->busNo == busNo) {
+                       /* make sure the device number is valid */
+                       if (devNo >= bus->deviceCount) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).",
+                                    devNo, bus->deviceCount);
+                               read_unlock(&BusListLock);
+                               return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+                       }
+                       /* make sure this device exists */
+                       dev = bus->device[devNo];
+                       if (!dev) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
+                                    devNo);
+                               read_unlock(&BusListLock);
+                               return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+                       }
+                       read_unlock(&BusListLock);
+                       /* the msg is bound for virtpci; send
+                        * guest_msgs struct to callback
+                        */
+                       if (!memcmp
+                           (&dev->channelTypeGuid,
+                            &UltraVhbaChannelProtocolGuid, sizeof(GUID))) {
+                               cmd.msgtype = GUEST_PAUSE_VHBA;
+                               cmd.pause_vhba.chanptr = dev->chanptr;
+                       } else
+                           if (!memcmp
+                               (&dev->channelTypeGuid,
+                                &UltraVnicChannelProtocolGuid,
+                                sizeof(GUID))) {
+                               cmd.msgtype = GUEST_PAUSE_VNIC;
+                               cmd.pause_vnic.chanptr = dev->chanptr;
+                       } else {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
+                               return
+                                   CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+                       }
+
+                       if (!VirtControlChanFunc) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+                               return
+                                   CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+                       }
+
+                       if (!VirtControlChanFunc(&cmd)) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
+                               return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+                       }
+                       break;
+               }
+       }
+
+       if (!bus) {
+               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist",
+                    busNo);
+               read_unlock(&BusListLock);
+               return CONTROLVM_RESP_ERROR_BUS_INVALID;
+       }
+
+       return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+resume_device(CONTROLVM_MESSAGE *msg)
+{
+       U32 busNo, devNo;
+       struct bus_info *bus;
+       struct device_info *dev;
+       struct guest_msgs cmd;
+
+       busNo = msg->cmd.deviceChangeState.busNo;
+       devNo = msg->cmd.deviceChangeState.devNo;
+
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; bus = bus->next) {
+               if (bus->busNo == busNo) {
+                       /* make sure the device number is valid */
+                       if (devNo >= bus->deviceCount) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).",
+                                    devNo, bus->deviceCount);
+                               read_unlock(&BusListLock);
+                               return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+                       }
+                       /* make sure this device exists */
+                       dev = bus->device[devNo];
+                       if (!dev) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
+                                    devNo);
+                               read_unlock(&BusListLock);
+                               return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+                       }
+                       read_unlock(&BusListLock);
+                       /* the msg is bound for virtpci; send
+                        * guest_msgs struct to callback
+                        */
+                       if (!memcmp(&dev->channelTypeGuid,
+                                   &UltraVhbaChannelProtocolGuid,
+                                   sizeof(GUID))) {
+                               cmd.msgtype = GUEST_RESUME_VHBA;
+                               cmd.resume_vhba.chanptr = dev->chanptr;
+                       } else
+                           if (!memcmp(&dev->channelTypeGuid,
+                                       &UltraVnicChannelProtocolGuid,
+                                       sizeof(GUID))) {
+                               cmd.msgtype = GUEST_RESUME_VNIC;
+                               cmd.resume_vnic.chanptr = dev->chanptr;
+                       } else {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
+                               return
+                                   CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+                       }
+
+                       if (!VirtControlChanFunc) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+                               return
+                                   CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+                       }
+
+                       if (!VirtControlChanFunc(&cmd)) {
+                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
+                               return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+                       }
+                       break;
+               }
+       }
+
+       if (!bus) {
+               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist",
+                    busNo);
+               read_unlock(&BusListLock);
+               return CONTROLVM_RESP_ERROR_BUS_INVALID;
+       }
+
+       return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
+{
+       U32 busNo, devNo;
+       struct bus_info *bus;
+       struct device_info *dev;
+       struct guest_msgs cmd;
+
+       busNo = msg->cmd.destroyDevice.busNo;
+       devNo = msg->cmd.destroyDevice.devNo;
+
+       read_lock(&BusListLock);
+       LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo);
+       for (bus = BusListHead; bus; bus = bus->next) {
+               if (bus->busNo == busNo) {
+                       /* make sure the device number is valid */
+                       if (devNo >= bus->deviceCount) {
+                               LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).",
+                                    devNo, bus->deviceCount);
+                               read_unlock(&BusListLock);
+                               return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+                       }
+                       /* make sure this device exists */
+                       dev = bus->device[devNo];
+                       if (!dev) {
+                               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
+                                    devNo);
+                               read_unlock(&BusListLock);
+                               return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+                       }
+                       read_unlock(&BusListLock);
+                       /* the msg is bound for virtpci; send
+                        * guest_msgs struct to callback
+                        */
+                       if (!memcmp
+                           (&dev->channelTypeGuid,
+                            &UltraVhbaChannelProtocolGuid, sizeof(GUID))) {
+                               cmd.msgtype = GUEST_DEL_VHBA;
+                               cmd.del_vhba.chanptr = dev->chanptr;
+                       } else
+                           if (!memcmp
+                               (&dev->channelTypeGuid,
+                                &UltraVnicChannelProtocolGuid,
+                                sizeof(GUID))) {
+                               cmd.msgtype = GUEST_DEL_VNIC;
+                               cmd.del_vnic.chanptr = dev->chanptr;
+                       } else {
+                               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
+                               return
+                                   CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+                       }
+
+                       if (!VirtControlChanFunc) {
+                               LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
+                               return
+                                   CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+                       }
+
+                       if (!VirtControlChanFunc(&cmd)) {
+                               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
+                               return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+                       }
+/* you must disable channel interrupts BEFORE you unmap the channel,
+ * because if you unmap first, there may still be some activity going
+ * on which accesses the channel and you will get a "unable to handle
+ * kernel paging request"
+ */
+                       if (dev->polling) {
+                               LOGINF("calling uislib_disable_channel_interrupts");
+                               uislib_disable_channel_interrupts(busNo, devNo);
+                       }
+                       /* unmap the channel memory for the device. */
+                       if (!msg->hdr.Flags.testMessage) {
+                               LOGINF("destroy_device, doing iounmap");
+                               uislib_iounmap(dev->chanptr);
+                       }
+                       UISFREE(dev, sizeof(struct device_info));
+                       bus->device[devNo] = NULL;
+                       break;
+               }
+       }
+
+       if (!bus) {
+               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
+                      busNo);
+               read_unlock(&BusListLock);
+               return CONTROLVM_RESP_ERROR_BUS_INVALID;
+       }
+
+       return CONTROLVM_RESP_SUCCESS;
+}
+
+void
+ULTRA_disp_channel_header(CHANNEL_HEADER *x)
+{
+       LOGINF("Sig=%llx, HdrSz=%lx, Sz=%llx, Feat=%llx, hPart=%llx, Hndl=%llx, ChSpace=%llx, Ver=%lx, PartIdx=%lx\n",
+            x->Signature, (long unsigned int) x->HeaderSize, x->Size,
+            x->Features, x->PartitionHandle, x->Handle, x->oChannelSpace,
+            (long unsigned int) x->VersionId,
+            (long unsigned int) x->PartitionIndex);
+
+       LOGINF("ClientStr=%lx, CliStBoot=%lx, CmdStCli=%lx, CliStOS=%lx, ChCharistics=%lx, CmdStSrv=%lx, SrvSt=%lx\n",
+            (long unsigned int) x->oClientString,
+            (long unsigned int) x->CliStateBoot,
+            (long unsigned int) x->CmdStateCli,
+            (long unsigned int) x->CliStateOS,
+            (long unsigned int) x->ChannelCharacteristics,
+            (long unsigned int) x->CmdStateSrv,
+            (long unsigned int) x->SrvState);
+
+}
+
+void
+ULTRA_disp_channel(ULTRA_IO_CHANNEL_PROTOCOL *x)
+{
+       ULTRA_disp_channel_header(&x->ChannelHeader);
+       LOGINF("cmdQ.Type=%lx\n", (long unsigned int) x->cmdQ.Type);
+       LOGINF("cmdQ.Size=%llx\n", x->cmdQ.Size);
+       LOGINF("cmdQ.oSignalBase=%llx\n", x->cmdQ.oSignalBase);
+       LOGINF("cmdQ.SignalSize=%lx\n", (long unsigned int) x->cmdQ.SignalSize);
+       LOGINF("cmdQ.MaxSignalSlots=%lx\n",
+              (long unsigned int) x->cmdQ.MaxSignalSlots);
+       LOGINF("cmdQ.MaxSignals=%lx\n", (long unsigned int) x->cmdQ.MaxSignals);
+       LOGINF("rspQ.Type=%lx\n", (long unsigned int) x->rspQ.Type);
+       LOGINF("rspQ.Size=%llx\n", x->rspQ.Size);
+       LOGINF("rspQ.oSignalBase=%llx\n", x->rspQ.oSignalBase);
+       LOGINF("rspQ.SignalSize=%lx\n", (long unsigned int) x->rspQ.SignalSize);
+       LOGINF("rspQ.MaxSignalSlots=%lx\n",
+              (long unsigned int) x->rspQ.MaxSignalSlots);
+       LOGINF("rspQ.MaxSignals=%lx\n", (long unsigned int) x->rspQ.MaxSignals);
+       LOGINF("SIZEOF_CMDRSP=%lx\n", SIZEOF_CMDRSP);
+       LOGINF("SIZEOF_PROTOCOL=%lx\n", SIZEOF_PROTOCOL);
+}
+
+void
+ULTRA_disp_vnic_channel(ULTRA_IO_CHANNEL_PROTOCOL *x)
+{
+       LOGINF("num_rcv_bufs=%lx\n", (long unsigned int) x->vnic.num_rcv_bufs);
+       LOGINF("mtu=%lx\n", (long unsigned int) x->vnic.mtu);
+}
+
+static int
+init_chipset(CONTROLVM_MESSAGE *msg, char *buf)
+{
+       POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+       MaxBusCount = msg->cmd.initChipset.busCount;
+       PlatformNumber = msg->cmd.initChipset.platformNumber;
+       PhysicalDataChan = 0;
+
+       /* We need to make sure we have our functions registered
+       * before processing messages.  If we are a test vehicle the
+       * testMessage for init_chipset will be set.  We can ignore the
+       * waits for the callbacks, since this will be manually entered
+       * from a user.  If no testMessage is set, we will wait for the
+       * functions.
+       */
+       if (!msg->hdr.Flags.testMessage)
+               WAIT_ON_CALLBACK(VirtControlChanFunc);
+
+       chipset_inited = 1;
+       POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+       return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+stop_chipset(CONTROLVM_MESSAGE *msg, char *buf)
+{
+       /* Check that all buses and switches have been torn down and
+        * destroyed.
+        */
+       if (BusListHead) {
+               /* Buses still exist. */
+               LOGERR("CONTROLVM_CHIPSET_STOP: BusListHead is not NULL");
+               return CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS;
+       }
+       if (BusListCount) {
+               /* BusListHead is NULL, but BusListCount != 0 */
+               LOGERR("CONTROLVM_CHIPSET_STOP: BusListCount != 0");
+               return CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS;
+       }
+
+       /* Buses are shut down. */
+       return visorchipset_chipset_notready();
+}
+
+static int
+delete_bus_glue(U32 busNo)
+{
+       CONTROLVM_MESSAGE msg;
+
+       init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
+       msg.cmd.destroyBus.busNo = busNo;
+       if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("destroy_bus failed. busNo=0x%x\n", busNo);
+               return 0;
+       }
+       return 1;
+}
+
+static int
+delete_device_glue(U32 busNo, U32 devNo)
+{
+       CONTROLVM_MESSAGE msg;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
+       msg.cmd.destroyDevice.busNo = busNo;
+       msg.cmd.destroyDevice.devNo = devNo;
+       if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo,
+                      devNo);
+               return 0;
+       }
+       return 1;
+}
+
+int
+uislib_client_inject_add_bus(U32 busNo, GUID instGuid,
+                            U64 channelAddr, ulong nChannelBytes)
+{
+       CONTROLVM_MESSAGE msg;
+
+       LOGINF("enter busNo=0x%x\n", busNo);
+       /* step 0: init the chipset */
+       POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+       if (!chipset_inited) {
+               /* step: initialize the chipset */
+               init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
+               /* this change is needed so that console will come up
+               * OK even when the bus 0 create comes in late.  If the
+               * bus 0 create is the first create, then the add_vnic
+               * will work fine, but if the bus 0 create arrives
+               * after number 4, then the add_vnic will fail, and the
+               * ultraboot will fail.
+               */
+               msg.cmd.initChipset.busCount = 23;
+               msg.cmd.initChipset.switchCount = 0;
+               if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+                       LOGERR("init_chipset failed.\n");
+                       return 0;
+               }
+               LOGINF("chipset initialized\n");
+               POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, busNo,
+                                POSTCODE_SEVERITY_INFO);
+       }
+
+       /* step 1: create a bus */
+       POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_WARNING);
+       init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
+       msg.cmd.createBus.busNo = busNo;
+       msg.cmd.createBus.deviceCount = 23;     /* devNo+1; */
+       msg.cmd.createBus.channelAddr = channelAddr;
+       msg.cmd.createBus.channelBytes = nChannelBytes;
+       if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("create_bus failed.\n");
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+       POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus);
+
+
+int
+uislib_client_inject_del_bus(U32 busNo)
+{
+       return delete_bus_glue(busNo);
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_del_bus);
+
+int
+uislib_client_inject_pause_vhba(U32 busNo, U32 devNo)
+{
+       CONTROLVM_MESSAGE msg;
+       int rc;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+       msg.cmd.deviceChangeState.busNo = busNo;
+       msg.cmd.deviceChangeState.devNo = devNo;
+       msg.cmd.deviceChangeState.state = SegmentStateStandby;
+       rc = pause_device(&msg);
+       if (rc != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("VHBA pause_device failed. busNo=0x%x devNo=0x%x\n",
+                      busNo, devNo);
+               return rc;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba);
+
+int
+uislib_client_inject_resume_vhba(U32 busNo, U32 devNo)
+{
+       CONTROLVM_MESSAGE msg;
+       int rc;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+       msg.cmd.deviceChangeState.busNo = busNo;
+       msg.cmd.deviceChangeState.devNo = devNo;
+       msg.cmd.deviceChangeState.state = SegmentStateRunning;
+       rc = resume_device(&msg);
+       if (rc != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("VHBA resume_device failed. busNo=0x%x devNo=0x%x\n",
+                      busNo, devNo);
+               return rc;
+       }
+       return 0;
+
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba);
+
+int
+uislib_client_inject_add_vhba(U32 busNo, U32 devNo,
+                             U64 phys_chan_addr, U32 chan_bytes,
+                             int is_test_addr, GUID instGuid,
+                             struct InterruptInfo *intr)
+{
+       CONTROLVM_MESSAGE msg;
+
+       LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
+       /* chipset init'ed with bus bus has been previously created -
+       * Verify it still exists step 2: create the VHBA device on the
+       * bus
+       */
+       POSTCODE_LINUX_4(VHBA_CREATE_ENTRY_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
+       if (is_test_addr)
+               /* signify that the physical channel address does NOT
+                * need to be ioremap()ed
+                */
+               msg.hdr.Flags.testMessage = 1;
+       msg.cmd.createDevice.busNo = busNo;
+       msg.cmd.createDevice.devNo = devNo;
+       msg.cmd.createDevice.devInstGuid = instGuid;
+       if (intr)
+               msg.cmd.createDevice.intr = *intr;
+       else
+               memset(&msg.cmd.createDevice.intr, 0,
+                      sizeof(struct InterruptInfo));
+       msg.cmd.createDevice.channelAddr = phys_chan_addr;
+       if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
+               LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
+                    chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
+               POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes,
+                                MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+       msg.cmd.createDevice.channelBytes = chan_bytes;
+       msg.cmd.createDevice.dataTypeGuid = UltraVhbaChannelProtocolGuid;
+       if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("VHBA create_device failed.\n");
+               POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+       POSTCODE_LINUX_4(VHBA_CREATE_SUCCESS_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_add_vhba);
+
+int
+uislib_client_inject_del_vhba(U32 busNo, U32 devNo)
+{
+       return delete_device_glue(busNo, devNo);
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_del_vhba);
+
+int
+uislib_client_inject_add_vnic(U32 busNo, U32 devNo,
+                             U64 phys_chan_addr, U32 chan_bytes,
+                             int is_test_addr, GUID instGuid,
+                             struct InterruptInfo *intr)
+{
+       CONTROLVM_MESSAGE msg;
+
+       LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
+       /* chipset init'ed with bus bus has been previously created -
+       * Verify it still exists step 2: create the VNIC device on the
+       * bus
+       */
+       POSTCODE_LINUX_4(VNIC_CREATE_ENTRY_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
+       if (is_test_addr)
+               /* signify that the physical channel address does NOT
+                * need to be ioremap()ed
+                */
+               msg.hdr.Flags.testMessage = 1;
+       msg.cmd.createDevice.busNo = busNo;
+       msg.cmd.createDevice.devNo = devNo;
+       msg.cmd.createDevice.devInstGuid = instGuid;
+       if (intr)
+               msg.cmd.createDevice.intr = *intr;
+       else
+               memset(&msg.cmd.createDevice.intr, 0,
+                      sizeof(struct InterruptInfo));
+       msg.cmd.createDevice.channelAddr = phys_chan_addr;
+       if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
+               LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
+                    chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
+               POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes,
+                                MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+       msg.cmd.createDevice.channelBytes = chan_bytes;
+       msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
+       if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("VNIC create_device failed.\n");
+               POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+
+       POSTCODE_LINUX_4(VNIC_CREATE_SUCCESS_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_add_vnic);
+
+int
+uislib_client_inject_pause_vnic(U32 busNo, U32 devNo)
+{
+       CONTROLVM_MESSAGE msg;
+       int rc;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+       msg.cmd.deviceChangeState.busNo = busNo;
+       msg.cmd.deviceChangeState.devNo = devNo;
+       msg.cmd.deviceChangeState.state = SegmentStateStandby;
+       rc = pause_device(&msg);
+       if (rc != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("VNIC pause_device failed. busNo=0x%x devNo=0x%x\n",
+                      busNo, devNo);
+               return -1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic);
+
+int
+uislib_client_inject_resume_vnic(U32 busNo, U32 devNo)
+{
+       CONTROLVM_MESSAGE msg;
+       int rc;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+       msg.cmd.deviceChangeState.busNo = busNo;
+       msg.cmd.deviceChangeState.devNo = devNo;
+       msg.cmd.deviceChangeState.state = SegmentStateRunning;
+       rc = resume_device(&msg);
+       if (rc != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("VNIC resume_device failed. busNo=0x%x devNo=0x%x\n",
+                      busNo, devNo);
+               return -1;
+       }
+       return 0;
+
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic);
+
+int
+uislib_client_inject_del_vnic(U32 busNo, U32 devNo)
+{
+       return delete_device_glue(busNo, devNo);
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_del_vnic);
+
+int
+uislib_client_add_vnic(U32 busNo)
+{
+       BOOL busCreated = FALSE;
+       int devNo = 0;          /* Default to 0, since only one device
+                                * will be created for this bus... */
+       GUID dummyGuid = GUID0;
+       CONTROLVM_MESSAGE msg;
+
+       init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
+       msg.hdr.Flags.testMessage = 1;
+       msg.cmd.createBus.busNo = busNo;
+       msg.cmd.createBus.deviceCount = 4;
+       msg.cmd.createBus.channelAddr = 0;
+       msg.cmd.createBus.channelBytes = 0;
+       if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("client create_bus failed");
+               return 0;
+       }
+       busCreated = TRUE;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
+       msg.hdr.Flags.testMessage = 1;
+       msg.cmd.createDevice.busNo = busNo;
+       msg.cmd.createDevice.devNo = devNo;
+       msg.cmd.createDevice.devInstGuid = dummyGuid;
+       memset(&msg.cmd.createDevice.intr, 0, sizeof(struct InterruptInfo));
+       msg.cmd.createDevice.channelAddr = PhysicalDataChan;
+       msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
+       msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
+       if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               LOGERR("client create_device failed");
+               goto AwayCleanup;
+       }
+
+       return 1;
+
+AwayCleanup:
+       if (busCreated) {
+               init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
+               msg.hdr.Flags.testMessage = 1;
+               msg.cmd.destroyBus.busNo = busNo;
+               if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
+                       LOGERR("client destroy_bus failed.\n");
+       }
+
+       return 0;
+}                              /* end uislib_client_add_vnic */
+EXPORT_SYMBOL_GPL(uislib_client_add_vnic);
+
+int
+uislib_client_delete_vnic(U32 busNo)
+{
+       int devNo = 0;          /* Default to 0, since only one device
+                                * will be created for this bus... */
+       CONTROLVM_MESSAGE msg;
+
+       init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
+       msg.hdr.Flags.testMessage = 1;
+       msg.cmd.destroyDevice.busNo = busNo;
+       msg.cmd.destroyDevice.devNo = devNo;
+       if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+               /* Don't error exit - try to see if bus can be destroyed... */
+               LOGERR("client destroy_device failed.\n");
+       }
+
+       init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
+       msg.hdr.Flags.testMessage = 1;
+       msg.cmd.destroyBus.busNo = busNo;
+       if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
+               LOGERR("client destroy_bus failed.\n");
+
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_delete_vnic);
+
+                               /* end client_delete_vnic */
+
+static atomic_t Malloc_BytesInUse = ATOMIC_INIT(0);
+static atomic_t Malloc_BuffersInUse = ATOMIC_INIT(0);
+static atomic_t Malloc_FailuresAlloc = ATOMIC_INIT(0);
+static atomic_t Malloc_FailuresFree = ATOMIC_INIT(0);
+static atomic_t Malloc_TotalMallocs = ATOMIC_INIT(0);
+static atomic_t Malloc_TotalFrees = ATOMIC_INIT(0);
+
+void *
+uislib_malloc(size_t siz, gfp_t gfp, U8 contiguous, char *fn, int ln)
+{
+       void *p = NULL;
+
+       if (contiguous == 0) {
+               /* Allocate non-contiguous memory, such as in the
+               * add_vnic and add_vhba methods where we are rebooting
+               * the guest, for example.  Otherwise the contiguous
+               * memory allocation attempt results in an
+               * out-of-memory crash in the IOVM...
+               */
+               p = vmalloc(siz);
+       } else {
+               /* __GFP_NORETRY means "ok to fail", meaning kmalloc()
+               * can return NULL.  If you do NOT specify
+               * __GFP_NORETRY, Linux will go to extreme measures to
+               * get memory for you (like, invoke oom killer), which
+               * will probably cripple the system.
+               */
+               p = kmalloc(siz, gfp | __GFP_NORETRY);
+       }
+       if (p == NULL) {
+               LOGERR("uislib_malloc failed to alloc %d bytes @%s:%d",
+                      (int) siz, fn, ln);
+               atomic_inc(&Malloc_FailuresAlloc);
+               return NULL;
+       }
+       atomic_add((int) (siz), &Malloc_BytesInUse);
+       atomic_inc(&Malloc_BuffersInUse);
+       atomic_inc(&Malloc_TotalMallocs);       /* will eventually overflow */
+       return p;
+}
+EXPORT_SYMBOL_GPL(uislib_malloc);
+
+void
+uislib_free(void *p, size_t siz, U8 contiguous, char *fn, int ln)
+{
+       if (p == NULL) {
+               LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
+               atomic_inc(&Malloc_FailuresFree);
+               return;
+       }
+
+       if (contiguous == 0)
+               vfree(p);
+       else
+               kfree(p);
+       atomic_sub((int) (siz), &Malloc_BytesInUse);
+       atomic_dec(&Malloc_BuffersInUse);
+       atomic_inc(&Malloc_TotalFrees); /* will eventually overflow */
+}
+EXPORT_SYMBOL_GPL(uislib_free);
+
+void *
+uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
+{
+       /* __GFP_NORETRY means "ok to fail", meaning kmalloc() can
+       * return NULL.  If you do NOT specify __GFP_NORETRY, Linux
+       * will go to extreme measures to get memory for you (like,
+       * invoke oom killer), which will probably cripple the system.
+       */
+       void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
+       if (p == NULL) {
+               LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
+                      fn, ln);
+               return NULL;
+       }
+       return p;
+}
+EXPORT_SYMBOL_GPL(uislib_cache_alloc);
+
+void
+uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln)
+{
+       if (p == NULL) {
+               LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
+               return;
+       }
+       kmem_cache_free(cur_pool, p);
+}
+EXPORT_SYMBOL_GPL(uislib_cache_free);
+
+/*****************************************************/
+/* proc filesystem callback functions                */
+/*****************************************************/
+
+static ssize_t
+vnic_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
+{
+       int action = 0xffff, busNo = 0, i, result = 0;
+       char buf[count];
+       char direction;
+/* GUID guid; */
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("echo > /proc/uislib/vnic copy_from_user ****FAILED.\n");
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%d%c", &action, &direction);
+       if (i != 2) {
+               LOGERR("unable to parse vnic proc parameters.\n");
+               return -EFAULT;
+       }
+
+       if ((direction != '-') && (direction != '+')) {
+               LOGERR("unable to determine whether to add or delete vnic\n");
+               return -EFAULT;
+       }
+
+       /* if (i < 1), i.e., if we didn't even read the action field,
+       * then action will default to 0xffff and the code below will
+       * fall through the switch and print usage.
+       */
+       switch (action) {
+       case 0:
+               /* call client method... */
+               busNo = 0;      /* All client drivers use bus value of 0... */
+               if (direction == '+')
+                       result = uislib_client_add_vnic(busNo);
+               else
+                       result = uislib_client_delete_vnic(busNo);
+               if (!result) {
+                       LOGERR("echo 0%c > /proc/uislib/vnic failed (client end)",
+                            direction);
+                       return -EFAULT;
+               }
+               return count;
+
+       default:
+               break;
+       }
+
+       LOGERR("USAGE: echo <action><direction (up/down)> > /proc/uislib/vnic");
+       LOGERR(" ");
+       LOGERR("Client Syntax");
+       LOGERR("-------------");
+       LOGERR("0+    ==> add vnic");
+       LOGERR("0-    ==> delete vnic");
+       LOGERR(" ");
+       return count;
+}                              /* end vnic_proc_write */
+
+static ssize_t
+chipset_proc_write(struct file *file, const char __user *buffer,
+                  size_t count, loff_t *ppos)
+{
+       int i, action = 0xffff;
+       char buf[count];
+       CONTROLVM_MESSAGE msg;
+
+       memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user ****FAILED.\n");
+               return -EFAULT;
+       }
+
+       if (chipset_inited) {
+               LOGINF("Chipset already initialized\n");
+               return -EFAULT;
+       }
+       i = sscanf(buf, "%x", &action);
+
+       /* if (i < 1), i.e., if we didn't even read the action field,
+       * then action will default to 0xffff and the code below will
+       * fall through the switch and print usage.
+       */
+       switch (action) {
+       case 1:
+               /* GUEST */
+               /* step: initialize the chipset */
+               init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
+               msg.hdr.Flags.testMessage = 0;
+               msg.cmd.initChipset.busCount = 23;
+               msg.cmd.initChipset.switchCount = 23;
+
+               if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+                       LOGERR("init_chipset failed.\n");
+                       return 0;
+               }
+               return 1;
+       case 2:
+               /* BOTH */
+               init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
+               msg.hdr.Flags.testMessage = 1;
+               msg.cmd.initChipset.busCount = 23;
+               msg.cmd.initChipset.switchCount = 23;
+
+               if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+                       LOGERR("init_chipset failed.\n");
+                       return 0;
+               }
+               return 1;
+
+       default:
+               break;
+       }
+
+       LOGERR("usage: 1 ==> init_chipset client\n");
+       LOGERR("usage: 2 ==> init_chipset test\n");
+       return -EFAULT;
+}
+
+#define PROCLINE(...)                                                  \
+       do {                                                            \
+               if (util_add_proc_line_ex(&tot, buff,                   \
+                                         buff_len, __VA_ARGS__) < 0) { \
+                       goto err_done;                                  \
+               }                                                       \
+       } while (0)
+
+static int
+info_proc_read_helper(char **buff, int *buff_len)
+{
+       int i, tot = 0;
+       struct bus_info *bus;
+
+       PROCLINE("\nBuses:\n");
+
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; bus = bus->next) {
+
+               PROCLINE("    bus=0x%p, busNo=%d, deviceCount=%d\n",
+                        bus, bus->busNo, bus->deviceCount);
+
+               PROCLINE("        Devices:\n");
+
+               for (i = 0; i < bus->deviceCount; i++) {
+                       if (bus->device[i]) {
+                               PROCLINE("            busNo %d, device[%i]: 0x%p, chanptr=0x%p, swtch=0x%p\n",
+                                    bus->busNo, i, bus->device[i],
+                                    bus->device[i]->chanptr,
+                                    bus->device[i]->swtch);
+                               PROCLINE("            first_busy_cnt=%llu, moved_to_tail_cnt=%llu, last_on_list_cnt=%llu\n",
+                                    bus->device[i]->first_busy_cnt,
+                                    bus->device[i]->moved_to_tail_cnt,
+                                    bus->device[i]->last_on_list_cnt);
+                       }
+               }
+       }
+       read_unlock(&BusListLock);
+
+       PROCLINE("Malloc bytes in use: %d\n", atomic_read(&Malloc_BytesInUse));
+       PROCLINE("Malloc buffers in use: %d\n",
+                atomic_read(&Malloc_BuffersInUse));
+       PROCLINE("Malloc allocation failures: %d\n",
+                atomic_read(&Malloc_FailuresAlloc));
+       PROCLINE("Malloc free failures: %d\n",
+                atomic_read(&Malloc_FailuresFree));
+       PROCLINE("Malloc total mallocs: %u (may overflow)\n",
+                (unsigned) atomic_read(&Malloc_TotalMallocs));
+       PROCLINE("Malloc total frees: %u (may overflow)\n",
+                (unsigned) atomic_read(&Malloc_TotalFrees));
+       PROCLINE("UisUtils_Registered_Services: %d\n",
+                atomic_read(&UisUtils_Registered_Services));
+
+       PROCLINE("cycles_before_wait %llu wait_cycles:%llu\n",
+                cycles_before_wait, wait_cycles);
+       PROCLINE("tot_wakeup_cnt %llu:tot_wait_cnt %llu:tot_schedule_cnt %llu\n",
+            tot_wakeup_cnt, tot_wait_cnt, tot_schedule_cnt);
+       PROCLINE("en_smart_wakeup %d\n", en_smart_wakeup);
+       PROCLINE("tot_moved_to_tail_cnt %llu\n", tot_moved_to_tail_cnt);
+
+       return tot;
+err_done:
+
+       return -1;
+}
+
+static ssize_t
+info_proc_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
+{
+       char *temp;
+       int totalBytes = 0;
+       int remaining_bytes = PROC_READ_BUFFER_SIZE;
+
+/* *start = buf; */
+       if (ProcReadBuffer == NULL) {
+               DBGINF("ProcReadBuffer == NULL; allocating buffer.\n.");
+               ProcReadBuffer = UISVMALLOC(PROC_READ_BUFFER_SIZE);
+
+               if (ProcReadBuffer == NULL) {
+                       LOGERR("failed to allocate buffer to provide proc data.\n");
+                       return -ENOMEM;
+               }
+       }
+
+       temp = ProcReadBuffer;
+
+       if ((*offset == 0) || (!ProcReadBufferValid)) {
+               DBGINF("calling info_proc_read_helper.\n");
+               /* if the read fails, then -1 will be returned */
+               totalBytes = info_proc_read_helper(&temp, &remaining_bytes);
+               ProcReadBufferValid = 1;
+       } else
+               totalBytes = strlen(ProcReadBuffer);
+
+       return simple_read_from_buffer(buf, len, offset,
+                                      ProcReadBuffer, totalBytes);
+}
+
+static ssize_t
+platformnumber_proc_read(struct file *file, char __user *buf,
+                        size_t len, loff_t *offset)
+{
+       int length = 0;
+       char *vbuf;
+       loff_t pos = *offset;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos > 0 || !len)
+               return 0;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       length = sprintf(vbuf, "%d\n", PlatformNumber);
+
+       if (copy_to_user(buf, vbuf, length)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+
+       kfree(vbuf);
+       *offset += length;
+       return length;
+}
+
+#ifdef UISLIB_TEST_PROC
+
+/* proc/uislib/vbus/<x>/info */
+static int
+proc_info_vbus_show(struct seq_file *m, void *v)
+{
+       struct bus_info *bus = m->private;
+       int i, devInfoCount, x;
+       char buf[999];
+
+       if (bus == NULL)
+               return 0;
+       seq_printf(m, "Client device / client driver info for %s partition (vbus #%d):\n",
+                  bus->partitionName, bus->busNo);
+       if ((bus->busChannelBytes == 0) || (bus->pBusChannel == NULL))
+               return 0;
+       devInfoCount =
+           (bus->busChannelBytes -
+            sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL)) /
+           sizeof(ULTRA_VBUS_DEVICEINFO);
+       x = VBUSCHANNEL_devInfoToStringBuffer(bus->pBusChannel->ChpInfo, buf,
+                                             sizeof(buf) - 1, -1);
+       buf[x] = '\0';
+       seq_printf(m, "%s", buf);
+       x = VBUSCHANNEL_devInfoToStringBuffer(bus->pBusChannel->BusInfo,
+                                             buf, sizeof(buf) - 1, -1);
+       buf[x] = '\0';
+       seq_printf(m, "%s", buf);
+       for (i = 0; i < devInfoCount; i++) {
+               x = VBUSCHANNEL_devInfoToStringBuffer(bus->pBusChannel->
+                                                     DevInfo[i], buf,
+                                                     sizeof(buf) - 1, i);
+               if (x > 0) {
+                       buf[x] = '\0';
+                       seq_printf(m, "%s", buf);
+               }
+       }
+       return 0;
+}
+
+static ssize_t
+bus_proc_write(struct file *file, const char __user *buffer,
+              size_t count, loff_t *ppos)
+{
+       int server_flag = 0;
+       int i, action = 0xffff, result;
+       char buf[count];
+       CONTROLVM_MESSAGE msg;
+       U32 busNo, deviceCount;
+
+       memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("echo > /proc/uislib/bus: copy_from_user ****FAILED.");
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%x-%d-%d", &action, &busNo, &deviceCount);
+
+       /* if (i < 1), i.e., if we didn't even read the action field,
+       * then action will default to 0xffff and the code below will
+       * fall through the switch and print usage.
+       */
+       switch (action) {
+       case 0:
+               /* destroy a bus */
+               if (i != 2)
+                       break;
+               init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, server_flag);
+               msg.cmd.destroyBus.busNo = busNo;
+
+               result = destroy_bus(&msg, NULL);
+
+               if (result != CONTROLVM_RESP_SUCCESS) {
+                       LOGERR("echo 0-%d > /proc/uislib/bus {CONTROLVM_BUS_DESTROY Failed} Result(%d)",
+                            busNo, result);
+                       return -EFAULT;
+               }
+               return count;
+       case 1:
+               /* create a bus */
+               if (i != 3)
+                       break;
+               init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, server_flag);
+               msg.cmd.createBus.busNo = busNo;
+               msg.cmd.createBus.deviceCount = deviceCount;
+
+               result = create_bus(&msg, NULL);
+
+               if (result != CONTROLVM_RESP_SUCCESS) {
+                       LOGERR("echo 1-%d-%d > /proc/uislib/bus {CONTROLVM_BUS_CREATE Failed} Result(%d)",
+                            busNo, deviceCount, result);
+                       return -EFAULT;
+               }
+
+               return count;
+       default:
+               break;
+       }
+
+       LOGERR("USAGE: echo <action>-<busNo>... > /proc/uislib/bus");
+       LOGERR(" ");
+       LOGERR("Destruct Syntax     ControlVM Message Id");
+       LOGERR("---------------     ---------------------");
+       LOGERR("0-<busNo>       ==> CONTROLVM_BUS_DESTROY");
+       LOGERR(" ");
+       LOGERR("Construct Syntax            ControlVM Message Id");
+       LOGERR("-----------------------     -------------------- ");
+       LOGERR("1-<busNo>-<deviceCount> ==> CONTROLVM_BUS_CREATE");
+
+       return -EFAULT;
+}
+
+static ssize_t
+uislib_proc_read_writeonly(struct file *file, char __user *buffer,
+              size_t count, loff_t *ppos)
+{
+       return 0;
+}
+
+static ssize_t
+dev_proc_write(struct file *file, const char __user *buffer,
+              size_t count, loff_t *ppos)
+{
+       int server_flag = 0;
+       CONTROLVM_MESSAGE msg;
+       U32 busNo, devNo;
+       char buf[count];
+       unsigned int chanptr;
+       int type, i, action = 0xffff, result;
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("echo > /proc/uislib/device: copy_from_user ****FAILED.");
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%x-%d-%d-%x-%d",
+                  &action, &busNo, &devNo, &chanptr, &type);
+
+       switch (action) {
+       case 0:
+               if (i != 3)
+                       break;
+
+               /* destroy a device */
+               init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, server_flag);
+               msg.cmd.destroyDevice.busNo = busNo;
+               msg.cmd.destroyDevice.devNo = devNo;
+
+               result = destroy_device(&msg, NULL);
+
+               if (result != CONTROLVM_RESP_SUCCESS) {
+                       LOGERR("echo 0-%d-%d > /proc/uislib/device {CONTROLVM_DEVICE_DESTROY Failed} Result(%d)",
+                            busNo, devNo, result);
+                       return -EFAULT;
+               }
+
+               return count;
+
+       case 1:
+               if (i != 5)
+                       break;
+
+               /* create a device */
+               init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, server_flag);
+               msg.cmd.createDevice.busNo = busNo;
+               msg.cmd.createDevice.devNo = devNo;
+               msg.cmd.createDevice.channelAddr = __pa(chanptr);
+               msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
+
+               if (type == 0)
+                       msg.cmd.createDevice.dataTypeGuid =
+                           UltraVhbaChannelProtocolGuid;
+               else if (type == 1)
+                       msg.cmd.createDevice.dataTypeGuid =
+                           UltraVnicChannelProtocolGuid;
+               else {
+                       LOGERR("echo 1-%d-%d-%x-<type> > /proc/uislib/devce failed: invalid device type %d.",
+                            busNo, devNo, chanptr, type);
+                       return -EFAULT;
+               }
+
+               result = create_device(&msg, NULL);
+
+               if (result != CONTROLVM_RESP_SUCCESS) {
+                       if (type == 0)
+                               LOGERR("echo 1-%d-%d-%x-0 > /proc/uislib/device {CONTROLVM_DEVICE_CREATE[vHBA] Failed} Result(%d)",
+                                    busNo, devNo, chanptr, result);
+                       else
+                               LOGERR("echo 1-%d-%d-%x-1 > /proc/uislib/device {CONTROLVM_DEVICE_CREATE[vNIC] Failed} Result(%d)",
+                                    busNo, devNo, chanptr, result);
+                       return -EFAULT;
+               }
+
+       default:
+               break;
+       }
+
+       LOGERR("USAGE: echo <action>-<busNo>-<devNo>... > /proc/uislib/device");
+       LOGERR(" ");
+       LOGERR("Destruct Syntax       ControlVM Message Id");
+       LOGERR("-----------------     ------------------------");
+       LOGERR("0-<busNo>-<devNo> ==> CONTROLVM_DEVICE_DESTROY");
+       LOGERR(" ");
+       LOGERR("Construct Syntax                       ControlVM Message Id");
+       LOGERR
+           ("----------------------------------     ----------------------- ");
+       LOGERR
+           ("1-<busNo>-<devNo>-<chanptr>-<type> ==> CONTROLVM_DEVICE_CREATE");
+       LOGERR("      <type = 0>: vHBA");
+       LOGERR("      <type = 1>: vNIC");
+       LOGERR(" ");
+
+       return -EFAULT;
+}
+
+static ssize_t
+cycles_before_wait_proc_write(struct file *file, const char __user *buffer,
+                             size_t count, loff_t *ppos)
+{
+       char buf[count];
+
+#define CYCLES_BEFORE_WAIT_USE_ERROR  { \
+       LOGERR("Incorrect Call Home Input.\n"); \
+       pr_info("Please pass Call Home Event Parameters in the form:\n"); \
+       pr_info("EventID Category Type[parameter1][parameter2][parameter3][parameter4][parameter5][parameter6]\n"); \
+       return -EFAULT; \
+}
+
+       if (count == 0)
+               CYCLES_BEFORE_WAIT_USE_ERROR;
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user failed.\n");
+               return -EFAULT;
+       }
+       buf[count - 1] = '\0';  /* Replace the LF at the end of the
+                                * input with a NULL */
+       /* Pull out the cycles_before_wait must be decimal integer */
+       if (sscanf(buf, "%lld", &cycles_before_wait) != 1)
+               CYCLES_BEFORE_WAIT_USE_ERROR;
+
+       return count;
+}
+
+static ssize_t
+reset_counts_proc_write(struct file *file, const char __user *buffer,
+                       size_t count, loff_t *ppos)
+{
+       char buf[count];
+       unsigned long long new_value;
+       struct bus_info *bus;
+       int i;
+
+#define RESET_COUNTS_USE_ERROR  { \
+       LOGERR("Incorrect reset_counts Input.\n"); \
+       pr_info("Please pass the new value for the counters:\n"); \
+       pr_info("e.g. echo 0 > reset_counts\n"); \
+       return -EFAULT; \
+       }
+
+       if (count == 0)
+               RESET_COUNTS_USE_ERROR;
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user failed.\n");
+               return -EFAULT;
+       }
+       buf[count - 1] = '\0';  /* Replace the LF at the end of the
+                                * input with a NULL */
+       /* Pull out the reset_counts must be decimal integer */
+       if (sscanf(buf, "%llu", &new_value) != 1)
+               RESET_COUNTS_USE_ERROR;
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; bus = bus->next) {
+
+               for (i = 0; i < bus->deviceCount; i++) {
+                       if (bus->device[i]) {
+                               bus->device[i]->first_busy_cnt = new_value;
+                               bus->device[i]->moved_to_tail_cnt = new_value;
+                               bus->device[i]->last_on_list_cnt = new_value;
+                       }
+               }
+       }
+       read_unlock(&BusListLock);
+       tot_moved_to_tail_cnt = new_value;
+       tot_wait_cnt = new_value;
+       tot_wakeup_cnt = new_value;
+       tot_schedule_cnt = new_value;
+       return count;
+}
+
+static ssize_t
+smart_wakeup_proc_write(struct file *file, const char __user *buffer,
+                       size_t count, loff_t *ppos)
+{
+       char buf[count];
+       int new_value;
+
+#define SMART_WAKEUP_USE_ERROR  { \
+       LOGERR("Incorrect smart_wakeup Input 0 disables smart_wakeup, and 1 enables smart_wakeup.\n"); \
+       pr_info("echo 0 > smart_wakeup\n"); \
+       pr_info("echo 1 > smart_wakeup\n"); \
+       return -EFAULT; \
+       }
+
+       if (count == 0)
+               SMART_WAKEUP_USE_ERROR;
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user failed.\n");
+               return -EFAULT;
+       }
+       buf[count - 1] = '\0';  /* Replace the LF at the end of the
+                                * input with a NULL */
+       /* Pull out the smart_wakeup must be decimal integer */
+       if (sscanf(buf, "%d", &new_value) != 1)
+               SMART_WAKEUP_USE_ERROR;
+       en_smart_wakeup = new_value;
+       return count;
+}
+
+static ssize_t
+test_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
+{
+       int i, action = 0xffff;
+       char buf[count];
+       CONTROLVM_MESSAGE msg;
+       S64 vrtc_offset;
+
+       memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user ****FAILED.\n");
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%x", &action);
+
+       /* if (i < 1), i.e., if we didn't even read the action field,
+       * then action will default to 0xffff and the code below will
+       * fall through the switch and print usage. */
+       switch (action) {
+       case 6:
+               msg.hdr.Id = CONTROLVM_CHIPSET_STOP;
+               msg.hdr.Flags.responseExpected = 1;
+               stop_chipset(&msg, NULL);
+               break;
+       case 7:
+               vrtc_offset = 0;
+               LOGERR("about to issue QUERY vrtc_offset=%LX", vrtc_offset);
+               vrtc_offset = Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
+               LOGERR("result is vrtc_offset=%LX", vrtc_offset);
+               break;
+       case 8:
+               vrtc_offset = 60;
+               LOGERR("about to increase physical time by 0x%LX seconds",
+                      vrtc_offset);
+               vrtc_offset = Issue_VMCALL_UPDATE_PHYSICAL_TIME(vrtc_offset);
+               break;
+       case 9:
+               vrtc_offset = -60;
+               LOGERR("about to decrease physical time by 0x%LX seconds",
+                      vrtc_offset);
+               vrtc_offset = Issue_VMCALL_UPDATE_PHYSICAL_TIME(vrtc_offset);
+               break;
+       default:
+               LOGERR("usage: 6 for CHIPSET_STOP\n");
+               LOGERR("       7 for VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET()\n");
+               LOGERR("       8 for VMCALL_UPDATE_PHYSICAL_TIME(60)\n");
+               LOGERR("       9 for VMCALL_UPDATE_PHYSICAL_TIME(-60)\n");
+               return -EFAULT;
+               break;
+       }
+       return count;
+}
+
+#endif                         /* UISLIB_TEST_PROC */
+static struct device_info *
+find_dev(U32 busNo, U32 devNo)
+{
+       struct bus_info *bus;
+       struct device_info *dev = NULL;
+
+       read_lock(&BusListLock);
+       for (bus = BusListHead; bus; bus = bus->next) {
+               if (bus->busNo == busNo) {
+                       /* make sure the device number is valid */
+                       if (devNo >= bus->deviceCount) {
+                               LOGERR("%s bad busNo, devNo=%d,%d",
+                                      __func__,
+                                      (int) (busNo), (int) (devNo));
+                               goto Away;
+                       }
+                       dev = bus->device[devNo];
+                       if (!dev)
+                               LOGERR("%s bad busNo, devNo=%d,%d",
+                                      __func__,
+                                      (int) (busNo), (int) (devNo));
+                       goto Away;
+               }
+       }
+Away:
+       read_unlock(&BusListLock);
+       return dev;
+}
+
+/*  This thread calls the "interrupt" function for each device that has
+ *  enabled such using uislib_enable_channel_interrupts().  The "interrupt"
+ *  function typically reads and processes the devices's channel input
+ *  queue.  This thread repeatedly does this, until the thread is told to stop
+ *  (via uisthread_stop()).  Sleeping rules:
+ *  - If we have called the "interrupt" function for all devices, and all of
+ *    them have reported "nothing processed" (returned 0), then we will go to
+ *    sleep for a maximum of POLLJIFFIES_NORMAL jiffies.
+ *  - If anyone calls uislib_force_channel_interrupt(), the above jiffy
+ *    sleep will be interrupted, and we will resume calling the "interrupt"
+ *    function for all devices.
+ *  - The list of devices is dynamically re-ordered in order to
+ *    attempt to preserve fairness.  Whenever we spin thru the list of
+ *    devices and call the dev->interrupt() function, if we find
+ *    devices which report that there is still more work to do, the
+ *    the first such device we find is moved to the end of the device
+ *    list.  This ensures that extremely busy devices don't starve out
+ *    less-busy ones.
+ *
+ */
+static int
+Process_Incoming(void *v)
+{
+       unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles;
+       struct list_head *new_tail = NULL;
+       int i;
+       UIS_DAEMONIZE("dev_incoming");
+       for (i = 0; i < 16; i++) {
+               old_cycles = get_cycles();
+               wait_event_timeout(Wakeup_Polling_Device_Channels,
+                                  0, POLLJIFFIES_NORMAL);
+               cur_cycles = get_cycles();
+               if (wait_cycles == 0) {
+                       wait_cycles = (cur_cycles - old_cycles);
+               } else {
+                       if (wait_cycles < (cur_cycles - old_cycles))
+                               wait_cycles = (cur_cycles - old_cycles);
+               }
+       }
+       LOGINF("wait_cycles=%llu", wait_cycles);
+       cycles_before_wait = wait_cycles;
+       idle_cycles = 0;
+       Go_Polling_Device_Channels = 0;
+       while (1) {
+               struct list_head *lelt, *tmp;
+               struct device_info *dev = NULL;
+
+               /* poll each channel for input */
+               LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+               new_tail = NULL;
+               list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) {
+                       int rc = 0;
+                       dev = list_entry(lelt, struct device_info,
+                                        list_polling_device_channels);
+                       LOCKSEM_UNINTERRUPTIBLE(&dev->interrupt_callback_lock);
+                       if (dev->interrupt)
+                               rc = dev->interrupt(dev->interrupt_context);
+                       else
+                               continue;
+                       UNLOCKSEM(&dev->interrupt_callback_lock);
+                       if (rc) {
+                               /* dev->interrupt returned, but there
+                               * is still more work to do.
+                               * Reschedule work to occur as soon as
+                               * possible. */
+                               idle_cycles = 0;
+                               if (new_tail == NULL) {
+                                       dev->first_busy_cnt++;
+                                       if (!
+                                           (list_is_last
+                                            (lelt,
+                                             &List_Polling_Device_Channels))) {
+                                               new_tail = lelt;
+                                               dev->moved_to_tail_cnt++;
+                                       } else
+                                               dev->last_on_list_cnt++;
+                               }
+
+                       }
+                       if (Incoming_ThreadInfo.should_stop)
+                               break;
+               }
+               if (new_tail != NULL) {
+                       tot_moved_to_tail_cnt++;
+                       list_move_tail(new_tail, &List_Polling_Device_Channels);
+               }
+               UNLOCKSEM(&Lock_Polling_Device_Channels);
+               cur_cycles = get_cycles();
+               delta_cycles = cur_cycles - old_cycles;
+               old_cycles = cur_cycles;
+
+               /* At this point, we have scanned thru all of the
+               * channels, and at least one of the following is true:
+               * - there is no input waiting on any of the channels
+               * - we have received a signal to stop this thread
+               */
+               if (Incoming_ThreadInfo.should_stop)
+                       break;
+               if (en_smart_wakeup == 0xFF) {
+                       LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming");
+                       break;
+               }
+               /* wait for POLLJIFFIES_NORMAL jiffies, or until
+               * someone wakes up Wakeup_Polling_Device_Channels,
+               * whichever comes first only do a wait when we have
+               * been idle for cycles_before_wait cycles.
+               */
+               if (idle_cycles > cycles_before_wait) {
+                       Go_Polling_Device_Channels = 0;
+                       tot_wait_cnt++;
+                       wait_event_timeout(Wakeup_Polling_Device_Channels,
+                                          Go_Polling_Device_Channels,
+                                          POLLJIFFIES_NORMAL);
+                       Go_Polling_Device_Channels = 1;
+               } else {
+                       tot_schedule_cnt++;
+                       schedule();
+                       idle_cycles = idle_cycles + delta_cycles;
+               }
+       }
+       DBGINF("exiting.\n");
+       complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0);
+}
+
+static BOOL
+Initialize_incoming_thread(void)
+{
+       if (Incoming_Thread_Started)
+               return TRUE;
+       if (!uisthread_start(&Incoming_ThreadInfo,
+                            &Process_Incoming, NULL, "dev_incoming")) {
+               LOGERR("uisthread_start Initialize_incoming_thread ****FAILED");
+               return FALSE;
+       }
+       Incoming_Thread_Started = TRUE;
+       return TRUE;
+}
+
+/*  Add a new device/channel to the list being processed by
+ *  Process_Incoming().
+ *  <interrupt> - indicates the function to call periodically.
+ *  <interrupt_context> - indicates the data to pass to the <interrupt>
+ *                        function.
+ */
+void
+uislib_enable_channel_interrupts(U32 busNo, U32 devNo,
+                                int (*interrupt)(void *),
+                                void *interrupt_context)
+{
+       struct device_info *dev;
+       dev = find_dev(busNo, devNo);
+       if (!dev) {
+               LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
+                      (int) (devNo));
+               return;
+       }
+       LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+       Initialize_incoming_thread();
+       dev->interrupt = interrupt;
+       dev->interrupt_context = interrupt_context;
+       dev->polling = TRUE;
+       list_add_tail(&(dev->list_polling_device_channels),
+                     &List_Polling_Device_Channels);
+       UNLOCKSEM(&Lock_Polling_Device_Channels);
+}
+EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
+
+/*  Remove a device/channel from the list being processed by
+ *  Process_Incoming().
+ */
+void
+uislib_disable_channel_interrupts(U32 busNo, U32 devNo)
+{
+       struct device_info *dev;
+       dev = find_dev(busNo, devNo);
+       if (!dev) {
+               LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
+                      (int) (devNo));
+               return;
+       }
+       LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+       list_del(&dev->list_polling_device_channels);
+       dev->polling = FALSE;
+       dev->interrupt = NULL;
+       UNLOCKSEM(&Lock_Polling_Device_Channels);
+}
+EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts);
+
+static void
+do_wakeup_polling_device_channels(struct work_struct *dummy)
+{
+       if (!Go_Polling_Device_Channels) {
+               Go_Polling_Device_Channels = 1;
+               wake_up(&Wakeup_Polling_Device_Channels);
+       }
+}
+
+DECLARE_WORK(Work_wakeup_polling_device_channels,
+            do_wakeup_polling_device_channels);
+
+/*  Call this function when you want to send a hint to Process_Incoming() that
+ *  your device might have more requests.
+ */
+void
+uislib_force_channel_interrupt(U32 busNo, U32 devNo)
+{
+       if (en_smart_wakeup == 0)
+               return;
+       if (Go_Polling_Device_Channels)
+               return;
+       /* The point of using schedule_work() instead of just doing
+        * the work inline is to force a slight delay before waking up
+        * the Process_Incoming() thread.
+        */
+       tot_wakeup_cnt++;
+       schedule_work(&Work_wakeup_polling_device_channels);
+}
+EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt);
+
+/*****************************************************/
+/* Module Init & Exit functions                      */
+/*****************************************************/
+
+static int __init
+uislib_mod_init(void)
+{
+
+       LOGINF("MONITORAPIS");
+
+       LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n",
+              (ulong) sizeof(struct uiscmdrsp));
+       LOGINF("sizeof(struct phys_info):%lu\n",
+              (ulong) sizeof(struct phys_info));
+       LOGINF("sizeof(uiscmdrsp_scsi):%lu\n",
+              (ulong) sizeof(struct uiscmdrsp_scsi));
+       LOGINF("sizeof(uiscmdrsp_net):%lu\n",
+              (ulong) sizeof(struct uiscmdrsp_net));
+       LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n",
+              (ulong) sizeof(CONTROLVM_MESSAGE));
+       LOGINF("sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL):%lu bytes\n",
+              (ulong) sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL));
+       LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n",
+              (ulong) sizeof(CHANNEL_HEADER));
+       LOGINF("sizeof(ULTRA_IO_CHANNEL_PROTOCOL):%lu bytes\n",
+              (ulong) sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
+       LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP);
+       LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL);
+
+       /* initialize global pointers to NULL */
+       BusListHead = NULL;
+       BusListCount = MaxBusCount = 0;
+       rwlock_init(&BusListLock);
+       VirtControlChanFunc = NULL;
+
+       /* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and
+        * then map this physical address to a virtual address. */
+       POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+       /* create the proc entries for the channels */
+       uislib_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
+       /* (e.g., for /proc/uislib/vbus/<x>/info) */
+       uislib_proc_vbus_dir = proc_mkdir(DIR_VBUS_PROC_ENTRY, uislib_proc_dir);
+
+       vnic_proc_entry = proc_create(VNIC_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                                     &proc_vnic_fops);
+       SET_PROC_OWNER(vnic_proc_entry, THIS_MODULE);
+
+       /* for testing purposes only, create the proc entries for
+        * enqueuing Control Channel messages */
+       chipset_proc_entry =
+           proc_create(CHIPSET_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                       &proc_chipset_fops);
+       SET_PROC_OWNER(chipset_proc_entry, THIS_MODULE);
+
+       info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                                     &proc_info_fops);
+       SET_PROC_OWNER(info_proc_entry, THIS_MODULE);
+
+       platformnumber_proc_entry =
+           proc_create(PLATFORMNUMBER_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                       &proc_platformnumber_fops);
+       SET_PROC_OWNER(platformnumberinfo_proc_entry, THIS_MODULE);
+
+       cycles_before_wait_proc_entry =
+           proc_create(CYCLES_BEFORE_WAIT_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                       &proc_cycles_before_wait_fops);
+       SET_PROC_OWNER(cycles_before_wait_proc_entry, THIS_MODULE);
+
+       reset_counts_proc_entry =
+           proc_create(RESET_COUNTS_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                       &proc_reset_counts_fops);
+       SET_PROC_OWNER(reset_counts_proc_entry, THIS_MODULE);
+
+       smart_wakeup_proc_entry =
+           proc_create(SMART_WAKEUP_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                       &proc_smart_wakeup_fops);
+       SET_PROC_OWNER(smart_wakeup_proc_entry, THIS_MODULE);
+
+#ifdef UISLIB_TEST_PROC
+       test_proc_entry = proc_create(TEST_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                                     &proc_test_fops);
+       SET_PROC_OWNER(test_proc_entry, THIS_MODULE);
+
+       bus_proc_entry = proc_create(BUS_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                                    &proc_bus_fops);
+       SET_PROC_OWNER(bus_proc_entry, THIS_MODULE);
+
+       dev_proc_entry = proc_create(DEV_PROC_ENTRY_FN, 0, uislib_proc_dir,
+                                    &proc_dev_fops);
+       SET_PROC_OWNER(dev_proc_entry, THIS_MODULE);
+#endif                         /* UISLIB_TEST_PROC */
+       POSTCODE_LINUX_3(DRIVER_EXIT_PC, 0, POSTCODE_SEVERITY_INFO);
+       return 0;
+}
+
+static void __exit
+uislib_mod_exit(void)
+{
+       if (disable_proc_entry)
+               remove_proc_entry(DISABLE_PROC_ENTRY_FN, uislib_proc_dir);
+       if (cycles_before_wait_proc_entry)
+               remove_proc_entry(CYCLES_BEFORE_WAIT_PROC_ENTRY_FN,
+                                 uislib_proc_dir);
+       if (reset_counts_proc_entry)
+               remove_proc_entry(RESET_COUNTS_PROC_ENTRY_FN, uislib_proc_dir);
+       if (smart_wakeup_proc_entry)
+               remove_proc_entry(SMART_WAKEUP_PROC_ENTRY_FN, uislib_proc_dir);
+       if (ctrlchan_proc_entry)
+               remove_proc_entry(CTRLCHAN_PROC_ENTRY_FN, uislib_proc_dir);
+       if (pmem_proc_entry)
+               remove_proc_entry(PMEM_PROC_ENTRY_FN, uislib_proc_dir);
+       if (info_proc_entry)
+               remove_proc_entry(INFO_PROC_ENTRY_FN, uislib_proc_dir);
+       if (switch_proc_entry)
+               remove_proc_entry(SWITCH_PROC_ENTRY_FN, uislib_proc_dir);
+       if (extport_proc_entry)
+               remove_proc_entry(EXTPORT_PROC_ENTRY_FN, uislib_proc_dir);
+       if (platformnumber_proc_entry)
+               remove_proc_entry(PLATFORMNUMBER_PROC_ENTRY_FN,
+                                 uislib_proc_dir);
+       if (bus_proc_entry)
+               remove_proc_entry(BUS_PROC_ENTRY_FN, uislib_proc_dir);
+       if (dev_proc_entry)
+               remove_proc_entry(DEV_PROC_ENTRY_FN, uislib_proc_dir);
+       if (vnic_proc_entry)
+               remove_proc_entry(VNIC_PROC_ENTRY_FN, uislib_proc_dir);
+       if (chipset_proc_entry)
+               remove_proc_entry(CHIPSET_PROC_ENTRY_FN, uislib_proc_dir);
+       if (uislib_proc_vbus_dir)
+               remove_proc_entry(DIR_VBUS_PROC_ENTRY, uislib_proc_dir);
+       if (uislib_proc_dir)
+               remove_proc_entry(DIR_PROC_ENTRY, NULL);
+
+       if (ProcReadBuffer) {
+               UISVFREE(ProcReadBuffer, PROC_READ_BUFFER_SIZE);
+               ProcReadBuffer = NULL;
+       }
+
+       DBGINF("goodbye.\n");
+       return;
+}
+
+module_init(uislib_mod_init);
+module_exit(uislib_mod_exit);
+
+int uis_mandatory_services = -1;
+
+module_param_named(mandatory_services, uis_mandatory_services,
+                  int, S_IRUGO);
+MODULE_PARM_DESC(uis_mandatory_services,
+                "number of server drivers we expect to register (default=-1 for legacy behavior)");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Usha Srinivasan");
+MODULE_ALIAS("uislib");
+  /* this is extracted during depmod and kept in modules.dep */
diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c
new file mode 100644 (file)
index 0000000..67e413f
--- /dev/null
@@ -0,0 +1,166 @@
+/* uisqueue.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* @ALL_INSPECTED */
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "uisutils.h"
+
+#include "chanstub.h"
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages */
+#define CURRENT_FILE_PC UISLIB_PC_uisqueue_c
+#define __MYFILE__ "uisqueue.c"
+
+#define RETVOID    do { goto Away; } while (0)
+#define RETINT(x)  do { rc = (x); goto Away; } while (0)
+#define RETPTR(x)  do { rc = (x); goto Away; } while (0)
+#define RETBOOL(x) do { rc = (x); goto Away; } while (0)
+
+#define CHECK_CACHE_ALIGN 0
+
+/*****************************************************/
+/* Exported functions                                */
+/*****************************************************/
+unsigned long long
+uisqueue_InterlockedOr(volatile unsigned long long *Target,
+                      unsigned long long Set)
+{
+       unsigned long long i;
+       unsigned long long j;
+
+       j = *Target;
+       do {
+               i = j;
+               j = uislibcmpxchg64((unsigned long long *) Target,
+                                   i, i | Set, sizeof(*(Target)));
+
+       } while (i != j);
+
+       return j;
+}
+EXPORT_SYMBOL_GPL(uisqueue_InterlockedOr);
+
+unsigned long long
+uisqueue_InterlockedAnd(volatile unsigned long long *Target,
+                       unsigned long long Set)
+{
+       unsigned long long i;
+       unsigned long long j;
+
+       j = *Target;
+       do {
+               i = j;
+               j = uislibcmpxchg64((unsigned long long *) Target,
+                                   i, i & Set, sizeof(*(Target)));
+
+       } while (i != j);
+
+       return j;
+}
+EXPORT_SYMBOL_GPL(uisqueue_InterlockedAnd);
+
+static U8
+do_locked_client_insert(struct uisqueue_info *queueinfo,
+                       unsigned int whichqueue,
+                       void *pSignal,
+                       spinlock_t *lock,
+                       unsigned char issueInterruptIfEmpty,
+                       U64 interruptHandle, U8 *channelId)
+{
+       unsigned long flags;
+       unsigned char queueWasEmpty;
+       unsigned int locked = 0;
+       unsigned int acquired = 0;
+       U8 rc = 0;
+
+       spin_lock_irqsave(lock, flags);
+       locked = 1;
+
+       if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(queueinfo->chan, channelId, NULL))
+               RETINT(0);
+
+       acquired = 1;
+
+       queueWasEmpty = SignalQueueIsEmpty(queueinfo->chan, whichqueue);
+       if (!SignalInsert(queueinfo->chan, whichqueue, pSignal))
+               RETINT(0);
+       ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId, NULL);
+       acquired = 0;
+       spin_unlock_irqrestore(lock, flags);
+       locked = 0;
+
+       queueinfo->packets_sent++;
+
+       RETINT(1);
+
+Away:
+       if (acquired) {
+               ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId,
+                                               NULL);
+               acquired = 0;
+       }
+       if (locked) {
+               spin_unlock_irqrestore((spinlock_t *) lock, flags);
+               locked = 0;
+       }
+
+       return rc;
+}
+
+int
+uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
+                                    struct uiscmdrsp *cmdrsp,
+                                    unsigned int whichqueue,
+                                    void *insertlock,
+                                    unsigned char issueInterruptIfEmpty,
+                                    U64 interruptHandle,
+                                    char oktowait, U8 *channelId)
+{
+       while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp,
+                                       (spinlock_t *) insertlock,
+                                       issueInterruptIfEmpty,
+                                       interruptHandle, channelId)) {
+               if (oktowait != OK_TO_WAIT) {
+                       LOGERR("****FAILED SignalInsert failed; cannot wait; insert aborted\n");
+                       return 0;       /* failed to queue */
+               }
+               /* try again */
+               LOGERR("****FAILED SignalInsert failed; waiting to try again\n");
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(msecs_to_jiffies(10));
+       }
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uisqueue_put_cmdrsp_with_lock_client);
+
+/* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
+ * returns NULL if queue is empty */
+int
+uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo,
+                   void *cmdrsp, unsigned int whichqueue)
+{
+       if (!SignalRemove(queueinfo->chan, whichqueue, cmdrsp))
+               return 0;
+
+       queueinfo->packets_received++;
+
+       return 1;               /* Success */
+}
+EXPORT_SYMBOL_GPL(uisqueue_get_cmdrsp);
diff --git a/drivers/staging/unisys/uislib/uisthread.c b/drivers/staging/unisys/uislib/uisthread.c
new file mode 100644 (file)
index 0000000..ecf4bfc
--- /dev/null
@@ -0,0 +1,85 @@
+/* uisthread.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* @ALL_INSPECTED */
+#include <asm/processor.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include "uniklog.h"
+#include "uisutils.h"
+#include "uisthread.h"
+
+#define KILL(a, b, c) kill_pid(find_vpid(a), b, c)
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC UISLIB_PC_uisthread_c
+#define __MYFILE__ "uisthread.c"
+
+/*****************************************************/
+/* Exported functions                                */
+/*****************************************************/
+
+/* returns 0 for failure, 1 for success */
+int
+uisthread_start(struct uisthread_info *thrinfo,
+               int (*threadfn)(void *), void *thrcontext, char *name)
+{
+       thrinfo->should_stop = 0;
+       /* used to stop the thread */
+       init_completion(&thrinfo->has_stopped);
+       thrinfo->task = kthread_create(threadfn, thrcontext, name, NULL);
+       if (thrinfo->task == NULL) {
+               thrinfo->id = 0;
+               return 0;       /* failure */
+       }
+       thrinfo->id = thrinfo->task->pid;
+       wake_up_process(thrinfo->task);
+       LOGINF("started thread pid:%d\n", thrinfo->id);
+       return 1;
+
+}
+EXPORT_SYMBOL_GPL(uisthread_start);
+
+void
+uisthread_stop(struct uisthread_info *thrinfo)
+{
+       int ret;
+       int stopped = 0;
+       if (thrinfo->id == 0)
+               return;         /* thread not running */
+
+       LOGINF("uisthread_stop stopping id:%d\n", thrinfo->id);
+       thrinfo->should_stop = 1;
+       ret = KILL(thrinfo->id, SIGHUP, 1);
+       if (ret) {
+               LOGERR("unable to signal thread %d\n", ret);
+       } else {
+               /* give up if the thread has NOT died in 1 minute */
+               if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ))
+                       stopped = 1;
+               else
+                       LOGERR("timed out trying to signal thread\n");
+       }
+       if (stopped) {
+               LOGINF("uisthread_stop stopped id:%d\n", thrinfo->id);
+               thrinfo->id = 0;
+       }
+}
+EXPORT_SYMBOL_GPL(uisthread_stop);
diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c
new file mode 100644 (file)
index 0000000..974f8bc
--- /dev/null
@@ -0,0 +1,349 @@
+/* uisutils.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <commontypes.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include "uniklog.h"
+#include "uisutils.h"
+#include "version.h"
+#include "vbushelper.h"
+#include "guidutils.h"
+#include <linux/skbuff.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/highmem.h>
+#endif
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC UISLIB_PC_uisutils_c
+#define __MYFILE__ "uisutils.c"
+
+/* exports */
+atomic_t UisUtils_Registered_Services = ATOMIC_INIT(0);
+                                       /* num registrations via
+                                        * uisctrl_register_req_handler() or
+                                        * uisctrl_register_req_handler_ex() */
+
+
+/*****************************************************/
+/* Utility functions                                 */
+/*****************************************************/
+
+int
+util_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
+                     char *format, ...)
+{
+       va_list args;
+       int len;
+
+       DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer);
+       va_start(args, format);
+       len = vsnprintf(*buffer, *buffer_remaining, format, args);
+       if (len >= *buffer_remaining) {
+               *buffer += *buffer_remaining;
+               *total += *buffer_remaining;
+               *buffer_remaining = 0;
+               LOGERR("bytes remaining is too small!\n");
+               return -1;
+       }
+       *buffer_remaining -= len;
+       *buffer += len;
+       *total += len;
+       return len;
+}
+EXPORT_SYMBOL_GPL(util_add_proc_line_ex);
+
+int
+uisctrl_register_req_handler(int type, void *fptr,
+                            ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
+{
+       LOGINF("type = %d, fptr = 0x%p.\n", type, fptr);
+
+       switch (type) {
+       case 2:
+               if (fptr) {
+                       if (!VirtControlChanFunc)
+                               atomic_inc(&UisUtils_Registered_Services);
+                       VirtControlChanFunc = fptr;
+               } else {
+                       if (VirtControlChanFunc)
+                               atomic_dec(&UisUtils_Registered_Services);
+                       VirtControlChanFunc = NULL;
+               }
+               break;
+
+       default:
+               LOGERR("invalid type %d.\n", type);
+               return 0;
+       }
+       if (chipset_DriverInfo)
+               BusDeviceInfo_Init(chipset_DriverInfo,
+                                  "chipset", "uislib",
+                                  VERSION, NULL, __DATE__, __TIME__);
+
+       return 1;
+}
+EXPORT_SYMBOL_GPL(uisctrl_register_req_handler);
+
+int
+uisctrl_register_req_handler_ex(GUID switchTypeGuid,
+                               const char *switch_type_name,
+                               int (*controlfunc)(struct io_msgs *),
+                               unsigned long min_channel_bytes,
+                               int (*Server_Channel_Ok)(unsigned long
+                                                         channelBytes),
+                               int (*Server_Channel_Init)
+                                (void *x, unsigned char *clientStr,
+                                 U32 clientStrLen, U64 bytes),
+                               ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
+{
+       char s[99];
+       ReqHandlerInfo_t *pReqHandlerInfo;
+       int rc = 0;             /* assume failure */
+       LOGINF("type=%s, controlfunc=0x%p.\n",
+              GUID_format1(&switchTypeGuid, s), controlfunc);
+       if (!controlfunc) {
+               LOGERR("%s: controlfunc must be supplied\n",
+                      GUID_format1(&switchTypeGuid, s));
+               goto Away;
+       }
+       if (!Server_Channel_Ok) {
+               LOGERR("%s: Server_Channel_Ok must be supplied\n",
+                      GUID_format1(&switchTypeGuid, s));
+               goto Away;
+       }
+       if (!Server_Channel_Init) {
+               LOGERR("%s: Server_Channel_Init must be supplied\n",
+                      GUID_format1(&switchTypeGuid, s));
+               goto Away;
+       }
+       pReqHandlerInfo = ReqHandlerAdd(switchTypeGuid,
+                                       switch_type_name,
+                                       controlfunc,
+                                       min_channel_bytes,
+                                       Server_Channel_Ok, Server_Channel_Init);
+       if (!pReqHandlerInfo) {
+               LOGERR("failed to add %s to server list\n",
+                      GUID_format1(&switchTypeGuid, s));
+               goto Away;
+       }
+
+       atomic_inc(&UisUtils_Registered_Services);
+       rc = 1;                 /* success */
+Away:
+       if (rc) {
+               if (chipset_DriverInfo)
+                       BusDeviceInfo_Init(chipset_DriverInfo,
+                                          "chipset", "uislib",
+                                          VERSION, NULL,
+                                          __DATE__, __TIME__);
+       } else
+               LOGERR("failed to register type %s.\n",
+                      GUID_format1(&switchTypeGuid, s));
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex);
+
+int
+uisctrl_unregister_req_handler_ex(GUID switchTypeGuid)
+{
+       char s[99];
+       int rc = 0;             /* assume failure */
+       LOGINF("type=%s.\n", GUID_format1(&switchTypeGuid, s));
+       if (ReqHandlerDel(switchTypeGuid) < 0) {
+               LOGERR("failed to remove %s from server list\n",
+                      GUID_format1(&switchTypeGuid, s));
+               goto Away;
+       }
+       atomic_dec(&UisUtils_Registered_Services);
+       rc = 1;                 /* success */
+Away:
+       if (!rc)
+               LOGERR("failed to unregister type %s.\n",
+                      GUID_format1(&switchTypeGuid, s));
+       return rc;
+}
+EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex);
+
+/*
+ * unsigned int util_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
+ *                                          void *skb_in,
+ *                                          unsigned int firstfraglen,
+ *                                          unsigned int frags_max,
+ *                                          struct phys_info frags[])
+ *
+ *     calling_ctx - input -   a string that is displayed to show
+ *                             who called * this func
+ *     void *skb_in -  skb whose frag info we're copying type is hidden so we
+ *                     don't need to include skbbuff in uisutils.h which is
+ *                     included in non-networking code.
+ *     unsigned int firstfraglen - input - length of first fragment in skb
+ *     unsigned int frags_max - input - max len of frags array
+ *     struct phys_info frags[] - output - frags array filled in on output
+ *                                         return value indicates number of
+ *                                         entries filled in frags
+ */
+unsigned int
+util_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in,
+                            unsigned int firstfraglen, unsigned int frags_max,
+                            struct phys_info frags[])
+{
+       unsigned int count = 0, ii, size, offset = 0, numfrags;
+       struct sk_buff *skb = skb_in;
+
+       numfrags = skb_shinfo(skb)->nr_frags;
+
+       while (firstfraglen) {
+               if (count == frags_max) {
+                       LOGERR("%s frags array too small: max:%d count:%d\n",
+                              calling_ctx, frags_max, count);
+                       return -1;      /* failure */
+               }
+               frags[count].pi_pfn =
+                   page_to_pfn(virt_to_page(skb->data + offset));
+               frags[count].pi_off =
+                   (unsigned long) (skb->data + offset) & PI_PAGE_MASK;
+               size =
+                   min(firstfraglen,
+                       (unsigned int) (PI_PAGE_SIZE - frags[count].pi_off));
+               /* can take smallest of firstfraglen(what's left) OR
+               * bytes left in the page
+               */
+               frags[count].pi_len = size;
+               firstfraglen -= size;
+               offset += size;
+               count++;
+       }
+       if (numfrags) {
+               if ((count + numfrags) > frags_max) {
+                       LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n",
+                            calling_ctx, frags_max, count + numfrags);
+                       return -1;      /* failure */
+               }
+
+               for (ii = 0; ii < numfrags; ii++) {
+                       count = add_physinfo_entries(page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[ii])),   /* pfn */
+                                                    skb_shinfo(skb)->frags[ii].
+                                                    page_offset,
+                                                    skb_shinfo(skb)->frags[ii].
+                                                    size, count, frags_max,
+                                                    frags);
+                       if (count == 0) {
+                               LOGERR("**** FAILED to add physinfo entries\n");
+                               return -1;      /* failure */
+                       }
+               }
+       }
+       if (skb_shinfo(skb)->frag_list) {
+               struct sk_buff *skbinlist;
+               int c;
+               for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist;
+                    skbinlist = skbinlist->next) {
+
+                       c = util_copy_fragsinfo_from_skb("recursive", skbinlist,
+                                                        skbinlist->len -
+                                                        skbinlist->data_len,
+                                                        frags_max - count,
+                                                        &frags[count]);
+                       if (c == -1) {
+                               LOGERR("**** FAILED recursive call failed\n");
+                               return -1;
+                       }
+                       count += c;
+               }
+       }
+       return count;
+}
+EXPORT_SYMBOL_GPL(util_copy_fragsinfo_from_skb);
+
+static LIST_HEAD(ReqHandlerInfo_list); /* list of ReqHandlerInfo_t */
+static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock);
+
+ReqHandlerInfo_t *
+ReqHandlerAdd(GUID switchTypeGuid,
+             const char *switch_type_name,
+             int (*controlfunc)(struct io_msgs *),
+             unsigned long min_channel_bytes,
+             int (*Server_Channel_Ok)(unsigned long channelBytes),
+             int (*Server_Channel_Init)
+              (void *x, unsigned char *clientStr, U32 clientStrLen, U64 bytes))
+{
+       ReqHandlerInfo_t *rc = NULL;
+
+       rc = UISMALLOC(sizeof(*rc), GFP_ATOMIC);
+       if (!rc)
+               return NULL;
+       memset(rc, 0, sizeof(*rc));
+       rc->switchTypeGuid = switchTypeGuid;
+       rc->controlfunc = controlfunc;
+       rc->min_channel_bytes = min_channel_bytes;
+       rc->Server_Channel_Ok = Server_Channel_Ok;
+       rc->Server_Channel_Init = Server_Channel_Init;
+       if (switch_type_name)
+               strncpy(rc->switch_type_name, switch_type_name,
+                       sizeof(rc->switch_type_name) - 1);
+       spin_lock(&ReqHandlerInfo_list_lock);
+       list_add_tail(&(rc->list_link), &ReqHandlerInfo_list);
+       spin_unlock(&ReqHandlerInfo_list_lock);
+
+       return rc;
+}
+
+ReqHandlerInfo_t *
+ReqHandlerFind(GUID switchTypeGuid)
+{
+       struct list_head *lelt, *tmp;
+       ReqHandlerInfo_t *entry = NULL;
+       spin_lock(&ReqHandlerInfo_list_lock);
+       list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
+               entry = list_entry(lelt, ReqHandlerInfo_t, list_link);
+               if (memcmp
+                   (&entry->switchTypeGuid, &switchTypeGuid,
+                    sizeof(GUID)) == 0) {
+                       spin_unlock(&ReqHandlerInfo_list_lock);
+                       return entry;
+               }
+       }
+       spin_unlock(&ReqHandlerInfo_list_lock);
+       return NULL;
+}
+
+int
+ReqHandlerDel(GUID switchTypeGuid)
+{
+       struct list_head *lelt, *tmp;
+       ReqHandlerInfo_t *entry = NULL;
+       int rc = -1;
+       spin_lock(&ReqHandlerInfo_list_lock);
+       list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
+               entry = list_entry(lelt, ReqHandlerInfo_t, list_link);
+               if (memcmp
+                   (&entry->switchTypeGuid, &switchTypeGuid,
+                    sizeof(GUID)) == 0) {
+                       list_del(lelt);
+                       UISFREE(entry, sizeof(*entry));
+                       rc++;
+               }
+       }
+       spin_unlock(&ReqHandlerInfo_list_lock);
+       return rc;
+}
diff --git a/drivers/staging/unisys/virthba/Kconfig b/drivers/staging/unisys/virthba/Kconfig
new file mode 100644 (file)
index 0000000..d2ef0fc
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys virthba configuration
+#
+
+config UNISYS_VIRTHBA
+       tristate "Unisys virthba driver"
+       depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB && UNISYS_UISLIB && UNISYS_VIRTPCI
+       ---help---
+       If you say Y here, you will enable the Unisys virthba driver.
+
diff --git a/drivers/staging/unisys/virthba/Makefile b/drivers/staging/unisys/virthba/Makefile
new file mode 100644 (file)
index 0000000..632b1c0
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# Makefile for Unisys virthba
+#
+
+obj-$(CONFIG_UNISYS_VIRTHBA)   += virthba.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/uislib
+ccflags-y += -Idrivers/staging/unisys/timskmod
+ccflags-y += -Idrivers/staging/unisys/visorchipset
+ccflags-y += -Idrivers/staging/unisys/virtpci
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c
new file mode 100644 (file)
index 0000000..dd5fe75
--- /dev/null
@@ -0,0 +1,1813 @@
+/* virthba.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+
+/* if you want to turn on some debugging of write device data or read
+ * device data, define these two undefs.  You will probably want to
+ * customize the code which is here since it was written assuming
+ * reading and writing a specific data file df.64M.txt which is a
+ * 64Megabyte file created by Art Nilson using a scritp I wrote called
+ * cr_test_data.pl.  The data file consists of 256 byte lines of text
+ * which start with an 8 digit sequence number, a colon, and then
+ * letters after that */
+
+#undef DBGINF
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "uisutils.h"
+#include "uisqueue.h"
+#include "uisthread.h"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <asm/param.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+
+#include "virthba.h"
+#include "virtpci.h"
+#include "visorchipset.h"
+#include "version.h"
+#include "guestlinuxdebug.h"
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC VIRT_HBA_PC_virthba_c
+#define __MYFILE__ "virthba.c"
+
+/* NOTE:  L1_CACHE_BYTES >=128 */
+#define DEVICE_ATTRIBUTE struct device_attribute
+
+/*****************************************************/
+/* Forward declarations                              */
+/*****************************************************/
+static int virthba_probe(struct virtpci_dev *dev,
+                        const struct pci_device_id *id);
+static void virthba_remove(struct virtpci_dev *dev);
+static int virthba_abort_handler(struct scsi_cmnd *scsicmd);
+static int virthba_bus_reset_handler(struct scsi_cmnd *scsicmd);
+static int virthba_device_reset_handler(struct scsi_cmnd *scsicmd);
+static int virthba_host_reset_handler(struct scsi_cmnd *scsicmd);
+static const char *virthba_get_info(struct Scsi_Host *shp);
+static int virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
+static int virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
+                                    void (*virthba_cmnd_done)(struct scsi_cmnd *));
+#ifdef DEF_SCSI_QCMD
+DEF_SCSI_QCMD(virthba_queue_command)
+#else
+#define virthba_queue_command virthba_queue_command_lck
+#endif
+static int virthba_slave_alloc(struct scsi_device *scsidev);
+static int virthba_slave_configure(struct scsi_device *scsidev);
+static void virthba_slave_destroy(struct scsi_device *scsidev);
+static int process_incoming_rsps(void *);
+static int virthba_serverup(struct virtpci_dev *virtpcidev);
+static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state);
+static void doDiskAddRemove(struct work_struct *work);
+static void virthba_serverdown_complete(struct work_struct *work);
+
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+                             size_t len, loff_t *offset);
+static ssize_t rqwu_proc_write(struct file *file, const char __user *buffer,
+                              size_t count, loff_t *ppos);
+static ssize_t enable_ints_read(struct file *file, char __user *buffer,
+                               size_t count, loff_t *ppos);
+static ssize_t enable_ints_write(struct file *file, const char __user *buffer,
+                                size_t count, loff_t *ppos);
+
+/*****************************************************/
+/* Globals                                           */
+/*****************************************************/
+
+int rsltq_wait_usecs = 4000;   /* Default 4ms */
+static unsigned int MaxBuffLen;
+
+/* Module options */
+char *virthba_options = "NONE";
+
+static const struct pci_device_id virthba_id_table[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_VIRTHBA)},
+       {0},
+};
+
+/* export virthba_id_table */
+MODULE_DEVICE_TABLE(pci, virthba_id_table);
+
+static struct workqueue_struct *virthba_serverdown_workqueue;
+
+static struct virtpci_driver virthba_driver = {
+       .name = "uisvirthba",
+       .version = VERSION,
+       .vertag = NULL,
+       .build_date = __DATE__,
+       .build_time = __TIME__,
+       .id_table = virthba_id_table,
+       .probe = virthba_probe,
+       .remove = virthba_remove,
+       .resume = virthba_serverup,
+       .suspend = virthba_serverdown
+};
+
+/* The Send and Recive Buffers of the IO Queue may both be full */
+#define MAX_PENDING_REQUESTS (MIN_NUMSIGNALS*2)
+#define INTERRUPT_VECTOR_MASK 0x3F
+
+struct scsipending {
+       char cmdtype;           /* Type of pointer that is being stored */
+       void *sent;             /* The Data being tracked */
+       /* struct scsi_cmnd *type for virthba_queue_command */
+       /* struct uiscmdrsp *type for management commands */
+};
+
+#define VIRTHBA_ERROR_COUNT 30
+#define IOS_ERROR_THRESHOLD 1000
+struct virtdisk_info {
+       U32 valid;
+       U32 channel, id, lun;   /* Disk Path */
+       atomic_t ios_threshold;
+       atomic_t error_count;
+       struct virtdisk_info *next;
+};
+/* Each Scsi_Host has a host_data area that contains this struct. */
+struct virthba_info {
+       struct Scsi_Host *scsihost;
+       struct virtpci_dev *virtpcidev;
+       struct list_head dev_info_list;
+       struct chaninfo chinfo;
+       struct InterruptInfo intr;      /* use recvInterrupt info to receive
+                                          interrupts when IOs complete */
+       int interrupt_vector;
+       struct scsipending pending[MAX_PENDING_REQUESTS]; /* Tracks the requests
+                                                            that have been */
+       /* forwarded to the IOVM and haven't returned yet */
+       unsigned int nextinsert;        /* Start search for next pending
+                                          free slot here */
+       spinlock_t privlock;
+       bool serverdown;
+       bool serverchangingstate;
+       unsigned long long acquire_failed_cnt;
+       unsigned long long interrupts_rcvd;
+       unsigned long long interrupts_notme;
+       unsigned long long interrupts_disabled;
+       struct work_struct serverdown_completion;
+       U64 *flags_addr;
+       atomic_t interrupt_rcvd;
+       wait_queue_head_t rsp_queue;
+       struct virtdisk_info head;
+};
+
+/* Work Data for DARWorkQ */
+struct diskaddremove {
+       U8 add;                 /* 0-remove, 1-add */
+       struct Scsi_Host *shost; /* Scsi Host for this virthba instance */
+       U32 channel, id, lun;   /* Disk Path */
+       struct diskaddremove *next;
+};
+
+#define virtpci_dev_to_virthba_virthba_get_info(d) \
+       container_of(d, struct virthba_info, virtpcidev)
+
+static DEVICE_ATTRIBUTE *virthba_shost_attrs[];
+static struct scsi_host_template virthba_driver_template = {
+       .name = "Unisys Virtual HBA",
+       .proc_name = "uisvirthba",
+       .info = virthba_get_info,
+       .ioctl = virthba_ioctl,
+       .queuecommand = virthba_queue_command,
+       .eh_abort_handler = virthba_abort_handler,
+       .eh_device_reset_handler = virthba_device_reset_handler,
+       .eh_bus_reset_handler = virthba_bus_reset_handler,
+       .eh_host_reset_handler = virthba_host_reset_handler,
+       .shost_attrs = virthba_shost_attrs,
+
+#define VIRTHBA_MAX_CMNDS 128
+       .can_queue = VIRTHBA_MAX_CMNDS,
+       .sg_tablesize = 64,     /* largest number of address/length pairs */
+       .this_id = -1,
+       .slave_alloc = virthba_slave_alloc,
+       .slave_configure = virthba_slave_configure,
+       .slave_destroy = virthba_slave_destroy,
+       .use_clustering = ENABLE_CLUSTERING,
+};
+
+struct virthba_devices_open {
+       struct virthba_info *virthbainfo;
+};
+
+static const struct file_operations proc_info_fops = {
+       .read = info_proc_read,
+};
+
+static const struct file_operations proc_rqwu_fops = {
+       .write = rqwu_proc_write,
+};
+
+static const struct file_operations proc_enable_ints_fops = {
+       .read = enable_ints_read,
+       .write = enable_ints_write,
+};
+
+
+#define VIRTHBASOPENMAX 1
+/* array of open devices maintained by open() and close(); */
+static struct virthba_devices_open VirtHbasOpen[VIRTHBASOPENMAX];
+static struct proc_dir_entry *virthba_proc_dir;
+static struct proc_dir_entry *info_proc_entry;
+static struct proc_dir_entry *rqwaitus_proc_entry;
+static struct proc_dir_entry *enable_ints_proc_entry;
+#define INFO_PROC_ENTRY_FN "info"
+#define ENABLE_INTS_ENTRY_FN "enable_ints"
+#define RQWU_PROC_ENTRY_FN "rqwait_usecs"
+#define DIR_PROC_ENTRY "virthba"
+
+/*****************************************************/
+/* Local Functions                                  */
+/*****************************************************/
+static int
+add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new)
+{
+       unsigned long flags;
+       int insert_location;
+
+       spin_lock_irqsave(&vhbainfo->privlock, flags);
+       insert_location = vhbainfo->nextinsert;
+       while (vhbainfo->pending[insert_location].sent != NULL) {
+               insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS;
+               if (insert_location == (int) vhbainfo->nextinsert) {
+                       LOGERR("Queue should be full. insert_location<<%d>>  Unable to find open slot for pending commands.\n",
+                            insert_location);
+                       spin_unlock_irqrestore(&vhbainfo->privlock, flags);
+                       return -1;
+               }
+       }
+
+       vhbainfo->pending[insert_location].cmdtype = cmdtype;
+       vhbainfo->pending[insert_location].sent = new;
+       vhbainfo->nextinsert = (insert_location + 1) % MAX_PENDING_REQUESTS;
+       spin_unlock_irqrestore(&vhbainfo->privlock, flags);
+
+       return insert_location;
+}
+
+static unsigned int
+add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype,
+                               void *new)
+{
+       int insert_location = add_scsipending_entry(vhbainfo, cmdtype, new);
+
+       while (insert_location == -1) {
+               LOGERR("Failed to find empty queue slot.  Waiting to try again\n");
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(msecs_to_jiffies(10));
+               insert_location = add_scsipending_entry(vhbainfo, cmdtype, new);
+       }
+
+       return (unsigned int) insert_location;
+}
+
+static void *
+del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del)
+{
+       unsigned long flags;
+       void *sent = NULL;
+
+       if (del >= MAX_PENDING_REQUESTS) {
+               LOGERR("Invalid queue position <<%lu>> given to delete. MAX_PENDING_REQUESTS <<%d>>\n",
+                    (unsigned long) del, MAX_PENDING_REQUESTS);
+       } else {
+               spin_lock_irqsave(&vhbainfo->privlock, flags);
+
+               if (vhbainfo->pending[del].sent == NULL)
+                       LOGERR("Deleting already cleared queue entry at <<%lu>>.\n",
+                            (unsigned long) del);
+
+               sent = vhbainfo->pending[del].sent;
+
+               vhbainfo->pending[del].cmdtype = 0;
+               vhbainfo->pending[del].sent = NULL;
+               spin_unlock_irqrestore(&vhbainfo->privlock, flags);
+       }
+
+       return sent;
+}
+
+/* DARWorkQ (Disk Add/Remove) */
+static struct work_struct DARWorkQ;
+struct diskaddremove *DARWorkQHead = NULL;
+spinlock_t DARWorkQLock;
+unsigned short DARWorkQSched = 0;
+#define QUEUE_DISKADDREMOVE(dar) { \
+       spin_lock_irqsave(&DARWorkQLock, flags); \
+       if (!DARWorkQHead) { \
+               DARWorkQHead = dar; \
+               dar->next = NULL; \
+       } \
+       else { \
+               dar->next = DARWorkQHead; \
+               DARWorkQHead = dar; \
+       } \
+       if (!DARWorkQSched) { \
+               schedule_work(&DARWorkQ); \
+               DARWorkQSched = 1; \
+       } \
+       spin_unlock_irqrestore(&DARWorkQLock, flags); \
+}
+
+static inline void
+SendDiskAddRemove(struct diskaddremove *dar)
+{
+       struct scsi_device *sdev;
+       int error;
+
+       sdev = scsi_device_lookup(dar->shost, dar->channel, dar->id, dar->lun);
+       if (sdev) {
+               if (!(dar->add))
+                       scsi_remove_device(sdev);
+       } else if (dar->add) {
+               error =
+                   scsi_add_device(dar->shost, dar->channel, dar->id,
+                                   dar->lun);
+               if (error)
+                       LOGERR("Failed scsi_add_device: host_no=%d[chan=%d:id=%d:lun=%d]\n",
+                            dar->shost->host_no, dar->channel, dar->id,
+                            dar->lun);
+       } else
+               LOGERR("Failed scsi_device_lookup:[chan=%d:id=%d:lun=%d]\n",
+                      dar->channel, dar->id, dar->lun);
+       kfree(dar);
+}
+
+/*****************************************************/
+/* DARWorkQ Handler Thread                           */
+/*****************************************************/
+static void
+doDiskAddRemove(struct work_struct *work)
+{
+       struct diskaddremove *dar;
+       struct diskaddremove *tmphead;
+       int i = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&DARWorkQLock, flags);
+       tmphead = DARWorkQHead;
+       DARWorkQHead = NULL;
+       DARWorkQSched = 0;
+       spin_unlock_irqrestore(&DARWorkQLock, flags);
+       while (tmphead) {
+               dar = tmphead;
+               tmphead = dar->next;
+               SendDiskAddRemove(dar);
+               i++;
+       }
+}
+
+/*****************************************************/
+/* Routine to add entry to DARWorkQ                  */
+/*****************************************************/
+static void
+process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp)
+{
+       struct diskaddremove *dar;
+       unsigned long flags;
+
+       dar = kmalloc(sizeof(struct diskaddremove), GFP_ATOMIC);
+       if (dar) {
+               memset(dar, 0, sizeof(struct diskaddremove));
+               dar->add = cmdrsp->disknotify.add;
+               dar->shost = shost;
+               dar->channel = cmdrsp->disknotify.channel;
+               dar->id = cmdrsp->disknotify.id;
+               dar->lun = cmdrsp->disknotify.lun;
+               QUEUE_DISKADDREMOVE(dar);
+       } else {
+               LOGERR("kmalloc failed for dar. host_no=%d[chan=%d:id=%d:lun=%d]\n",
+                    shost->host_no, cmdrsp->disknotify.channel,
+                    cmdrsp->disknotify.id, cmdrsp->disknotify.lun);
+       }
+}
+
+/*****************************************************/
+/* Probe Remove Functions                            */
+/*****************************************************/
+irqreturn_t
+virthba_ISR(int irq, void *dev_id)
+{
+       struct virthba_info *virthbainfo = (struct virthba_info *) dev_id;
+       pCHANNEL_HEADER pChannelHeader;
+       pSIGNAL_QUEUE_HEADER pqhdr;
+       U64 mask;
+       unsigned long long rc1;
+
+       if (virthbainfo == NULL)
+               return IRQ_NONE;
+       virthbainfo->interrupts_rcvd++;
+       pChannelHeader = virthbainfo->chinfo.queueinfo->chan;
+       if (((pChannelHeader->Features
+             & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0)
+           && ((pChannelHeader->Features & ULTRA_IO_DRIVER_DISABLES_INTS) !=
+               0)) {
+               virthbainfo->interrupts_disabled++;
+               mask = ~ULTRA_CHANNEL_ENABLE_INTS;
+               rc1 = uisqueue_InterlockedAnd(virthbainfo->flags_addr, mask);
+       }
+       if (SignalQueueIsEmpty(pChannelHeader, IOCHAN_FROM_IOPART)) {
+               virthbainfo->interrupts_notme++;
+               return IRQ_NONE;
+       }
+       pqhdr = (pSIGNAL_QUEUE_HEADER) ((char *) pChannelHeader +
+                                       pChannelHeader->oChannelSpace) +
+                                       IOCHAN_FROM_IOPART;
+       pqhdr->NumInterruptsReceived++;
+       atomic_set(&virthbainfo->interrupt_rcvd, 1);
+       wake_up_interruptible(&virthbainfo->rsp_queue);
+       return IRQ_HANDLED;
+}
+
+static int
+virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
+{
+       int error;
+       struct Scsi_Host *scsihost;
+       struct virthba_info *virthbainfo;
+       int rsp;
+       int i;
+       irq_handler_t handler = virthba_ISR;
+       pCHANNEL_HEADER pChannelHeader;
+       pSIGNAL_QUEUE_HEADER pqhdr;
+       U64 mask;
+
+       LOGVER("entering virthba_probe...\n");
+       LOGVER("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+              virtpcidev->deviceNo);
+
+       LOGINF("entering virthba_probe...\n");
+       LOGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+              virtpcidev->deviceNo);
+       POSTCODE_LINUX_2(VHBA_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       /* call scsi_host_alloc to register a scsi host adapter
+        * instance - this virthba that has just been created is an
+        * instance of a scsi host adapter. This scsi_host_alloc
+        * function allocates a new Scsi_Host struct & performs basic
+        * initializatoin.  The host is not published to the scsi
+        * midlayer until scsi_add_host is called.
+        */
+       DBGINF("calling scsi_host_alloc.\n");
+
+       /* arg 2 passed in length of extra space we want allocated
+        * with scsi_host struct for our own use scsi_host_alloc
+        * assign host_no
+        */
+       scsihost = scsi_host_alloc(&virthba_driver_template,
+                                  sizeof(struct virthba_info));
+       if (scsihost == NULL)
+               return -ENODEV;
+
+       DBGINF("scsihost: 0x%p, scsihost->this_id: %d, host_no: %d.\n",
+              scsihost, scsihost->this_id, scsihost->host_no);
+
+       scsihost->this_id = UIS_MAGIC_VHBA;
+       /* linux treats max-channel differently than max-id & max-lun.
+        * In the latter cases, those two values result in 0 to max-1
+        * (inclusive) being scanned. But in the case of channels, the
+        * scan is 0 to max (inclusive); so we will subtract one from
+        * the max-channel value.
+        */
+       LOGINF("virtpcidev->scsi.max.max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_io_size=%u\n",
+            (unsigned) virtpcidev->scsi.max.max_channel - 1,
+            (unsigned) virtpcidev->scsi.max.max_id,
+            (unsigned) virtpcidev->scsi.max.max_lun,
+            (unsigned) virtpcidev->scsi.max.cmd_per_lun,
+            (unsigned) virtpcidev->scsi.max.max_io_size);
+       scsihost->max_channel = (unsigned) virtpcidev->scsi.max.max_channel;
+       scsihost->max_id = (unsigned) virtpcidev->scsi.max.max_id;
+       scsihost->max_lun = (unsigned) virtpcidev->scsi.max.max_lun;
+       scsihost->cmd_per_lun = (unsigned) virtpcidev->scsi.max.cmd_per_lun;
+       scsihost->max_sectors =
+           (unsigned short) (virtpcidev->scsi.max.max_io_size >> 9);
+       scsihost->sg_tablesize =
+           (unsigned short) (virtpcidev->scsi.max.max_io_size / PAGE_SIZE);
+       if (scsihost->sg_tablesize > MAX_PHYS_INFO)
+               scsihost->sg_tablesize = MAX_PHYS_INFO;
+       LOGINF("scsihost->max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n",
+            scsihost->max_channel, scsihost->max_id, scsihost->max_lun,
+            scsihost->cmd_per_lun, scsihost->max_sectors,
+            scsihost->sg_tablesize);
+       LOGINF("scsihost->can_queue=%u, scsihost->cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n",
+            scsihost->can_queue, scsihost->cmd_per_lun, scsihost->max_sectors,
+            scsihost->sg_tablesize);
+
+       DBGINF("calling scsi_add_host\n");
+
+       /* this creates "host%d" in sysfs.  If 2nd argument is NULL,
+        * then this generic /sys/devices/platform/host?  device is
+        * created and /sys/scsi_host/host? ->
+        * /sys/devices/platform/host?  If 2nd argument is not NULL,
+        * then this generic /sys/devices/<path>/host? is created and
+        * host? points to that device instead.
+        */
+       error = scsi_add_host(scsihost, &virtpcidev->generic_dev);
+       if (error) {
+               LOGERR("scsi_add_host ****FAILED 0x%x  TBD - RECOVER\n", error);
+               POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               /* decr refcount on scsihost which was incremented by
+                * scsi_add_host so the scsi_host gets deleted
+                */
+               scsi_host_put(scsihost);
+               return -ENODEV;
+       }
+
+       virthbainfo = (struct virthba_info *) scsihost->hostdata;
+       memset(virthbainfo, 0, sizeof(struct virthba_info));
+       for (i = 0; i < VIRTHBASOPENMAX; i++) {
+               if (VirtHbasOpen[i].virthbainfo == NULL) {
+                       VirtHbasOpen[i].virthbainfo = virthbainfo;
+                       break;
+               }
+       }
+       virthbainfo->interrupt_vector = -1;
+       virthbainfo->chinfo.queueinfo = &virtpcidev->queueinfo;
+       virthbainfo->virtpcidev = virtpcidev;
+       spin_lock_init(&virthbainfo->chinfo.insertlock);
+
+       DBGINF("generic_dev: 0x%p, queueinfo: 0x%p.\n",
+              &virtpcidev->generic_dev, &virtpcidev->queueinfo);
+
+       init_waitqueue_head(&virthbainfo->rsp_queue);
+       spin_lock_init(&virthbainfo->privlock);
+       memset(&virthbainfo->pending, 0, sizeof(virthbainfo->pending));
+       virthbainfo->serverdown = false;
+       virthbainfo->serverchangingstate = false;
+
+       virthbainfo->intr = virtpcidev->intr;
+       /* save of host within virthba_info */
+       virthbainfo->scsihost = scsihost;
+
+       /* save of host within virtpci_dev */
+       virtpcidev->scsi.scsihost = scsihost;
+
+       /* Setup workqueue for serverdown messages */
+       INIT_WORK(&virthbainfo->serverdown_completion,
+                 virthba_serverdown_complete);
+
+       virthbainfo->chinfo.queueinfo->chan->Features |=
+           ULTRA_IO_CHANNEL_IS_POLLING;
+       /* start thread that will receive scsicmnd responses */
+       DBGINF("starting rsp thread -- queueinfo: 0x%p, threadinfo: 0x%p.\n",
+              virthbainfo->chinfo.queueinfo, &virthbainfo->chinfo.threadinfo);
+
+       pChannelHeader = virthbainfo->chinfo.queueinfo->chan;
+       pqhdr = (pSIGNAL_QUEUE_HEADER) ((char *) pChannelHeader +
+                                       pChannelHeader->oChannelSpace) +
+                                       IOCHAN_FROM_IOPART;
+       virthbainfo->flags_addr = &pqhdr->FeatureFlags;
+
+       if (!uisthread_start(&virthbainfo->chinfo.threadinfo,
+                            process_incoming_rsps,
+                            virthbainfo, "vhba_incoming")) {
+               LOGERR("uisthread_start rsp ****FAILED\n");
+               /* decr refcount on scsihost which was incremented by
+                * scsi_add_host so the scsi_host gets deleted
+                */
+               POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               scsi_host_put(scsihost);
+               return -ENODEV;
+       }
+       LOGINF("sendInterruptHandle=0x%16llX",
+              virthbainfo->intr.sendInterruptHandle);
+       LOGINF("recvInterruptHandle=0x%16llX",
+              virthbainfo->intr.recvInterruptHandle);
+       LOGINF("recvInterruptVector=0x%8X",
+              virthbainfo->intr.recvInterruptVector);
+       LOGINF("recvInterruptShared=0x%2X",
+              virthbainfo->intr.recvInterruptShared);
+       LOGINF("scsihost.hostt->name=%s", scsihost->hostt->name);
+       virthbainfo->interrupt_vector =
+           virthbainfo->intr.recvInterruptHandle & INTERRUPT_VECTOR_MASK;
+       rsp = request_irq(virthbainfo->interrupt_vector, handler, IRQF_SHARED,
+                         scsihost->hostt->name, virthbainfo);
+       if (rsp != 0) {
+               LOGERR("request_irq(%d) uislib_virthba_ISR request failed with rsp=%d\n",
+                      virthbainfo->interrupt_vector, rsp);
+               virthbainfo->interrupt_vector = -1;
+               POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+       } else {
+               U64 *Features_addr =
+                   &virthbainfo->chinfo.queueinfo->chan->Features;
+               LOGERR("request_irq(%d) uislib_virthba_ISR request succeeded\n",
+                      virthbainfo->interrupt_vector);
+               mask = ~(ULTRA_IO_CHANNEL_IS_POLLING |
+                        ULTRA_IO_DRIVER_DISABLES_INTS);
+               uisqueue_InterlockedAnd(Features_addr, mask);
+               mask = ULTRA_IO_DRIVER_ENABLES_INTS;
+               uisqueue_InterlockedOr(Features_addr, mask);
+               rsltq_wait_usecs = 4000000;
+       }
+
+       DBGINF("calling scsi_scan_host.\n");
+       scsi_scan_host(scsihost);
+       DBGINF("return from scsi_scan_host.\n");
+
+       LOGINF("virthba added scsihost:0x%p\n", scsihost);
+       POSTCODE_LINUX_2(VHBA_PROBE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       return 0;
+}
+
+static void
+virthba_remove(struct virtpci_dev *virtpcidev)
+{
+       struct virthba_info *virthbainfo;
+       struct Scsi_Host *scsihost =
+           (struct Scsi_Host *) virtpcidev->scsi.scsihost;
+
+       LOGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+              virtpcidev->deviceNo);
+       virthbainfo = (struct virthba_info *) scsihost->hostdata;
+       if (virthbainfo->interrupt_vector != -1)
+               free_irq(virthbainfo->interrupt_vector, virthbainfo);
+       LOGINF("Removing virtpcidev: 0x%p, virthbainfo: 0x%p\n", virtpcidev,
+              virthbainfo);
+
+       DBGINF("removing scsihost: 0x%p, scsihost->this_id: %d\n", scsihost,
+              scsihost->this_id);
+       scsi_remove_host(scsihost);
+
+       DBGINF("stopping thread.\n");
+       uisthread_stop(&virthbainfo->chinfo.threadinfo);
+
+       DBGINF("calling scsi_host_put\n");
+
+       /* decr refcount on scsihost which was incremented by
+        * scsi_add_host so the scsi_host gets deleted
+        */
+       scsi_host_put(scsihost);
+       LOGINF("virthba removed scsi_host.\n");
+}
+
+static int
+forward_vdiskmgmt_command(VDISK_MGMT_TYPES vdiskcmdtype,
+                         struct Scsi_Host *scsihost,
+                         struct uisscsi_dest *vdest)
+{
+       struct uiscmdrsp *cmdrsp;
+       struct virthba_info *virthbainfo =
+           (struct virthba_info *) scsihost->hostdata;
+       int notifyresult = 0xffff;
+       wait_queue_head_t notifyevent;
+
+       LOGINF("vDiskMgmt:%d %d:%d:%d\n", vdiskcmdtype,
+              vdest->channel, vdest->id, vdest->lun);
+
+       if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
+               DBGINF("Server is down/changing state. Returning Failure.\n");
+               return FAILED;
+       }
+
+       ALLOC_CMDRSP(cmdrsp);
+       if (cmdrsp == NULL) {
+               LOGERR("kmalloc of cmdrsp failed.\n");
+               return FAILED;  /* reject */
+       }
+
+       init_waitqueue_head(&notifyevent);
+
+       /* issue VDISK_MGMT_CMD
+        * set type to command - as opposed to task mgmt
+        */
+       cmdrsp->cmdtype = CMD_VDISKMGMT_TYPE;
+       /* specify the event that has to be triggered when this cmd is
+        * complete
+        */
+       cmdrsp->vdiskmgmt.notify = (void *) &notifyevent;
+       cmdrsp->vdiskmgmt.notifyresult = (void *) &notifyresult;
+
+       /* save destination */
+       cmdrsp->vdiskmgmt.vdisktype = vdiskcmdtype;
+       cmdrsp->vdiskmgmt.vdest.channel = vdest->channel;
+       cmdrsp->vdiskmgmt.vdest.id = vdest->id;
+       cmdrsp->vdiskmgmt.vdest.lun = vdest->lun;
+       cmdrsp->vdiskmgmt.scsicmd =
+           (void *) (uintptr_t)
+               add_scsipending_entry_with_wait(virthbainfo, CMD_VDISKMGMT_TYPE,
+                                               (void *) cmdrsp);
+
+       uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo,
+                                            cmdrsp, IOCHAN_TO_IOPART,
+                                            &virthbainfo->chinfo.insertlock,
+                                            DONT_ISSUE_INTERRUPT, (U64) NULL,
+                                            OK_TO_WAIT, "vhba");
+       LOGINF("VdiskMgmt waiting on event notifyevent=0x%p\n",
+              cmdrsp->scsitaskmgmt.notify);
+       wait_event(notifyevent, notifyresult != 0xffff);
+       LOGINF("VdiskMgmt complete; result:%d\n", cmdrsp->vdiskmgmt.result);
+       kfree(cmdrsp);
+       return SUCCESS;
+}
+
+/*****************************************************/
+/* Scsi Host support functions                       */
+/*****************************************************/
+
+static int
+forward_taskmgmt_command(TASK_MGMT_TYPES tasktype, struct scsi_device *scsidev)
+{
+       struct uiscmdrsp *cmdrsp;
+       struct virthba_info *virthbainfo =
+           (struct virthba_info *) scsidev->host->hostdata;
+       int notifyresult = 0xffff;
+       wait_queue_head_t notifyevent;
+
+       LOGINF("TaskMgmt:%d %d:%d:%d\n", tasktype,
+              scsidev->channel, scsidev->id, scsidev->lun);
+
+       if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
+               DBGINF("Server is down/changing state. Returning Failure.\n");
+               return FAILED;
+       }
+
+       ALLOC_CMDRSP(cmdrsp);
+       if (cmdrsp == NULL) {
+               LOGERR("kmalloc of cmdrsp failed.\n");
+               return FAILED;  /* reject */
+       }
+
+       init_waitqueue_head(&notifyevent);
+
+       /* issue TASK_MGMT_ABORT_TASK */
+       /* set type to command - as opposed to task mgmt */
+       cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE;
+       /* specify the event that has to be triggered when this */
+       /* cmd is complete */
+       cmdrsp->scsitaskmgmt.notify = (void *) &notifyevent;
+       cmdrsp->scsitaskmgmt.notifyresult = (void *) &notifyresult;
+
+       /* save destination */
+       cmdrsp->scsitaskmgmt.tasktype = tasktype;
+       cmdrsp->scsitaskmgmt.vdest.channel = scsidev->channel;
+       cmdrsp->scsitaskmgmt.vdest.id = scsidev->id;
+       cmdrsp->scsitaskmgmt.vdest.lun = scsidev->lun;
+       cmdrsp->scsitaskmgmt.scsicmd =
+           (void *) (uintptr_t)
+               add_scsipending_entry_with_wait(virthbainfo,
+                                               CMD_SCSITASKMGMT_TYPE,
+                                               (void *) cmdrsp);
+
+       uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo,
+                                            cmdrsp, IOCHAN_TO_IOPART,
+                                            &virthbainfo->chinfo.insertlock,
+                                            DONT_ISSUE_INTERRUPT, (U64) NULL,
+                                            OK_TO_WAIT, "vhba");
+       LOGINF("TaskMgmt waiting on event notifyevent=0x%p\n",
+              cmdrsp->scsitaskmgmt.notify);
+       wait_event(notifyevent, notifyresult != 0xffff);
+       LOGINF("TaskMgmt complete; result:%d\n", cmdrsp->scsitaskmgmt.result);
+       kfree(cmdrsp);
+       return SUCCESS;
+}
+
+/* The abort handler returns SUCCESS if it has succeeded to make LLDD
+ * and all related hardware forget about the scmd.
+ */
+static int
+virthba_abort_handler(struct scsi_cmnd *scsicmd)
+{
+       /* issue TASK_MGMT_ABORT_TASK */
+       struct scsi_device *scsidev;
+       struct virtdisk_info *vdisk;
+
+       scsidev = scsicmd->device;
+       for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+            vdisk->next; vdisk = vdisk->next) {
+               if ((scsidev->channel == vdisk->channel)
+                   && (scsidev->id == vdisk->id)
+                   && (scsidev->lun == vdisk->lun)) {
+                       if (atomic_read(&vdisk->error_count) <
+                           VIRTHBA_ERROR_COUNT) {
+                               atomic_inc(&vdisk->error_count);
+                               POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC,
+                                                POSTCODE_SEVERITY_INFO);
+                       } else
+                               atomic_set(&vdisk->ios_threshold,
+                                          IOS_ERROR_THRESHOLD);
+               }
+       }
+       return forward_taskmgmt_command(TASK_MGMT_ABORT_TASK, scsicmd->device);
+}
+
+static int
+virthba_bus_reset_handler(struct scsi_cmnd *scsicmd)
+{
+       /* issue TASK_MGMT_TARGET_RESET for each target on the bus */
+       struct scsi_device *scsidev;
+       struct virtdisk_info *vdisk;
+
+       scsidev = scsicmd->device;
+       for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+            vdisk->next; vdisk = vdisk->next) {
+               if ((scsidev->channel == vdisk->channel)
+                   && (scsidev->id == vdisk->id)
+                   && (scsidev->lun == vdisk->lun)) {
+                       if (atomic_read(&vdisk->error_count) <
+                           VIRTHBA_ERROR_COUNT) {
+                               atomic_inc(&vdisk->error_count);
+                               POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC,
+                                                POSTCODE_SEVERITY_INFO);
+                       } else
+                               atomic_set(&vdisk->ios_threshold,
+                                          IOS_ERROR_THRESHOLD);
+               }
+       }
+       return forward_taskmgmt_command(TASK_MGMT_BUS_RESET, scsicmd->device);
+}
+
+static int
+virthba_device_reset_handler(struct scsi_cmnd *scsicmd)
+{
+       /* issue TASK_MGMT_LUN_RESET */
+       struct scsi_device *scsidev;
+       struct virtdisk_info *vdisk;
+
+       scsidev = scsicmd->device;
+       for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+            vdisk->next; vdisk = vdisk->next) {
+               if ((scsidev->channel == vdisk->channel)
+                   && (scsidev->id == vdisk->id)
+                   && (scsidev->lun == vdisk->lun)) {
+                       if (atomic_read(&vdisk->error_count) <
+                           VIRTHBA_ERROR_COUNT) {
+                               atomic_inc(&vdisk->error_count);
+                               POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC,
+                                                POSTCODE_SEVERITY_INFO);
+                       } else
+                               atomic_set(&vdisk->ios_threshold,
+                                          IOS_ERROR_THRESHOLD);
+               }
+       }
+       return forward_taskmgmt_command(TASK_MGMT_LUN_RESET, scsicmd->device);
+}
+
+static int
+virthba_host_reset_handler(struct scsi_cmnd *scsicmd)
+{
+       /* issue TASK_MGMT_TARGET_RESET for each target on each bus for host */
+       LOGERR("virthba_host_reset_handler Not yet implemented\n");
+       return SUCCESS;
+}
+
+static char virthba_get_info_str[256];
+
+static const char *
+virthba_get_info(struct Scsi_Host *shp)
+{
+       /* Return version string */
+       sprintf(virthba_get_info_str, "virthba, version %s\n", VIRTHBA_VERSION);
+       return virthba_get_info_str;
+}
+
+static int
+virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
+{
+       DBGINF("In virthba_ioctl: ioctl: cmd=0x%x\n", cmd);
+       return -EINVAL;
+}
+
+/* This returns SCSI_MLQUEUE_DEVICE_BUSY if the signal queue to IOpart
+ * is full.
+ */
+static int
+virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
+                         void (*virthba_cmnd_done)(struct scsi_cmnd *))
+{
+       struct scsi_device *scsidev = scsicmd->device;
+       int insert_location;
+       unsigned char op;
+       unsigned char *cdb = scsicmd->cmnd;
+       struct Scsi_Host *scsihost = scsidev->host;
+       struct uiscmdrsp *cmdrsp;
+       unsigned int i;
+       struct virthba_info *virthbainfo =
+           (struct virthba_info *) scsihost->hostdata;
+       struct scatterlist *sg = NULL;
+       struct scatterlist *sgl = NULL;
+       int sg_failed = 0;
+
+       if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
+               DBGINF("Server is down/changing state. Returning SCSI_MLQUEUE_DEVICE_BUSY.\n");
+               return SCSI_MLQUEUE_DEVICE_BUSY;
+       }
+
+       ALLOC_CMDRSP(cmdrsp);
+       if (cmdrsp == NULL) {
+               LOGERR("kmalloc of cmdrsp failed.\n");
+               return 1;       /* reject the command */
+       }
+
+       /* now saving everything we need from scsi_cmd into cmdrsp
+        * before we queue cmdrsp set type to command - as opposed to
+        * task mgmt
+        */
+       cmdrsp->cmdtype = CMD_SCSI_TYPE;
+       /* save the pending insertion location.  Deletion from pending
+        * will return the scsicmd pointer for completion
+        */
+       insert_location =
+           add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *) scsicmd);
+       if (insert_location != -1) {
+               cmdrsp->scsi.scsicmd = (void *) (uintptr_t) insert_location;
+       } else {
+               LOGERR("Queue is full. Returning busy.\n");
+               kfree(cmdrsp);
+               return SCSI_MLQUEUE_DEVICE_BUSY;
+       }
+       /* save done function that we have call when cmd is complete */
+       scsicmd->scsi_done = virthba_cmnd_done;
+       /* save destination */
+       cmdrsp->scsi.vdest.channel = scsidev->channel;
+       cmdrsp->scsi.vdest.id = scsidev->id;
+       cmdrsp->scsi.vdest.lun = scsidev->lun;
+       /* save datadir */
+       cmdrsp->scsi.data_dir = scsicmd->sc_data_direction;
+       memcpy(cmdrsp->scsi.cmnd, cdb, MAX_CMND_SIZE);
+
+       cmdrsp->scsi.bufflen = scsi_bufflen(scsicmd);
+
+       /* keep track of the max buffer length so far. */
+       if (cmdrsp->scsi.bufflen > MaxBuffLen)
+               MaxBuffLen = cmdrsp->scsi.bufflen;
+
+       if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) {
+               LOGERR("scsicmd use_sg:%d greater than MAX:%d\n",
+                      scsi_sg_count(scsicmd), MAX_PHYS_INFO);
+               del_scsipending_entry(virthbainfo, (uintptr_t) insert_location);
+               kfree(cmdrsp);
+               return 1;       /* reject the command */
+       }
+
+       /* This is what we USED to do when we assumed we were running */
+       /* uissd & virthba on the same Linux system. */
+       /* cmdrsp->scsi.buffer = scsicmd->request_buffer; */
+       /* The following code does NOT make that assumption. */
+       /* convert buffer to phys information */
+       if (scsi_sg_count(scsicmd) == 0) {
+               if (scsi_bufflen(scsicmd) > 0) {
+                       LOGERR("**** FAILED No scatter list for bufflen > 0\n");
+                       BUG_ON(scsi_sg_count(scsicmd) == 0);
+               }
+               DBGINF("No sg; buffer:0x%p bufflen:%d\n",
+                      scsi_sglist(scsicmd), scsi_bufflen(scsicmd));
+       } else {
+               /* buffer is scatterlist - copy it out */
+               sgl = scsi_sglist(scsicmd);
+
+               for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) {
+
+                       cmdrsp->scsi.gpi_list[i].address = sg_phys(sg);
+                       cmdrsp->scsi.gpi_list[i].length = sg->length;
+                       if ((i != 0) && (sg->offset != 0))
+                               LOGINF("Offset on a sg_entry other than zero =<<%d>>.\n",
+                                    sg->offset);
+               }
+
+               if (sg_failed) {
+                       LOGERR("Start sg_list dump (entries %d, bufflen %d)...\n",
+                            scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen);
+                       for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) {
+                               LOGERR("   Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n",
+                                    i, sg_page(sg),
+                                    (unsigned long long) sg_phys(sg),
+                                    sg->offset, sg->length);
+                       }
+                       LOGERR("Done sg_list dump.\n");
+                       /* BUG(); ***** For now, let it fail in uissd
+                        * if it is a problem, as it might just
+                        * work
+                        */
+               }
+
+               cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd);
+       }
+
+       op = cdb[0];
+       i = uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo,
+                                                cmdrsp, IOCHAN_TO_IOPART,
+                                                &virthbainfo->chinfo.
+                                                insertlock,
+                                                DONT_ISSUE_INTERRUPT,
+                                                (U64) NULL, DONT_WAIT, "vhba");
+       if (i == 0) {
+               /* queue must be full - and we said don't wait - return busy */
+               LOGERR("uisqueue_put_cmdrsp_with_lock ****FAILED\n");
+               kfree(cmdrsp);
+               del_scsipending_entry(virthbainfo, (uintptr_t) insert_location);
+               return SCSI_MLQUEUE_DEVICE_BUSY;
+       }
+
+       /* we're done with cmdrsp space - data from it has been copied
+        * into channel - free it now.
+        */
+       kfree(cmdrsp);
+       return 0;               /* non-zero implies host/device is busy */
+}
+
+static int
+virthba_slave_alloc(struct scsi_device *scsidev)
+{
+       /* this called by the midlayer before scan for new devices -
+        * LLD can alloc any struc & do init if needed.
+        */
+       struct virtdisk_info *vdisk;
+       struct virtdisk_info *tmpvdisk;
+       struct virthba_info *virthbainfo;
+       struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host;
+
+       virthbainfo = (struct virthba_info *) scsihost->hostdata;
+       if (!virthbainfo) {
+               LOGERR("Could not find virthba_info for scsihost\n");
+               return 0;       /* even though we errored, treat as success */
+       }
+       for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) {
+               if (vdisk->next->valid &&
+                   (vdisk->next->channel == scsidev->channel) &&
+                   (vdisk->next->id == scsidev->id) &&
+                   (vdisk->next->lun == scsidev->lun))
+                       return 0;
+       }
+       tmpvdisk = kmalloc(sizeof(struct virtdisk_info), GFP_ATOMIC);
+       if (!tmpvdisk) {        /* error allocating */
+               LOGERR("Could not allocate memory for disk\n");
+               return 0;
+       }
+       memset(tmpvdisk, 0, sizeof(struct virtdisk_info));
+       tmpvdisk->channel = scsidev->channel;
+       tmpvdisk->id = scsidev->id;
+       tmpvdisk->lun = scsidev->lun;
+       tmpvdisk->valid = 1;
+       vdisk->next = tmpvdisk;
+       return 0;               /* success */
+}
+
+static int
+virthba_slave_configure(struct scsi_device *scsidev)
+{
+       return 0;               /* success */
+}
+
+static void
+virthba_slave_destroy(struct scsi_device *scsidev)
+{
+       /* midlevel calls this after device has been quiesced and
+        * before it is to be deleted.
+        */
+       struct virtdisk_info *vdisk, *delvdisk;
+       struct virthba_info *virthbainfo;
+       struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host;
+
+       virthbainfo = (struct virthba_info *) scsihost->hostdata;
+       if (!virthbainfo)
+               LOGERR("Could not find virthba_info for scsihost\n");
+       for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) {
+               if (vdisk->next->valid &&
+                   (vdisk->next->channel == scsidev->channel) &&
+                   (vdisk->next->id == scsidev->id) &&
+                   (vdisk->next->lun == scsidev->lun)) {
+                       delvdisk = vdisk->next;
+                       vdisk->next = vdisk->next->next;
+                       kfree(delvdisk);
+                       return;
+               }
+       }
+       return;
+}
+
+/*****************************************************/
+/* Scsi Cmnd support thread                          */
+/*****************************************************/
+
+static void
+do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
+{
+       struct virtdisk_info *vdisk;
+       struct scsi_device *scsidev;
+       struct sense_data *sd;
+
+       scsidev = scsicmd->device;
+       memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE);
+       sd = (struct sense_data *) scsicmd->sense_buffer;
+
+       /* Do not log errors for disk-not-present inquiries */
+       if ((cmdrsp->scsi.cmnd[0] == INQUIRY) &&
+           (host_byte(cmdrsp->scsi.linuxstat) == DID_NO_CONNECT) &&
+           (cmdrsp->scsi.addlstat == ADDL_SEL_TIMEOUT))
+               return;
+
+       /* Okay see what our error_count is here.... */
+       for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+            vdisk->next; vdisk = vdisk->next) {
+               if ((scsidev->channel != vdisk->channel)
+                   || (scsidev->id != vdisk->id)
+                   || (scsidev->lun != vdisk->lun))
+                       continue;
+
+               if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) {
+                       atomic_inc(&vdisk->error_count);
+                       LOGERR("SCSICMD ****FAILED scsicmd:0x%p op:0x%x <%d:%d:%d:%d> 0x%x-0x%x-0x%x-0x%x-0x%x.\n",
+                              scsicmd, cmdrsp->scsi.cmnd[0],
+                              scsidev->host->host_no, scsidev->id,
+                              scsidev->channel, scsidev->lun,
+                              cmdrsp->scsi.linuxstat, sd->Valid, sd->SenseKey,
+                              sd->AdditionalSenseCode,
+                              sd->AdditionalSenseCodeQualifier);
+                       if (atomic_read(&vdisk->error_count) ==
+                           VIRTHBA_ERROR_COUNT) {
+                               LOGERR("Throtling SCSICMD errors disk <%d:%d:%d:%d>\n",
+                                    scsidev->host->host_no, scsidev->id,
+                                    scsidev->channel, scsidev->lun);
+                       }
+                       atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD);
+               }
+       }
+}
+
+static void
+do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
+{
+       struct scsi_device *scsidev;
+       unsigned char buf[36];
+       struct scatterlist *sg;
+       unsigned int i;
+       char *thispage;
+       char *thispage_orig;
+       int bufind = 0;
+       struct virtdisk_info *vdisk;
+
+       scsidev = scsicmd->device;
+       if ((cmdrsp->scsi.cmnd[0] == INQUIRY)
+           && (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) {
+               if (cmdrsp->scsi.no_disk_result == 0)
+                       return;
+
+               /* Linux scsi code is weird; it wants
+                * a device at Lun 0 to issue report
+                * luns, but we don't want a disk
+                * there so we'll present a processor
+                * there. */
+               SET_NO_DISK_INQUIRY_RESULT(buf, cmdrsp->scsi.bufflen,
+                                          scsidev->lun,
+                                          DEV_DISK_CAPABLE_NOT_PRESENT,
+                                          DEV_NOT_CAPABLE);
+
+               if (scsi_sg_count(scsicmd) == 0) {
+                       if (scsi_bufflen(scsicmd) > 0) {
+                               LOGERR("**** FAILED No scatter list for bufflen > 0\n");
+                               BUG_ON(scsi_sg_count(scsicmd) ==
+                                      0);
+                       }
+                       memcpy(scsi_sglist(scsicmd), buf,
+                              cmdrsp->scsi.bufflen);
+                       return;
+               }
+
+               sg = scsi_sglist(scsicmd);
+               for (i = 0; i < scsi_sg_count(scsicmd); i++) {
+                       DBGVER("copying OUT OF buf into 0x%p %d\n",
+                            sg_page(sg + i), sg[i].length);
+                       thispage_orig = kmap_atomic(sg_page(sg + i));
+                       thispage = (void *) ((unsigned long)thispage_orig |
+                                            sg[i].offset);
+                       memcpy(thispage, buf + bufind, sg[i].length);
+                       kunmap_atomic(thispage_orig);
+                       bufind += sg[i].length;
+               }
+       } else {
+
+               vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head;
+               for ( ; vdisk->next; vdisk = vdisk->next) {
+                       if ((scsidev->channel != vdisk->channel)
+                           || (scsidev->id != vdisk->id)
+                           || (scsidev->lun != vdisk->lun))
+                               continue;
+
+                       if (atomic_read(&vdisk->ios_threshold) > 0) {
+                               atomic_dec(&vdisk->ios_threshold);
+                               if (atomic_read(&vdisk->ios_threshold) == 0) {
+                                       LOGERR("Resetting error count for disk\n");
+                                       atomic_set(&vdisk->error_count, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void
+complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
+{
+       DBGINF("cmdrsp: 0x%p, scsistat:0x%x.\n", cmdrsp, cmdrsp->scsi.scsistat);
+
+       /* take what we need out of cmdrsp and complete the scsicmd */
+       scsicmd->result = cmdrsp->scsi.linuxstat;
+       if (cmdrsp->scsi.linuxstat)
+               do_scsi_linuxstat(cmdrsp, scsicmd);
+       else
+               do_scsi_nolinuxstat(cmdrsp, scsicmd);
+
+       if (scsicmd->scsi_done) {
+               DBGVER("Scsi_DONE\n");
+               scsicmd->scsi_done(scsicmd);
+       }
+}
+
+static inline void
+complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp)
+{
+       /* copy the result of the taskmgmt and */
+       /* wake up the error handler that is waiting for this */
+       *(int *) cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result;
+       wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify);
+       LOGINF("set notify result to %d\n", cmdrsp->vdiskmgmt.result);
+}
+
+static inline void
+complete_taskmgmt_command(struct uiscmdrsp *cmdrsp)
+{
+       /* copy the result of the taskmgmt and */
+       /* wake up the error handler that is waiting for this */
+       *(int *) cmdrsp->scsitaskmgmt.notifyresult =
+           cmdrsp->scsitaskmgmt.result;
+       wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify);
+       LOGINF("set notify result to %d\n", cmdrsp->scsitaskmgmt.result);
+}
+
+static void
+drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc,
+               struct uiscmdrsp *cmdrsp)
+{
+       unsigned long flags;
+       int qrslt = 0;
+       struct scsi_cmnd *scsicmd;
+       struct Scsi_Host *shost = virthbainfo->scsihost;
+
+       while (1) {
+               spin_lock_irqsave(&virthbainfo->chinfo.insertlock, flags);
+               if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(dc->queueinfo->chan,
+                                                    "vhba", NULL)) {
+                       spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock,
+                                              flags);
+                       virthbainfo->acquire_failed_cnt++;
+                       break;
+               }
+               qrslt = uisqueue_get_cmdrsp(dc->queueinfo, cmdrsp,
+                                           IOCHAN_FROM_IOPART);
+               ULTRA_CHANNEL_CLIENT_RELEASE_OS(dc->queueinfo->chan,
+                                               "vhba", NULL);
+               spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, flags);
+               if (qrslt == 0)
+                       break;
+               if (cmdrsp->cmdtype == CMD_SCSI_TYPE) {
+                       /* scsicmd location is returned by the
+                        * deletion
+                        */
+                       scsicmd = del_scsipending_entry(virthbainfo,
+                                       (uintptr_t) cmdrsp->scsi.scsicmd);
+                       if (!scsicmd)
+                               break;
+                       /* complete the orig cmd */
+                       complete_scsi_command(cmdrsp, scsicmd);
+               } else if (cmdrsp->cmdtype == CMD_SCSITASKMGMT_TYPE) {
+                       if (!del_scsipending_entry(virthbainfo,
+                                  (uintptr_t) cmdrsp->scsitaskmgmt.scsicmd))
+                               break;
+                       complete_taskmgmt_command(cmdrsp);
+               } else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) {
+                       /* The vHba pointer has no meaning in
+                        * a Client/Guest Partition. Let's be
+                        * safe and set it to NULL now.  Do
+                        * not use it here! */
+                       cmdrsp->disknotify.vHba = NULL;
+                       process_disk_notify(shost, cmdrsp);
+               } else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) {
+                       if (!del_scsipending_entry(virthbainfo,
+                                  (uintptr_t) cmdrsp->vdiskmgmt.scsicmd))
+                               break;
+                       complete_vdiskmgmt_command(cmdrsp);
+               } else
+                       LOGERR("Invalid cmdtype %d\n", cmdrsp->cmdtype);
+               /* cmdrsp is now available for reuse */
+       }
+}
+
+
+/* main function for the thread that waits for scsi commands to arrive
+ * in a specified queue
+ */
+static int
+process_incoming_rsps(void *v)
+{
+       struct virthba_info *virthbainfo = v;
+       struct chaninfo *dc = &virthbainfo->chinfo;
+       struct uiscmdrsp *cmdrsp = NULL;
+       const int SZ = sizeof(struct uiscmdrsp);
+       U64 mask;
+       unsigned long long rc1;
+
+       UIS_DAEMONIZE("vhba_incoming");
+       /* alloc once and reuse */
+       cmdrsp = kmalloc(SZ, GFP_ATOMIC);
+       if (cmdrsp == NULL) {
+               LOGERR("process_incoming_rsps ****FAILED to malloc - thread exiting\n");
+               complete_and_exit(&dc->threadinfo.has_stopped, 0);
+               return 0;
+       }
+       mask = ULTRA_CHANNEL_ENABLE_INTS;
+       while (1) {
+               wait_event_interruptible_timeout(virthbainfo->rsp_queue,
+                        (atomic_read(&virthbainfo->interrupt_rcvd) == 1),
+                                        usecs_to_jiffies(rsltq_wait_usecs));
+               atomic_set(&virthbainfo->interrupt_rcvd, 0);
+               /* drain queue */
+               drain_queue(virthbainfo, dc, cmdrsp);
+               rc1 = uisqueue_InterlockedOr(virthbainfo->flags_addr, mask);
+               if (dc->threadinfo.should_stop)
+                       break;
+       }
+
+       kfree(cmdrsp);
+
+       DBGINF("exiting processing incoming rsps.\n");
+       complete_and_exit(&dc->threadinfo.has_stopped, 0);
+}
+
+/*****************************************************/
+/* proc filesystem functions                                            */
+/*****************************************************/
+
+static ssize_t
+info_proc_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
+{
+       int length = 0;
+       U64 phys_flags_addr;
+       int i;
+       struct virthba_info *virthbainfo;
+       char *vbuf;
+       loff_t pos = *offset;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos > 0 || !len)
+               return 0;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       for (i = 0; i < VIRTHBASOPENMAX; i++) {
+               if (VirtHbasOpen[i].virthbainfo == NULL)
+                       continue;
+
+               virthbainfo = VirtHbasOpen[i].virthbainfo;
+               length += sprintf(vbuf + length, "CHANSOCK is not defined.\n");
+
+               length += sprintf(vbuf + length, "MaxBuffLen:%d\n", MaxBuffLen);
+
+               length += sprintf(vbuf + length, "\nvirthba result queue poll wait:%d usecs.\n",
+                                 rsltq_wait_usecs);
+
+               length += sprintf(vbuf + length,
+                                 "\nModule build: Date:%s Time:%s\n",
+                                 __DATE__, __TIME__);
+               length += sprintf(vbuf + length, "\ninterrupts_rcvd = %llu, interrupts_disabled = %llu\n",
+                                 virthbainfo->interrupts_rcvd,
+                                 virthbainfo->interrupts_disabled);
+               length += sprintf(vbuf + length, "\ninterrupts_notme = %llu,\n",
+                                 virthbainfo->interrupts_notme);
+               phys_flags_addr = virt_to_phys(virthbainfo->flags_addr);
+
+               length += sprintf(vbuf + length, "flags_addr = %p, phys_flags_addr=0x%016llx, FeatureFlags=%llu\n",
+                         virthbainfo->flags_addr, phys_flags_addr,
+                         *virthbainfo->flags_addr);
+               length += sprintf(vbuf + length, "acquire_failed_cnt:%llu\n",
+                                 virthbainfo->acquire_failed_cnt);
+
+               length += sprintf(vbuf + length, "\n");
+       }
+       if (copy_to_user(buf, vbuf, length)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+
+       kfree(vbuf);
+       *offset += length;
+       return length;
+}
+
+static ssize_t
+enable_ints_read(struct file *file, char __user *buffer,
+                 size_t count, loff_t *ppos)
+{
+       return 0;
+}
+
+static ssize_t
+enable_ints_write(struct file *file, const char __user *buffer,
+                 size_t count, loff_t *ppos)
+{
+       char buf[count + 1];
+       int i, new_value;
+       struct virthba_info *virthbainfo;
+       U64 *Features_addr;
+       U64 mask;
+
+       buf[count] = '\0';
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n",
+                      (int) count, buf, count);
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%d", &new_value);
+
+       if (i < 1) {
+               LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>",
+                      (int) count, buf);
+               return -EFAULT;
+       }
+
+       /* set all counts to new_value usually 0 */
+       for (i = 0; i < VIRTHBASOPENMAX; i++) {
+               if (VirtHbasOpen[i].virthbainfo != NULL) {
+                       virthbainfo = VirtHbasOpen[i].virthbainfo;
+                       Features_addr =
+                               &virthbainfo->chinfo.queueinfo->chan->Features;
+                       if (new_value == 1) {
+                               mask = ~(ULTRA_IO_CHANNEL_IS_POLLING |
+                                        ULTRA_IO_DRIVER_DISABLES_INTS);
+                               uisqueue_InterlockedAnd(Features_addr, mask);
+                               mask = ULTRA_IO_DRIVER_ENABLES_INTS;
+                               uisqueue_InterlockedOr(Features_addr, mask);
+                               rsltq_wait_usecs = 4000000;
+                       } else {
+                               mask = ~(ULTRA_IO_DRIVER_ENABLES_INTS |
+                                        ULTRA_IO_DRIVER_DISABLES_INTS);
+                               uisqueue_InterlockedAnd(Features_addr, mask);
+                               mask = ULTRA_IO_CHANNEL_IS_POLLING;
+                               uisqueue_InterlockedOr(Features_addr, mask);
+                               rsltq_wait_usecs = 4000;
+                       }
+               }
+       }
+       return count;
+}
+
+static ssize_t
+rqwu_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
+{
+       char buf[count];
+       int i, usecs;
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n",
+                      (int) count, buf, count);
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%d", &usecs);
+
+       if (i < 1) {
+               LOGERR("Failed to scan value for rqwait_usecs buf<<%.*s>>",
+                      (int) count, buf);
+               return -EFAULT;
+       }
+
+       /* set global wait time */
+       rsltq_wait_usecs = usecs;
+       return count;
+}
+
+/* As per VirtpciFunc returns 1 for success and 0 for failure */
+static int
+virthba_serverup(struct virtpci_dev *virtpcidev)
+{
+       struct virthba_info *virthbainfo =
+           (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi.
+                                    scsihost)->hostdata;
+
+       DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+              virtpcidev->deviceNo);
+
+       if (!virthbainfo->serverdown) {
+               DBGINF("Server up message recieved while server is already up.\n");
+               return 1;
+       }
+       if (virthbainfo->serverchangingstate) {
+               LOGERR("Server already processing change state message\n");
+               return 0;
+       }
+
+       virthbainfo->serverchangingstate = true;
+       /* Must transition channel to ATTACHED state BEFORE we
+        * can start using the device again
+        */
+       ULTRA_CHANNEL_CLIENT_TRANSITION(virthbainfo->chinfo.queueinfo->chan,
+                                       dev_name(&virtpcidev->generic_dev),
+                                       CliStateOS,
+                                       CHANNELCLI_ATTACHED, NULL);
+
+       /* Start Processing the IOVM Response Queue Again */
+       if (!uisthread_start(&virthbainfo->chinfo.threadinfo,
+                            process_incoming_rsps,
+                            virthbainfo, "vhba_incoming")) {
+               LOGERR("uisthread_start rsp ****FAILED\n");
+               return 0;
+       }
+       virthbainfo->serverdown = false;
+       virthbainfo->serverchangingstate = false;
+
+       return 1;
+}
+
+static void
+virthba_serverdown_complete(struct work_struct *work)
+{
+       struct virthba_info *virthbainfo;
+       struct virtpci_dev *virtpcidev;
+       int i;
+       struct scsipending *pendingdel = NULL;
+       struct scsi_cmnd *scsicmd = NULL;
+       struct uiscmdrsp *cmdrsp;
+       unsigned long flags;
+
+       virthbainfo = container_of(work, struct virthba_info,
+                                  serverdown_completion);
+
+       /* Stop Using the IOVM Response Queue (queue should be drained
+        * by the end)
+        */
+       uisthread_stop(&virthbainfo->chinfo.threadinfo);
+
+       /* Fail Commands that weren't completed */
+       spin_lock_irqsave(&virthbainfo->privlock, flags);
+       for (i = 0; i < MAX_PENDING_REQUESTS; i++) {
+               pendingdel = &(virthbainfo->pending[i]);
+               switch (pendingdel->cmdtype) {
+               case CMD_SCSI_TYPE:
+                       scsicmd = (struct scsi_cmnd *) pendingdel->sent;
+                       scsicmd->result = (DID_RESET << 16);
+                       if (scsicmd->scsi_done)
+                               scsicmd->scsi_done(scsicmd);
+                       break;
+               case CMD_SCSITASKMGMT_TYPE:
+                       cmdrsp = (struct uiscmdrsp *) pendingdel->sent;
+                       DBGINF("cmdrsp=0x%x, notify=0x%x\n", cmdrsp,
+                              cmdrsp->scsitaskmgmt.notify);
+                       *(int *) cmdrsp->scsitaskmgmt.notifyresult =
+                           TASK_MGMT_FAILED;
+                       wake_up_all((wait_queue_head_t *)
+                                   cmdrsp->scsitaskmgmt.notify);
+                       break;
+               case CMD_VDISKMGMT_TYPE:
+                       cmdrsp = (struct uiscmdrsp *) pendingdel->sent;
+                       *(int *) cmdrsp->vdiskmgmt.notifyresult =
+                           VDISK_MGMT_FAILED;
+                       wake_up_all((wait_queue_head_t *)
+                                   cmdrsp->vdiskmgmt.notify);
+                       break;
+               default:
+                       if (pendingdel->sent != NULL)
+                               LOGERR("Unknown command type: 0x%x.  Only freeing list structure.\n",
+                                    pendingdel->cmdtype);
+               }
+               pendingdel->cmdtype = 0;
+               pendingdel->sent = NULL;
+       }
+       spin_unlock_irqrestore(&virthbainfo->privlock, flags);
+
+       virtpcidev = virthbainfo->virtpcidev;
+
+       DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+              virtpcidev->deviceNo);
+       virthbainfo->serverdown = true;
+       virthbainfo->serverchangingstate = false;
+       /* Return the ServerDown response to Command */
+       device_pause_response(virtpcidev->busNo, virtpcidev->deviceNo, 0);
+}
+
+/* As per VirtpciFunc returns 1 for success and 0 for failure */
+static int
+virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state)
+{
+       struct virthba_info *virthbainfo =
+           (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi.
+                                    scsihost)->hostdata;
+
+       DBGINF("virthba_serverdown");
+       DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+              virtpcidev->deviceNo);
+
+       if (!virthbainfo->serverdown && !virthbainfo->serverchangingstate) {
+               virthbainfo->serverchangingstate = true;
+               queue_work(virthba_serverdown_workqueue,
+                          &virthbainfo->serverdown_completion);
+       } else if (virthbainfo->serverchangingstate) {
+               LOGERR("Server already processing change state message\n");
+               return 0;
+       } else
+               LOGERR("Server already down, but another server down message received.");
+
+       return 1;
+}
+
+/*****************************************************/
+/* Module Init & Exit functions                      */
+/*****************************************************/
+
+static int __init
+virthba_parse_line(char *str)
+{
+       DBGINF("In virthba_parse_line %s\n", str);
+       return 1;
+}
+
+static void __init
+virthba_parse_options(char *line)
+{
+       char *next = line;
+
+       POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       if (line == NULL || !*line)
+               return;
+       while ((line = next) != NULL) {
+               next = strchr(line, ' ');
+               if (next != NULL)
+                       *next++ = 0;
+               if (!virthba_parse_line(line))
+                       DBGINF("Unknown option '%s'\n", line);
+       }
+
+       POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+}
+
+static int __init
+virthba_mod_init(void)
+{
+       int error;
+       int i;
+
+       LOGINF("Entering virthba_mod_init...\n");
+
+       POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       virthba_parse_options(virthba_options);
+
+       error = virtpci_register_driver(&virthba_driver);
+       if (error < 0) {
+               LOGERR("register ****FAILED 0x%x\n", error);
+               POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error,
+                                POSTCODE_SEVERITY_ERR);
+       } else {
+               /* create the proc directories */
+               virthba_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
+               info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0,
+                                             virthba_proc_dir,
+                                             &proc_info_fops);
+               rqwaitus_proc_entry = proc_create(RQWU_PROC_ENTRY_FN, 0,
+                                                 virthba_proc_dir,
+                                                 &proc_rqwu_fops);
+               enable_ints_proc_entry = proc_create(ENABLE_INTS_ENTRY_FN, 0,
+                                                    virthba_proc_dir,
+                                                    &proc_enable_ints_fops);
+
+               /* Initialize DARWorkQ */
+               INIT_WORK(&DARWorkQ, doDiskAddRemove);
+               spin_lock_init(&DARWorkQLock);
+
+               /* clear out array */
+               for (i = 0; i < VIRTHBASOPENMAX; i++)
+                       VirtHbasOpen[i].virthbainfo = NULL;
+               /* Initialize the serverdown workqueue */
+               virthba_serverdown_workqueue =
+                   create_singlethread_workqueue("virthba_serverdown");
+               if (virthba_serverdown_workqueue == NULL) {
+                       LOGERR("**** FAILED virthba_serverdown_workqueue creation\n");
+                       POSTCODE_LINUX_2(VHBA_CREATE_FAILURE_PC,
+                                        POSTCODE_SEVERITY_ERR);
+                       error = -1;
+               }
+       }
+
+       POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       LOGINF("Leaving virthba_mod_init\n");
+       return error;
+}
+
+static ssize_t
+virthba_acquire_lun(struct device *cdev, struct device_attribute *attr,
+                   const char *buf, size_t count)
+{
+       struct uisscsi_dest vdest;
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       int i;
+
+       i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun);
+       if (i != 3)
+               return i;
+
+       return forward_vdiskmgmt_command(VDISK_MGMT_ACQUIRE, shost, &vdest);
+}
+
+static ssize_t
+virthba_release_lun(struct device *cdev, struct device_attribute *attr,
+                   const char *buf, size_t count)
+{
+       struct uisscsi_dest vdest;
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       int i;
+
+       i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun);
+       if (i != 3)
+               return i;
+
+       return forward_vdiskmgmt_command(VDISK_MGMT_RELEASE, shost, &vdest);
+}
+
+#define CLASS_DEVICE_ATTR(_name, _mode, _show, _store)      \
+       struct device_attribute class_device_attr_##_name =   \
+               __ATTR(_name, _mode, _show, _store)
+
+static CLASS_DEVICE_ATTR(acquire_lun, S_IWUSR, NULL, virthba_acquire_lun);
+static CLASS_DEVICE_ATTR(release_lun, S_IWUSR, NULL, virthba_release_lun);
+
+static DEVICE_ATTRIBUTE *virthba_shost_attrs[] = {
+       &class_device_attr_acquire_lun,
+       &class_device_attr_release_lun,
+       NULL
+};
+
+static void __exit
+virthba_mod_exit(void)
+{
+       LOGINF("entering virthba_mod_exit...\n");
+
+       virtpci_unregister_driver(&virthba_driver);
+       /* unregister is going to call virthba_remove */
+       /* destroy serverdown completion workqueue */
+       if (virthba_serverdown_workqueue) {
+               destroy_workqueue(virthba_serverdown_workqueue);
+               virthba_serverdown_workqueue = NULL;
+       }
+
+       if (info_proc_entry)
+               remove_proc_entry(INFO_PROC_ENTRY_FN, virthba_proc_dir);
+
+       if (rqwaitus_proc_entry)
+               remove_proc_entry(RQWU_PROC_ENTRY_FN, NULL);
+
+       if (enable_ints_proc_entry)
+               remove_proc_entry(ENABLE_INTS_ENTRY_FN, NULL);
+
+       if (virthba_proc_dir)
+               remove_proc_entry(DIR_PROC_ENTRY, NULL);
+
+       LOGINF("Leaving virthba_mod_exit\n");
+
+}
+
+/* specify function to be run at module insertion time */
+module_init(virthba_mod_init);
+
+/* specify function to be run when module is removed */
+module_exit(virthba_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Usha Srinivasan");
+MODULE_ALIAS("uisvirthba");
+       /* this is extracted during depmod and kept in modules.dep */
+/* module parameter */
+module_param(virthba_options, charp, S_IRUGO);
diff --git a/drivers/staging/unisys/virthba/virthba.h b/drivers/staging/unisys/virthba/virthba.h
new file mode 100644 (file)
index 0000000..88b7974
--- /dev/null
@@ -0,0 +1,31 @@
+/* virthba.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys Virtual HBA driver header
+ */
+
+
+
+#ifndef __VIRTHBA_H__
+#define __VIRTHBA_H__
+
+
+#define VIRTHBA_VERSION "01.00"
+
+
+#endif /* __VIRTHBA_H__ */
diff --git a/drivers/staging/unisys/virtpci/Kconfig b/drivers/staging/unisys/virtpci/Kconfig
new file mode 100644 (file)
index 0000000..e59efcb
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys virtpci configuration
+#
+
+config UNISYS_VIRTPCI
+       tristate "Unisys virtpci driver"
+       depends on UNISYSSPAR && UNISYS_UISLIB
+       ---help---
+       If you say Y here, you will enable the Unisys virtpci driver.
+
diff --git a/drivers/staging/unisys/virtpci/Makefile b/drivers/staging/unisys/virtpci/Makefile
new file mode 100644 (file)
index 0000000..f9399aa
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for Unisys virtpci
+#
+
+obj-$(CONFIG_UNISYS_VIRTPCI)   += virtpci.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/uislib
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c
new file mode 100644 (file)
index 0000000..5700e4b
--- /dev/null
@@ -0,0 +1,1755 @@
+/* virtpci.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "uisutils.h"
+#include "commontypes.h"
+#include "vbuschannel.h"
+#include "vbushelper.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/proc_fs.h>
+#include <linux/if_ether.h>
+#include <linux/version.h>
+#include "version.h"
+#include "guestlinuxdebug.h"
+
+struct driver_private {
+       struct kobject kobj;
+       struct klist klist_devices;
+       struct klist_node knode_bus;
+       struct module_kobject *mkobj;
+       struct device_driver *driver;
+};
+#define to_driver(obj) container_of(obj, struct driver_private, kobj)
+
+/* bus_id went away in 2.6.30 - the size was 20 bytes, so we'll define
+ * it ourselves, and a macro to make getting the field a bit simpler.
+ */
+#ifndef BUS_ID_SIZE
+#define BUS_ID_SIZE 20
+#endif
+
+#define BUS_ID(x) dev_name(x)
+
+#include "virtpci.h"
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC VIRT_PCI_PC_virtpci_c
+#define __MYFILE__ "virtpci.c"
+
+#define VIRTPCI_VERSION "01.00"
+
+/*****************************************************/
+/* Forward declarations                              */
+/*****************************************************/
+
+static int delete_vbus_device(struct device *vbus, void *data);
+static int match_busid(struct device *dev, void *data);
+static void virtpci_bus_release(struct device *dev);
+static void virtpci_device_release(struct device *dev);
+static int virtpci_device_add(struct device *parentbus, int devtype,
+                             struct add_virt_guestpart *addparams,
+                             struct scsi_adap_info *scsi,
+                             struct net_adap_info *net);
+static int virtpci_device_del(struct device *parentbus, int devtype,
+                             struct vhba_wwnn *wwnn, unsigned char macaddr[]);
+static int virtpci_device_serverdown(struct device *parentbus, int devtype,
+                                    struct vhba_wwnn *wwnn,
+                                    unsigned char macaddr[]);
+static int virtpci_device_serverup(struct device *parentbus, int devtype,
+                                  struct vhba_wwnn *wwnn,
+                                  unsigned char macaddr[]);
+static ssize_t virtpci_driver_attr_show(struct kobject *kobj,
+                                       struct attribute *attr, char *buf);
+static ssize_t virtpci_driver_attr_store(struct kobject *kobj,
+                                        struct attribute *attr,
+                                        const char *buf, size_t count);
+static int virtpci_bus_match(struct device *dev, struct device_driver *drv);
+static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env);
+static int virtpci_device_suspend(struct device *dev, pm_message_t state);
+static int virtpci_device_resume(struct device *dev);
+static int virtpci_device_probe(struct device *dev);
+static int virtpci_device_remove(struct device *dev);
+static ssize_t virt_proc_write(struct file *file, const char __user *buffer,
+                              size_t count, loff_t *ppos);
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+                             size_t len, loff_t *offset);
+
+static const struct file_operations proc_virt_fops = {
+       .write = virt_proc_write,
+};
+
+static const struct file_operations proc_info_fops = {
+       .read = info_proc_read,
+};
+
+/*****************************************************/
+/* Globals                                           */
+/*****************************************************/
+
+/* methods in bus_type struct allow the bus code to serve as an
+ * intermediary between the device core and individual device core and
+ * individual drivers
+ */
+static struct bus_type virtpci_bus_type = {
+       .name = "uisvirtpci",
+       .match = virtpci_bus_match,
+       .uevent = virtpci_uevent,
+       .suspend = virtpci_device_suspend,
+       .resume = virtpci_device_resume,
+};
+
+static struct device virtpci_rootbus_device = {
+       .init_name = "vbusroot",        /* root bus */
+       .release = virtpci_bus_release
+};
+
+/* filled in with info about parent chipset driver when we register with it */
+static ULTRA_VBUS_DEVICEINFO Chipset_DriverInfo;
+
+static const struct sysfs_ops virtpci_driver_sysfs_ops = {
+       .show = virtpci_driver_attr_show,
+       .store = virtpci_driver_attr_store,
+};
+
+static struct kobj_type virtpci_driver_kobj_type = {
+       .sysfs_ops = &virtpci_driver_sysfs_ops,
+};
+
+static struct virtpci_dev *VpcidevListHead;
+static DEFINE_RWLOCK(VpcidevListLock);
+
+/* filled in with info about this driver, wrt it servicing client busses */
+static ULTRA_VBUS_DEVICEINFO Bus_DriverInfo;
+
+/* virtpci_proc_dir_entry is used to create the proc entry directory
+ * for virtpci
+ */
+static struct proc_dir_entry *virtpci_proc_dir;
+/* virt_proc_entry is used to tell virtpci to add/delete vhbas/vnics/vbuses */
+static struct proc_dir_entry *virt_proc_entry;
+/* info_proc_entry is used to tell virtpci to display current info
+ * kept in the driver
+ */
+static struct proc_dir_entry *info_proc_entry;
+#define VIRT_PROC_ENTRY_FN "virt"
+#define INFO_PROC_ENTRY_FN "info"
+#define DIR_PROC_ENTRY "virtpci"
+
+struct virtpci_busdev {
+       struct device virtpci_bus_device;
+};
+
+/*****************************************************/
+/* Local functions                                   */
+/*****************************************************/
+
+static inline int WAIT_FOR_IO_CHANNEL(ULTRA_IO_CHANNEL_PROTOCOL *chanptr)
+{
+       int count = 120;
+       while (count > 0) {
+
+               if (ULTRA_CHANNEL_SERVER_READY(&chanptr->ChannelHeader))
+                       return 1;
+               UIS_THREAD_WAIT_SEC(1);
+               count--;
+       }
+       return 0;
+}
+
+/* Write the contents of <info> to the ULTRA_VBUS_CHANNEL_PROTOCOL.ChpInfo. */
+static int write_vbus_chpInfo(ULTRA_VBUS_CHANNEL_PROTOCOL *chan,
+                             ULTRA_VBUS_DEVICEINFO *info)
+{
+       int off;
+       if (!chan) {
+               LOGERR("vbus channel not present");
+               return -1;
+       }
+       off = sizeof(ULTRA_CHANNEL_PROTOCOL) + chan->HdrInfo.chpInfoByteOffset;
+       if (chan->HdrInfo.chpInfoByteOffset == 0) {
+               LOGERR("vbus channel not used, because chpInfoByteOffset == 0");
+               return -1;
+       }
+       memcpy(((U8 *) (chan)) + off, info, sizeof(*info));
+       return 0;
+}
+
+/* Write the contents of <info> to the ULTRA_VBUS_CHANNEL_PROTOCOL.BusInfo. */
+static int write_vbus_busInfo(ULTRA_VBUS_CHANNEL_PROTOCOL *chan,
+                             ULTRA_VBUS_DEVICEINFO *info)
+{
+       int off;
+       if (!chan) {
+               LOGERR("vbus channel not present");
+               return -1;
+       }
+       off = sizeof(ULTRA_CHANNEL_PROTOCOL) + chan->HdrInfo.busInfoByteOffset;
+       if (chan->HdrInfo.busInfoByteOffset == 0) {
+               LOGERR("vbus channel not used, because busInfoByteOffset == 0");
+               return -1;
+       }
+       memcpy(((U8 *) (chan)) + off, info, sizeof(*info));
+       return 0;
+}
+
+/* Write the contents of <info> to the
+ * ULTRA_VBUS_CHANNEL_PROTOCOL.DevInfo[<devix>].
+ */
+static int
+write_vbus_devInfo(ULTRA_VBUS_CHANNEL_PROTOCOL *chan,
+                  ULTRA_VBUS_DEVICEINFO *info, int devix)
+{
+       int off;
+       if (!chan) {
+               LOGERR("vbus channel not present");
+               return -1;
+       }
+       off =
+           (sizeof(ULTRA_CHANNEL_PROTOCOL) +
+            chan->HdrInfo.devInfoByteOffset) +
+           (chan->HdrInfo.deviceInfoStructBytes * devix);
+       if (chan->HdrInfo.devInfoByteOffset == 0) {
+               LOGERR("vbus channel not used, because devInfoByteOffset == 0");
+               return -1;
+       }
+       memcpy(((U8 *) (chan)) + off, info, sizeof(*info));
+       return 0;
+}
+
+/* adds a vbus
+ * returns 0 failure, 1 success,
+ */
+static int add_vbus(struct add_vbus_guestpart *addparams)
+{
+       int ret;
+       struct device *vbus;
+       vbus = kmalloc(sizeof(struct device), GFP_ATOMIC);
+
+       POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       if (!vbus)
+               return 0;
+
+       memset(vbus, 0, sizeof(struct device));
+       dev_set_name(vbus, "vbus%d", addparams->busNo);
+       vbus->release = virtpci_bus_release;
+       vbus->parent = &virtpci_rootbus_device; /* root bus is parent */
+       vbus->bus = &virtpci_bus_type;  /* bus type */
+       vbus->platform_data = addparams->chanptr;
+
+       /* register a virt bus device -
+        * this bus shows up under /sys/devices with .name value
+        * "virtpci%d" any devices added to this bus then show up under
+        * /sys/devices/virtpci0
+        */
+       ret = device_register(vbus);
+       if (ret) {
+               LOGERR("device_register FAILED:%d\n", ret);
+               POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+       write_vbus_chpInfo(vbus->platform_data /* chanptr */ ,
+                          &Chipset_DriverInfo);
+       write_vbus_busInfo(vbus->platform_data /* chanptr */ , &Bus_DriverInfo);
+       LOGINF("Added vbus %d; device %s created successfully\n",
+              addparams->busNo, BUS_ID(vbus));
+       POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       return 1;
+}
+
+/* for CHANSOCK wwwnn/max are AUTO-GENERATED; for normal channels,
+ * wwnn/max are in the channel header.
+ */
+#define GET_SCSIADAPINFO_FROM_CHANPTR(chanptr) { \
+       scsi.wwnn = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vhba.wwnn; \
+       scsi.max = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vhba.max; \
+}
+
+/* find bus device with the busid that matches - match_busid matches bus_id */
+#define GET_BUS_DEV(busno) { \
+       sprintf(busid, "vbus%d", busno); \
+       vbus = bus_find_device(&virtpci_bus_type, NULL, \
+                              (void *)busid, match_busid);     \
+       if (!vbus) { \
+               LOGERR("**** FAILED to find vbus %s\n", busid); \
+               return 0; \
+       } \
+}
+
+/* adds a vhba
+ * returns 0 failure, 1 success,
+ */
+static int add_vhba(struct add_virt_guestpart *addparams)
+{
+       int i;
+       struct scsi_adap_info scsi;
+       struct device *vbus;
+       unsigned char busid[BUS_ID_SIZE];
+
+       POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       if (!WAIT_FOR_IO_CHANNEL
+           ((ULTRA_IO_CHANNEL_PROTOCOL *) addparams->chanptr)) {
+               LOGERR("Timed out.  Channel not ready\n");
+               POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+
+       GET_SCSIADAPINFO_FROM_CHANPTR(addparams->chanptr);
+
+       GET_BUS_DEV(addparams->busNo);
+
+       LOGINF("Adding vhba wwnn:%x:%x config:%d-%d-%d-%d chanptr:%p\n",
+              scsi.wwnn.wwnn1, scsi.wwnn.wwnn2,
+              scsi.max.max_channel, scsi.max.max_id, scsi.max.max_lun,
+              scsi.max.cmd_per_lun, addparams->chanptr);
+       i = virtpci_device_add(vbus, VIRTHBA_TYPE, addparams, &scsi, NULL);
+       if (i) {
+               LOGINF("Added vhba wwnn:%x:%x chanptr:%p\n", scsi.wwnn.wwnn1,
+                      scsi.wwnn.wwnn2, addparams->chanptr);
+               POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i,
+                                POSTCODE_SEVERITY_INFO);
+       }
+       return i;
+
+}
+
+/* for CHANSOCK macaddr is AUTO-GENERATED; for normal channels,
+ * macaddr is in the channel header.
+ */
+#define GET_NETADAPINFO_FROM_CHANPTR(chanptr) { \
+       memcpy(net.mac_addr, ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.macaddr, MAX_MACADDR_LEN); \
+       net.num_rcv_bufs = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.num_rcv_bufs; \
+       net.mtu = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.mtu; \
+       net.zoneGuid = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.zoneGuid; \
+}
+
+/* adds a vnic
+ * returns 0 failure, 1 success,
+ */
+static int
+add_vnic(struct add_virt_guestpart *addparams)
+{
+       int i;
+       struct net_adap_info net;
+       struct device *vbus;
+       unsigned char busid[BUS_ID_SIZE];
+
+       POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       if (!WAIT_FOR_IO_CHANNEL
+           ((ULTRA_IO_CHANNEL_PROTOCOL *) addparams->chanptr)) {
+               LOGERR("Timed out, channel not ready\n");
+               POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+
+       GET_NETADAPINFO_FROM_CHANPTR(addparams->chanptr);
+
+       GET_BUS_DEV(addparams->busNo);
+
+       LOGINF("Adding vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x rcvbufs:%d mtu:%d chanptr:%p{%-8.8lx-%-4.4x-%-4.4x-%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x}\n",
+            net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3],
+            net.mac_addr[4], net.mac_addr[5], net.num_rcv_bufs, net.mtu,
+            addparams->chanptr, (ulong) net.zoneGuid.data1, net.zoneGuid.data2,
+            net.zoneGuid.data3, net.zoneGuid.data4[0], net.zoneGuid.data4[1],
+            net.zoneGuid.data4[2], net.zoneGuid.data4[3],
+            net.zoneGuid.data4[4], net.zoneGuid.data4[5],
+            net.zoneGuid.data4[6], net.zoneGuid.data4[7]);
+       i = virtpci_device_add(vbus, VIRTNIC_TYPE, addparams, NULL, &net);
+       if (i) {
+               LOGINF("Added vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+               POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i,
+                                POSTCODE_SEVERITY_INFO);
+               return 1;
+       }
+       return 0;
+}
+
+/* delete vbus
+ * returns 0 failure, 1 success,
+ */
+static int
+delete_vbus(struct del_vbus_guestpart *delparams)
+{
+       struct device *vbus;
+       unsigned char busid[BUS_ID_SIZE];
+
+       GET_BUS_DEV(delparams->busNo);
+       /* ensure that bus has no devices? -- TBD */
+       LOGINF("Deleting %s\n", BUS_ID(vbus));
+       if (delete_vbus_device(vbus, NULL))
+               return 0;       /* failure */
+       LOGINF("Deleted vbus %d\n", delparams->busNo);
+       return 1;
+}
+
+static int
+delete_vbus_device(struct device *vbus, void *data)
+{
+       int checkforroot = (data != NULL);
+       struct device *pDev = &virtpci_rootbus_device;
+
+       if ((checkforroot) && match_busid(vbus, (void *) BUS_ID(pDev))) {
+               /* skip it - don't delete root bus */
+               LOGINF("skipping root bus\n");
+               return 0;       /* pretend no error */
+       }
+       LOGINF("Calling unregister for %s\n", BUS_ID(vbus));
+       device_unregister(vbus);
+       kfree(vbus);
+       LOGINF("VBus unregister and freed\n");
+       return 0;               /* no error */
+}
+
+/* pause vhba
+* returns 0 failure, 1 success,
+*/
+static int pause_vhba(struct pause_virt_guestpart *pauseparams)
+{
+       int i;
+       struct scsi_adap_info scsi;
+
+       GET_SCSIADAPINFO_FROM_CHANPTR(pauseparams->chanptr);
+
+       LOGINF("Pausing vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
+       i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTHBA_TYPE,
+                                     &scsi.wwnn, NULL);
+       if (i)
+               LOGINF("Paused vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
+                      scsi.wwnn.wwnn2);
+       return i;
+}
+
+/* pause vnic
+ * returns 0 failure, 1 success,
+ */
+static int pause_vnic(struct pause_virt_guestpart *pauseparams)
+{
+       int i;
+       struct net_adap_info net;
+
+       GET_NETADAPINFO_FROM_CHANPTR(pauseparams->chanptr);
+
+       LOGINF("Pausing vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+       i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTNIC_TYPE,
+                                     NULL, net.mac_addr);
+       if (i) {
+               LOGINF(" Paused vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+       }
+       return i;
+}
+
+/* resume vhba
+ * returns 0 failure, 1 success,
+ */
+static int resume_vhba(struct resume_virt_guestpart *resumeparams)
+{
+       int i;
+       struct scsi_adap_info scsi;
+
+       GET_SCSIADAPINFO_FROM_CHANPTR(resumeparams->chanptr);
+
+       LOGINF("Resuming vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
+       i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTHBA_TYPE,
+                                   &scsi.wwnn, NULL);
+       if (i)
+               LOGINF("Resumed vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
+                      scsi.wwnn.wwnn2);
+       return i;
+}
+
+/* resume vnic
+* returns 0 failure, 1 success,
+*/
+static int
+resume_vnic(struct resume_virt_guestpart *resumeparams)
+{
+       int i;
+       struct net_adap_info net;
+
+       GET_NETADAPINFO_FROM_CHANPTR(resumeparams->chanptr);
+
+       LOGINF("Resuming vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+       i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTNIC_TYPE,
+                                   NULL, net.mac_addr);
+       if (i) {
+               LOGINF(" Resumed vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+       }
+       return i;
+}
+
+/* delete vhba
+* returns 0 failure, 1 success,
+*/
+static int delete_vhba(struct del_virt_guestpart *delparams)
+{
+       int i;
+       struct scsi_adap_info scsi;
+
+       GET_SCSIADAPINFO_FROM_CHANPTR(delparams->chanptr);
+
+       LOGINF("Deleting vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
+       i = virtpci_device_del(NULL /*no parent bus */ , VIRTHBA_TYPE,
+                              &scsi.wwnn, NULL);
+       if (i) {
+               LOGINF("Deleted vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
+                      scsi.wwnn.wwnn2);
+               return 1;
+       }
+       return 0;
+}
+
+/* deletes a vnic
+ * returns 0 failure, 1 success,
+ */
+static int delete_vnic(struct del_virt_guestpart *delparams)
+{
+       int i;
+       struct net_adap_info net;
+
+       GET_NETADAPINFO_FROM_CHANPTR(delparams->chanptr);
+
+       LOGINF("Deleting vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+       i = virtpci_device_del(NULL /*no parent bus */ , VIRTNIC_TYPE, NULL,
+                              net.mac_addr);
+       if (i) {
+               LOGINF("Deleted vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+       }
+       return i;
+}
+
+#define DELETE_ONE_VPCIDEV(vpcidev) { \
+       LOGINF("calling device_unregister:%p\n", &vpcidev->generic_dev); \
+       device_unregister(&vpcidev->generic_dev); \
+       LOGINF("Deleted %p\n", vpcidev); \
+       kfree(vpcidev); \
+}
+
+/* deletes all vhbas and vnics
+ * returns 0 failure, 1 success,
+ */
+static void delete_all(void)
+{
+       int count = 0;
+       unsigned long flags;
+       struct virtpci_dev *tmpvpcidev, *nextvpcidev;
+
+       /* delete the entire vhba/vnic list in one shot */
+       write_lock_irqsave(&VpcidevListLock, flags);
+       tmpvpcidev = VpcidevListHead;
+       VpcidevListHead = NULL;
+       write_unlock_irqrestore(&VpcidevListLock, flags);
+
+       /* delete one vhba/vnic at a time */
+       while (tmpvpcidev) {
+               nextvpcidev = tmpvpcidev->next;
+               /* delete the vhba/vnic at tmpvpcidev */
+               DELETE_ONE_VPCIDEV(tmpvpcidev);
+               tmpvpcidev = nextvpcidev;
+               count++;
+       }
+       LOGINF("Deleted %d vhbas/vnics.\n", count);
+
+       /* now delete each vbus */
+       if (bus_for_each_dev
+           (&virtpci_bus_type, NULL, (void *) 1, delete_vbus_device))
+               LOGERR("delete of all vbus failed\n");
+}
+
+/* deletes all vnics or vhbas
+ * returns 0 failure, 1 success,
+ */
+static int delete_all_virt(VIRTPCI_DEV_TYPE devtype, struct del_vbus_guestpart *delparams)
+{
+       int i;
+       unsigned char busid[BUS_ID_SIZE];
+       struct device *vbus;
+
+       GET_BUS_DEV(delparams->busNo);
+
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+               LOGERR("**** FAILED to delete all devices; devtype:%d not vhba:%d or vnic:%d\n",
+                    devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+               return 0;
+       }
+
+       LOGINF("Deleting all %s in vbus %s\n",
+              devtype == VIRTHBA_TYPE ? "vhbas" : "vnics", busid);
+       /* delete all vhbas/vnics */
+       i = virtpci_device_del(vbus, devtype, NULL, NULL);
+       if (i > 0)
+               LOGINF("Deleted %d %s\n", i,
+                      devtype == VIRTHBA_TYPE ? "vhbas" : "vnics");
+       return 1;
+}
+
+static int virtpci_ctrlchan_func(struct guest_msgs *msg)
+{
+       switch (msg->msgtype) {
+       case GUEST_ADD_VBUS:
+               return add_vbus(&msg->add_vbus);
+       case GUEST_ADD_VHBA:
+               return add_vhba(&msg->add_vhba);
+       case GUEST_ADD_VNIC:
+               return add_vnic(&msg->add_vnic);
+       case GUEST_DEL_VBUS:
+               return delete_vbus(&msg->del_vbus);
+       case GUEST_DEL_VHBA:
+               return delete_vhba(&msg->del_vhba);
+       case GUEST_DEL_VNIC:
+               return delete_vnic(&msg->del_vhba);
+       case GUEST_DEL_ALL_VHBAS:
+               return delete_all_virt(VIRTHBA_TYPE, &msg->del_all_vhbas);
+       case GUEST_DEL_ALL_VNICS:
+               return delete_all_virt(VIRTNIC_TYPE, &msg->del_all_vnics);
+       case GUEST_DEL_ALL_VBUSES:
+               delete_all();
+               return 1;
+       case GUEST_PAUSE_VHBA:
+               return pause_vhba(&msg->pause_vhba);
+       case GUEST_PAUSE_VNIC:
+               return pause_vnic(&msg->pause_vnic);
+       case GUEST_RESUME_VHBA:
+               return resume_vhba(&msg->resume_vhba);
+       case GUEST_RESUME_VNIC:
+               return resume_vnic(&msg->resume_vnic);
+       default:
+               LOGERR("invalid message type %d.\n", msg->msgtype);
+               return 0;
+       }
+}
+
+/* same as driver_helper in bus.c linux */
+static int match_busid(struct device *dev, void *data)
+{
+       const char *name = data;
+
+       if (strcmp(name, BUS_ID(dev)) == 0)
+               return 1;
+       return 0;
+}
+
+/*****************************************************/
+/*  Bus functions                                    */
+/*****************************************************/
+
+const struct pci_device_id *
+virtpci_match_device(const struct pci_device_id *ids,
+                    const struct virtpci_dev *dev)
+{
+       while (ids->vendor || ids->subvendor || ids->class_mask) {
+               DBGINF("ids->vendor:%x dev->vendor:%x ids->device:%x dev->device:%x\n",
+                    ids->vendor, dev->vendor, ids->device, dev->device);
+
+               if ((ids->vendor == dev->vendor)
+                   && (ids->device == dev->device))
+                       return ids;
+
+               ids++;
+       }
+       return NULL;
+}
+
+/* NOTE: !!!!!!  This function is called when a new device is added
+* for this bus.  Or, it is called for existing devices when a new
+* driver is added for this bus.  It returns nonzero if a given device
+* can be handled by the given driver.
+*/
+static int virtpci_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev);
+       struct virtpci_driver *virtpcidrv = driver_to_virtpci_driver(drv);
+       int match = 0;
+
+       DBGINF("In virtpci_bus_match dev->bus_id:%s drv->name:%s\n",
+              dev->bus_id, drv->name);
+
+       /* check ids list for a match */
+       if (virtpci_match_device(virtpcidrv->id_table, virtpcidev))
+               match = 1;
+
+       DBGINF("returning match:%d\n", match);
+       return match;           /* 0 - no match; 1 - yes it matches */
+}
+
+static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       DBGINF("In virtpci_hotplug\n");
+       /* add variables to the environment prior to the generation of
+        * hotplug events to user space
+        */
+       if (add_uevent_var(env, "VIRTPCI_VERSION=%s", VIRTPCI_VERSION))
+               return -ENOMEM;
+       return 0;
+}
+
+static int virtpci_device_suspend(struct device *dev, pm_message_t state)
+{
+       DBGINF("In virtpci_device_suspend -NYI ****\n");
+       return 0;
+}
+
+static int virtpci_device_resume(struct device *dev)
+{
+       DBGINF("In virtpci_device_resume -NYI ****\n");
+       return 0;
+}
+
+/* For a child device just created on a client bus, fill in
+ * information about the driver that is controlling this device into
+ * the the appropriate slot within the vbus channel of the bus
+ * instance.
+ */
+static void fix_vbus_devInfo(struct device *dev, int devNo, int devType,
+                            struct virtpci_driver *virtpcidrv)
+{
+       struct device *vbus;
+       void *pChan;
+       ULTRA_VBUS_DEVICEINFO devInfo;
+       const char *stype;
+
+       if (!dev) {
+               LOGERR("%s dev is NULL", __func__);
+               return;
+       }
+       if (!virtpcidrv) {
+               LOGERR("%s driver is NULL", __func__);
+               return;
+       }
+       vbus = dev->parent;
+       if (!vbus) {
+               LOGERR("%s dev has no parent bus", __func__);
+               return;
+       }
+       pChan = vbus->platform_data;
+       if (!pChan) {
+               LOGERR("%s dev bus has no channel", __func__);
+               return;
+       }
+       switch (devType) {
+       case PCI_DEVICE_ID_VIRTHBA:
+               stype = "vHBA";
+               break;
+       case PCI_DEVICE_ID_VIRTNIC:
+               stype = "vNIC";
+               break;
+       default:
+               stype = "unknown";
+               break;
+       }
+       BusDeviceInfo_Init(&devInfo, stype,
+                          virtpcidrv->name,
+                          virtpcidrv->version,
+                          virtpcidrv->vertag,
+                          virtpcidrv->build_date, virtpcidrv->build_time);
+       write_vbus_devInfo(pChan, &devInfo, devNo);
+
+       /* Re-write bus+chipset info, because it is possible that this
+       * was previously written by our good counterpart, visorbus.
+       */
+       write_vbus_chpInfo(pChan, &Chipset_DriverInfo);
+       write_vbus_busInfo(pChan, &Bus_DriverInfo);
+}
+
+/* This function is called to query the existence of a specific device
+* and whether this driver can work with it.  It should return -ENODEV
+* in case of failure.
+*/
+static int virtpci_device_probe(struct device *dev)
+{
+       struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev);
+       struct virtpci_driver *virtpcidrv =
+           driver_to_virtpci_driver(dev->driver);
+       const struct pci_device_id *id;
+       int error = 0;
+
+       LOGINF("In virtpci_device_probe dev:%p virtpcidev:%p virtpcidrv:%p\n",
+              dev, virtpcidev, virtpcidrv);    /* VERBOSE/DEBUG ? */
+       POSTCODE_LINUX_2(VPCI_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       /* static match and static probe vs dynamic match & dynamic
+        * probe - do we care?.
+        */
+       if (!virtpcidrv->id_table)
+               return -ENODEV;
+
+       id = virtpci_match_device(virtpcidrv->id_table, virtpcidev);
+       if (!id)
+               return -ENODEV;
+
+       /* increment reference count */
+       get_device(dev);
+
+       /* if virtpcidev is not already claimed & probe function is
+        * valid, probe it
+        */
+       if (!virtpcidev->mydriver && virtpcidrv->probe) {
+               /* call the probe function - virthba or virtnic probe
+                * is what it should be
+                */
+               error = virtpcidrv->probe(virtpcidev, id);
+               if (!error) {
+                       fix_vbus_devInfo(dev, virtpcidev->deviceNo,
+                                        virtpcidev->device, virtpcidrv);
+                       virtpcidev->mydriver = virtpcidrv;
+                       POSTCODE_LINUX_2(VPCI_PROBE_EXIT_PC,
+                                        POSTCODE_SEVERITY_INFO);
+               } else
+                       put_device(dev);
+       }
+       POSTCODE_LINUX_2(VPCI_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+       return error;           /* -ENODEV for probe failure */
+}
+
+static int virtpci_device_remove(struct device *dev_)
+{
+       /* dev_ passed in is the HBA device which we called
+       * generic_dev in our virtpcidev struct
+       */
+       struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev_);
+       struct virtpci_driver *virtpcidrv = virtpcidev->mydriver;
+       LOGINF("In virtpci_device_remove bus_id:%s dev_:%p virtpcidev:%p dev->driver:%p drivername:%s\n",
+              BUS_ID(dev_), dev_, virtpcidev, dev_->driver,
+              dev_->driver->name);     /* VERBOSE/DEBUG */
+       if (virtpcidrv) {
+               /* TEMP: assuming we have only one such driver for now */
+               if (virtpcidrv->remove)
+                       virtpcidrv->remove(virtpcidev);
+               virtpcidev->mydriver = NULL;
+       }
+
+       DBGINF("calling putdevice\n");
+       put_device(dev_);
+
+       DBGINF("Leaving\n");
+       return 0;
+}
+
+/*****************************************************/
+/* Bus functions                                     */
+/*****************************************************/
+
+static void virtpci_bus_release(struct device *dev)
+{
+       /* this function is called when the last reference to the
+        * device is removed
+        */
+       DBGINF("In virtpci_bus_release\n");
+       /* what else is supposed to happen here? */
+}
+
+/*****************************************************/
+/* Adapter functions                                 */
+/*****************************************************/
+
+static int virtpci_device_add(struct device *parentbus, int devtype,
+                             struct add_virt_guestpart *addparams,
+                             struct scsi_adap_info *scsi, /* NULL for VNIC add */
+                             struct net_adap_info *net /* NULL for VHBA add */)
+{
+       struct virtpci_dev *virtpcidev = NULL;
+       struct virtpci_dev *tmpvpcidev = NULL, *prev;
+       unsigned long flags;
+       int ret;
+       ULTRA_IO_CHANNEL_PROTOCOL *pIoChan = NULL;
+       struct device *pDev;
+
+       LOGINF("virtpci_device_add parentbus:%p chanptr:%p\n", parentbus,
+              addparams->chanptr);
+
+       POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+               LOGERR("**** FAILED to add device; devtype:%d not vhba:%d or vnic:%d\n",
+                    devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+               POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, devtype,
+                                POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+
+       /* add a Virtual Device */
+       virtpcidev = kmalloc(sizeof(struct virtpci_dev), GFP_ATOMIC);
+       if (virtpcidev == NULL) {
+               LOGERR("can't add device - malloc FALLED\n");
+               POSTCODE_LINUX_2(MALLOC_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+
+       memset(virtpcidev, 0, sizeof(struct virtpci_dev));
+
+       /* initialize stuff unique to virtpci_dev struct */
+       virtpcidev->devtype = devtype;
+       if (devtype == VIRTHBA_TYPE) {
+               virtpcidev->device = PCI_DEVICE_ID_VIRTHBA;
+               virtpcidev->scsi = *scsi;
+       } else {
+               virtpcidev->device = PCI_DEVICE_ID_VIRTNIC;
+               virtpcidev->net = *net;
+       }
+       virtpcidev->vendor = PCI_VENDOR_ID_UNISYS;
+       virtpcidev->busNo = addparams->busNo;
+       virtpcidev->deviceNo = addparams->deviceNo;
+
+       virtpcidev->queueinfo.chan = addparams->chanptr;
+       virtpcidev->queueinfo.send_int_if_needed = NULL;
+
+       /* Set up safe queue... */
+       pIoChan = (ULTRA_IO_CHANNEL_PROTOCOL *) virtpcidev->queueinfo.chan;
+
+       virtpcidev->intr = addparams->intr;
+
+       /* initialize stuff in the device portion of the struct */
+       virtpcidev->generic_dev.bus = &virtpci_bus_type;
+       virtpcidev->generic_dev.parent = parentbus;
+       virtpcidev->generic_dev.release = virtpci_device_release;
+
+       dev_set_name(&virtpcidev->generic_dev, "%x:%x",
+                    addparams->busNo, addparams->deviceNo);
+
+       /* add the vhba/vnic to virtpci device list - but check for
+        * duplicate wwnn/macaddr first
+        */
+       write_lock_irqsave(&VpcidevListLock, flags);
+       for (tmpvpcidev = VpcidevListHead; tmpvpcidev;
+            tmpvpcidev = tmpvpcidev->next) {
+               if (devtype == VIRTHBA_TYPE) {
+                       if ((tmpvpcidev->scsi.wwnn.wwnn1 == scsi->wwnn.wwnn1) &&
+                           (tmpvpcidev->scsi.wwnn.wwnn2 == scsi->wwnn.wwnn2)) {
+                               /* duplicate - already have vpcidev
+                                  with this wwnn */
+                               break;
+                       }
+               } else
+                   if (memcmp
+                       (tmpvpcidev->net.mac_addr, net->mac_addr,
+                        MAX_MACADDR_LEN) == 0) {
+                       /* duplicate - already have vnic with this wwnn */
+                       break;
+               }
+       }
+       if (tmpvpcidev) {
+               /* found a vhba/vnic already in the list with same
+                * wwnn or macaddr - reject add
+                */
+               write_unlock_irqrestore(&VpcidevListLock, flags);
+               kfree(virtpcidev);
+               LOGERR("**** FAILED vhba/vnic already exists in the list\n");
+               POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               return 0;
+       }
+
+       /* add it at the head */
+       if (!VpcidevListHead)
+               VpcidevListHead = virtpcidev;
+       else {
+               /* insert virtpcidev at the head of our linked list of
+                * vpcidevs
+                */
+               virtpcidev->next = VpcidevListHead;
+               VpcidevListHead = virtpcidev;
+       }
+
+       write_unlock_irqrestore(&VpcidevListLock, flags);
+
+       /* Must transition channel to ATTACHED state BEFORE
+        * registering the device, because polling of the channel
+        * queues can begin at any time after device_register().
+        */
+       pDev = &virtpcidev->generic_dev;
+       ULTRA_CHANNEL_CLIENT_TRANSITION(addparams->chanptr,
+                                       BUS_ID(pDev),
+                                       CliStateOS, CHANNELCLI_ATTACHED, NULL);
+
+       /* don't register until device has been added to
+       * list. Otherwise, a device_unregister from this function can
+       * cause a "scheduling while atomic".
+       */
+       DBGINF("registering device:%p with bus_id:%s\n",
+              &virtpcidev->generic_dev, virtpcidev->generic_dev.bus_id);
+       ret = device_register(&virtpcidev->generic_dev);
+       /* NOTE: THIS IS CALLING HOTPLUG virtpci_hotplug!!!
+        * This call to device_register results in virtpci_bus_match
+        * being called !!!!!  And, if match returns success, then
+        * virtpcidev->generic_dev.driver is setup to core_driver,
+        * i.e., virtpci and the probe function
+        * virtpcidev->generic_dev.driver->probe is called which
+        * results in virtpci_device_probe being called. And if
+        * virtpci_device_probe is successful
+        */
+       if (ret) {
+               LOGERR("device_register returned %d\n", ret);
+               pDev = &virtpcidev->generic_dev;
+               ULTRA_CHANNEL_CLIENT_TRANSITION(addparams->chanptr,
+                                               BUS_ID(pDev),
+                                               CliStateOS,
+                                               CHANNELCLI_DETACHED, NULL);
+               /* remove virtpcidev, the one we just added, from the list */
+               write_lock_irqsave(&VpcidevListLock, flags);
+               for (tmpvpcidev = VpcidevListHead, prev = NULL;
+                    tmpvpcidev;
+                    prev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) {
+                       if (tmpvpcidev == virtpcidev) {
+                               if (prev)
+                                       prev->next = tmpvpcidev->next;
+                               else
+                                       VpcidevListHead = tmpvpcidev->next;
+                               break;
+                       }
+               }
+               write_unlock_irqrestore(&VpcidevListLock, flags);
+               kfree(virtpcidev);
+               return 0;
+       }
+
+       LOGINF("Added %s:%d:%d &virtpcidev->generic_dev:%p\n",
+              (devtype == VIRTHBA_TYPE) ? "virthba" : "virtnic",
+              addparams->busNo, addparams->deviceNo, &virtpcidev->generic_dev);
+       POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       return 1;
+}
+
+static int virtpci_device_serverdown(struct device *parentbus,
+                                    int devtype,
+                                    struct vhba_wwnn *wwnn,
+                                    unsigned char macaddr[])
+{
+       int pausethisone = 0;
+       bool found = false;
+       struct virtpci_dev *tmpvpcidev, *prevvpcidev;
+       struct virtpci_driver *vpcidriver;
+       unsigned long flags;
+       int rc = 0;
+
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+               LOGERR("**** FAILED to pause device; devtype:%d not vhba:%d or vnic:%d\n",
+                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+               return 0;
+       }
+
+       /* find the vhba or vnic in virtpci device list */
+       write_lock_irqsave(&VpcidevListLock, flags);
+
+       for (tmpvpcidev = VpcidevListHead, prevvpcidev = NULL;
+            (tmpvpcidev && !found);
+            prevvpcidev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) {
+               if (tmpvpcidev->devtype != devtype)
+                       continue;
+
+               if (devtype == VIRTHBA_TYPE) {
+                       pausethisone =
+                           ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) &&
+                            (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2));
+                       /* devtype is vhba, we're pausing vhba whose
+                       * wwnn matches the current device's wwnn
+                       */
+               } else {        /* VIRTNIC_TYPE */
+                       pausethisone =
+                           memcmp(tmpvpcidev->net.mac_addr, macaddr,
+                                  MAX_MACADDR_LEN) == 0;
+                       /* devtype is vnic, we're pausing vnic whose
+                       * macaddr matches the current device's macaddr */
+               }
+
+               if (!pausethisone)
+                       continue;
+
+               found = true;
+               vpcidriver = tmpvpcidev->mydriver;
+               rc = vpcidriver->suspend(tmpvpcidev, 0);
+       }
+       write_unlock_irqrestore(&VpcidevListLock, flags);
+
+       if (!found) {
+               LOGERR("**** FAILED to find vhba/vnic in the list\n");
+               return 0;
+       }
+
+       return rc;
+}
+
+static int virtpci_device_serverup(struct device *parentbus,
+                                  int devtype,
+                                  struct vhba_wwnn *wwnn,
+                                  unsigned char macaddr[])
+{
+       int resumethisone = 0;
+       bool found = false;
+       struct virtpci_dev *tmpvpcidev, *prevvpcidev;
+       struct virtpci_driver *vpcidriver;
+       unsigned long flags;
+       int rc = 0;
+
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+               LOGERR("**** FAILED to resume device; devtype:%d not vhba:%d or vnic:%d\n",
+                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+               return 0;
+       }
+
+       /* find the vhba or vnic in virtpci device list */
+       write_lock_irqsave(&VpcidevListLock, flags);
+
+       for (tmpvpcidev = VpcidevListHead, prevvpcidev = NULL;
+            (tmpvpcidev && !found);
+            prevvpcidev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) {
+               if (tmpvpcidev->devtype != devtype)
+                       continue;
+
+               if (devtype == VIRTHBA_TYPE) {
+                       resumethisone =
+                           ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) &&
+                            (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2));
+                       /* devtype is vhba, we're resuming vhba whose
+                       * wwnn matches the current device's wwnn */
+               } else {        /* VIRTNIC_TYPE */
+                       resumethisone =
+                           memcmp(tmpvpcidev->net.mac_addr, macaddr,
+                                  MAX_MACADDR_LEN) == 0;
+                       /* devtype is vnic, we're resuming vnic whose
+                       * macaddr matches the current device's macaddr */
+               }
+
+               if (!resumethisone)
+                       continue;
+
+               found = true;
+               vpcidriver = tmpvpcidev->mydriver;
+               /* This should be done at BUS resume time, but an
+               * existing problem prevents us from ever getting a bus
+               * resume...  This hack would fail to work should we
+               * ever have a bus that contains NO devices, since we
+               * would never even get here in that case.
+               */
+               fix_vbus_devInfo(&tmpvpcidev->generic_dev, tmpvpcidev->deviceNo,
+                                tmpvpcidev->device, vpcidriver);
+               rc = vpcidriver->resume(tmpvpcidev);
+       }
+
+       write_unlock_irqrestore(&VpcidevListLock, flags);
+
+       if (!found) {
+               LOGERR("**** FAILED to find vhba/vnic in the list\n");
+               return 0;
+       }
+
+       return rc;
+}
+
+static int virtpci_device_del(struct device *parentbus,
+                             int devtype, struct vhba_wwnn *wwnn,
+                             unsigned char macaddr[])
+{
+       int count = 0, all = 0, delthisone;
+       struct virtpci_dev *tmpvpcidev, *prevvpcidev, *dellist = NULL;
+       unsigned long flags;
+
+#define DEL_CONTINUE { \
+       prevvpcidev = tmpvpcidev;\
+       tmpvpcidev = tmpvpcidev->next;\
+       continue; \
+}
+
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+               LOGERR("**** FAILED to delete device; devtype:%d not vhba:%d or vnic:%d\n",
+                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+               return 0;
+       }
+
+       /* see if we are to delete all - NOTE: all implies we have a
+        * valid parentbus
+        */
+       all = ((devtype == VIRTHBA_TYPE) && (wwnn == NULL)) ||
+           ((devtype == VIRTNIC_TYPE) && (macaddr == NULL));
+
+       /* find all the vhba or vnic or both in virtpci device list
+       * keep list of ones we are deleting so we can call
+       * device_unregister after we release the lock; otherwise we
+       * encounter "schedule while atomic"
+       */
+       write_lock_irqsave(&VpcidevListLock, flags);
+       for (tmpvpcidev = VpcidevListHead, prevvpcidev = NULL; tmpvpcidev;) {
+               if (tmpvpcidev->devtype != devtype)
+                       DEL_CONTINUE;
+
+               if (all) {
+                       delthisone =
+                           (tmpvpcidev->generic_dev.parent == parentbus);
+                       /* we're deleting all vhbas or vnics on the
+                        * specified parent bus
+                        */
+               } else if (devtype == VIRTHBA_TYPE) {
+                       delthisone =
+                           ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) &&
+                            (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2));
+                       /* devtype is vhba, we're deleting vhba whose
+                        * wwnn matches the current device's wwnn
+                        */
+               } else {        /* VIRTNIC_TYPE */
+                       delthisone =
+                           memcmp(tmpvpcidev->net.mac_addr, macaddr,
+                                  MAX_MACADDR_LEN) == 0;
+                       /* devtype is vnic, we're deleting vnic whose
+                       * macaddr matches the current device's macaddr
+                       */
+               }
+
+               if (!delthisone)
+                       DEL_CONTINUE;
+
+               /* take vhba/vnic out of the list */
+               if (prevvpcidev)
+                       /* not at head */
+                       prevvpcidev->next = tmpvpcidev->next;
+               else
+                       VpcidevListHead = tmpvpcidev->next;
+
+               /* add it to our deletelist */
+               tmpvpcidev->next = dellist;
+               dellist = tmpvpcidev;
+
+               count++;
+               if (!all)
+                       break;  /* done */
+               /* going to top of loop again - set tmpvpcidev to next
+                * one we're to process
+                */
+               if (prevvpcidev)
+                       tmpvpcidev = prevvpcidev->next;
+               else
+                       tmpvpcidev = VpcidevListHead;
+       }
+       write_unlock_irqrestore(&VpcidevListLock, flags);
+
+       if (!all && (count == 0)) {
+               LOGERR("**** FAILED to find vhba/vnic in the list\n");
+               return 0;
+       }
+
+       /* now delete each one from delete list */
+       while (dellist) {
+               /* save next */
+               tmpvpcidev = dellist->next;
+               /* delete the vhba/vnic at dellist */
+               DELETE_ONE_VPCIDEV(dellist);
+               /* do next */
+               dellist = tmpvpcidev;
+       }
+
+       return count;
+}
+
+static void virtpci_device_release(struct device *dev_)
+{
+       /* this function is called when the last reference to the
+        * device is removed
+        */
+       LOGINF("In virtpci_device_release:%p - NOT YET IMPLEMENTED\n", dev_);
+}
+
+/*****************************************************/
+/* Driver functions                                  */
+/*****************************************************/
+
+#define kobj_to_device_driver(obj) container_of(obj, struct device_driver, kobj)
+#define attribute_to_driver_attribute(obj) \
+       container_of(obj, struct driver_attribute, attr)
+
+static ssize_t virtpci_driver_attr_show(struct kobject *kobj,
+                                       struct attribute *attr,
+                                       char *buf)
+{
+       struct driver_attribute *dattr = attribute_to_driver_attribute(attr);
+       ssize_t ret = 0;
+
+       struct driver_private *dprivate = to_driver(kobj);
+       struct device_driver *driver;
+       if (dprivate != NULL)
+               driver = dprivate->driver;
+       else
+               driver = NULL;
+
+       DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name);
+       if (driver) {
+               if (dattr->show)
+                       ret = dattr->show(driver, buf);
+       }
+       return ret;
+}
+
+static ssize_t virtpci_driver_attr_store(struct kobject *kobj,
+                                        struct attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct driver_attribute *dattr = attribute_to_driver_attribute(attr);
+       ssize_t ret = 0;
+
+       struct driver_private *dprivate = to_driver(kobj);
+       struct device_driver *driver;
+       if (dprivate != NULL)
+               driver = dprivate->driver;
+       else
+               driver = NULL;
+
+       DBGINF("In virtpci_driver_attr_store driver->name:%s\n", driver->name);
+
+       if (driver) {
+               if (dattr->store)
+                       ret = dattr->store(driver, buf, count);
+       }
+       return ret;
+}
+
+/* register a new virtpci driver */
+int virtpci_register_driver(struct virtpci_driver *drv)
+{
+       int result = 0;
+
+       DBGINF("In virtpci_register_driver\n");
+
+       if (drv->id_table == NULL) {
+               LOGERR("id_table missing\n");
+               return 1;
+       }
+       /* initialize core driver fields needed to call driver_register */
+       drv->core_driver.name = drv->name;      /* name of driver in sysfs */
+       drv->core_driver.bus = &virtpci_bus_type;       /* type of bus this
+                                                        * driver works with */
+       drv->core_driver.probe = virtpci_device_probe;  /* called to query the
+                                                        * existence of a
+                                                        * specific device and
+                                                        * whether this driver
+                                                        *can work with it */
+       drv->core_driver.remove = virtpci_device_remove; /* called when the
+                                                         * device is removed
+                                                         * from the system */
+       /* register with core */
+       result = driver_register(&drv->core_driver);
+       /* calls bus_add_driver which calls driver_attach and
+        * module_add_driver
+        */
+       if (result)
+               return result;  /* failed */
+
+       drv->core_driver.p->kobj.ktype = &virtpci_driver_kobj_type;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(virtpci_register_driver);
+
+void virtpci_unregister_driver(struct virtpci_driver *drv)
+{
+       DBGINF("In virtpci_unregister_driver drv:%p\n", drv);
+       driver_unregister(&drv->core_driver);
+       /* driver_unregister calls bus_remove_driver
+        * bus_remove_driver calls device_detach
+        * device_detach calls device_release_driver for each of the
+        * driver's devices
+        * device_release driver calls drv->remove which is
+        * virtpci_device_remove
+        * virtpci_device_remove calls virthba_remove
+        */
+       DBGINF("Leaving\n");
+}
+EXPORT_SYMBOL_GPL(virtpci_unregister_driver);
+
+/*****************************************************/
+/* proc filesystem functions                                            */
+/*****************************************************/
+struct print_vbus_info {
+       int *length;
+       char *buf;
+};
+
+static int print_vbus(struct device *vbus, void *data)
+{
+       struct print_vbus_info *p = (struct print_vbus_info *) data;
+       int l = *(p->length);
+
+       *(p->length) = l + sprintf(p->buf + l, "bus_id:%s\n", dev_name(vbus));
+       return 0;               /* no error */
+}
+
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+                             size_t len, loff_t *offset)
+{
+       int length = 0;
+       struct virtpci_dev *tmpvpcidev;
+       unsigned long flags;
+       struct print_vbus_info printparam;
+       char *vbuf;
+       loff_t pos = *offset;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos > 0 || !len)
+               return 0;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       length += sprintf(vbuf + length, "CHANSOCK is not defined.\n");
+
+       length += sprintf(vbuf + length, "\n Virtual PCI Bus devices\n");
+       printparam.length = &length;
+       printparam.buf = vbuf;
+       if (bus_for_each_dev(&virtpci_bus_type, NULL,
+                            (void *) &printparam, print_vbus))
+               LOGERR("delete of all vbus failed\n");
+
+       length += sprintf(vbuf + length, "\n Virtual PCI devices\n");
+       read_lock_irqsave(&VpcidevListLock, flags);
+       tmpvpcidev = VpcidevListHead;
+       while (tmpvpcidev) {
+               if (tmpvpcidev->devtype == VIRTHBA_TYPE) {
+                       length += sprintf(vbuf + length, "[%d:%d] VHba:%08x:%08x max-config:%d-%d-%d-%d",
+                                   tmpvpcidev->busNo, tmpvpcidev->deviceNo,
+                                   tmpvpcidev->scsi.wwnn.wwnn1,
+                                   tmpvpcidev->scsi.wwnn.wwnn2,
+                                   tmpvpcidev->scsi.max.max_channel,
+                                   tmpvpcidev->scsi.max.max_id,
+                                   tmpvpcidev->scsi.max.max_lun,
+                                   tmpvpcidev->scsi.max.cmd_per_lun);
+               } else {
+                       length += sprintf(vbuf + length, "[%d:%d] VNic:%02x:%02x:%02x:%02x:%02x:%02x num_rcv_bufs:%d mtu:%d",
+                                   tmpvpcidev->busNo, tmpvpcidev->deviceNo,
+                                   tmpvpcidev->net.mac_addr[0],
+                                   tmpvpcidev->net.mac_addr[1],
+                                   tmpvpcidev->net.mac_addr[2],
+                                   tmpvpcidev->net.mac_addr[3],
+                                   tmpvpcidev->net.mac_addr[4],
+                                   tmpvpcidev->net.mac_addr[5],
+                                   tmpvpcidev->net.num_rcv_bufs,
+                                   tmpvpcidev->net.mtu);
+               }
+               length +=
+                   sprintf(vbuf + length, " chanptr:%p\n",
+                           tmpvpcidev->queueinfo.chan);
+               tmpvpcidev = tmpvpcidev->next;
+       }
+       read_unlock_irqrestore(&VpcidevListLock, flags);
+
+       length +=
+           sprintf(vbuf + length, "\nModule build: Date:%s Time:%s\n", __DATE__,
+                   __TIME__);
+
+       length += sprintf(vbuf + length, "\n");
+       if (copy_to_user(buf, vbuf, length)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+
+       kfree(vbuf);
+       *offset += length;
+       return length;
+}
+
+static ssize_t virt_proc_write(struct file *file, const char __user *buffer,
+                              size_t count, loff_t *ppos)
+{
+       char buf[count];
+       int type, i, action = 0xffff;
+       unsigned int busno, deviceno;
+       void *chanptr;
+       struct add_vbus_guestpart busaddparams;
+       struct add_virt_guestpart addparams;
+       struct del_vbus_guestpart busdelparams;
+       struct del_virt_guestpart delparams;
+       GUID dummyGuid = GUID0;
+#ifdef STORAGE_CHANNEL
+       U64 storagechannel;
+#endif
+
+#define PRINT_USAGE_RETURN {\
+       LOGERR("usage: 0-0-<chanptr>                                    ==> delete vhba\n"); \
+       LOGERR("usage: 0-1-<chanptr>-<busNo>-<deviceNo> ==> add vhba\n"); \
+       LOGERR("usage: 0-f-<busNo>                                              ==> delete all vhbas\n"); \
+       LOGERR("\n"); \
+       LOGERR("usage: 1-0-<chanptr>                                    ==> delete vnic\n"); \
+       LOGERR("usage: 1-1-<chanptr>-<busNo>-<deviceNo> ==> add vnic\n"); \
+       LOGERR("usage: 1-f-<busNo>                                              ==> delete all vnics\n"); \
+       LOGERR("\n"); \
+       LOGERR("usage: 6-0-<busNo>                                              ==> delete vbus\n"); \
+       LOGERR("usage: 6-1-<busNo>                                              ==> add vbus\n"); \
+       LOGERR("usage: 6-f                                                              ==> delete all vbuses\n"); \
+       LOGERR("usage: 98-<busNo>-<deviceNo>                    ==> INJECT Client delete vnic\n"); \
+       LOGERR("usage: 99-<chanptr>-<busNo>-<deviceNo>  ==> INJECT Client add vnic\n"); \
+       return -EINVAL; \
+}
+
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("copy_from_user failed.\n");
+               return -EFAULT;
+       }
+
+       i = sscanf(buf, "%x-%x", &type, &action);
+       if (i < 2)
+               PRINT_USAGE_RETURN;
+
+       if (type == 0x98) {
+               /* client inject delete vnic */
+               i = sscanf(buf, "%x-%d-%d", &type, &busno, &deviceno);
+               if (i != 3)
+                       PRINT_USAGE_RETURN;
+               uislib_client_inject_del_vnic(busno, deviceno);
+               return count;   /* success */
+       } else if (type == 0x99) {
+               /* client inject add vnic */
+               i = sscanf(buf, "%x-%p-%d-%d", &type, &chanptr, &busno,
+                          &deviceno);
+               if (i != 4)
+                       PRINT_USAGE_RETURN;
+               if (!uislib_client_inject_add_vnic(busno, deviceno,
+                                                  __pa(chanptr),
+                                                  MIN_IO_CHANNEL_SIZE,
+                                                  1, /* test msg */
+                                                  dummyGuid, /* inst guid */
+                                                  NULL)) { /*interrupt info */
+                       LOGERR("FAILED to inject add vnic\n");
+                       return -EFAULT;
+               }
+               return count;   /* success */
+       }
+
+       if ((type != VIRTHBA_TYPE) && (type != VIRTNIC_TYPE)
+           && (type != VIRTBUS_TYPE))
+               PRINT_USAGE_RETURN;
+
+       if (type == VIRTBUS_TYPE) {
+               i = sscanf(buf, "%x-%x-%d", &type, &action, &busno);
+               switch (action) {
+               case 0:
+                       /* delete vbus */
+                       if (i != 3)
+                               break;
+                       busdelparams.busNo = busno;
+                       if (delete_vbus(&busdelparams))
+                               return count;   /* success */
+                       return -EFAULT;
+
+               case 1:
+                       /* add vbus */
+                       if (i != 3)
+                               break;
+                       busaddparams.chanptr = NULL;    /* NOT YET USED */
+                       busaddparams.busNo = busno;
+                       if (add_vbus(&busaddparams))
+                               return count;   /* success */
+                       return -EFAULT;
+
+               case 0xf:
+                       /* delete all vbuses and all vhbas/vnics on the buses */
+                       if (i != 2)
+                               break;
+                       delete_all();
+                       return count;   /* success */
+               default:
+                       break;
+               }
+               PRINT_USAGE_RETURN;
+       }
+
+       /* if (type == VIRTNIC_TYPE) or         if (type == VIRTHBA_TYPE) */
+       switch (action) {
+       case 0:
+               /* delete vhba/vnic */
+               i = sscanf(buf, "%x-%x-%p", &type, &action, &chanptr);
+               if (i != 3)
+                       break;
+               delparams.chanptr = chanptr;
+               if (type == VIRTHBA_TYPE) {
+                       if (delete_vhba(&delparams))
+                               return count;   /* success */
+               } else {
+                       if (delete_vnic(&delparams))
+                               return count;   /* success */
+               }
+               return -EFAULT;
+
+       case 1:
+               /* add vhba/vnic */
+               i = sscanf(buf, "%x-%x-%p-%d-%d", &type, &action, &chanptr,
+                          &busno, &deviceno);
+               if (i != 5)
+                       break;
+               addparams.chanptr = chanptr;
+               addparams.busNo = busno;
+               addparams.deviceNo = deviceno;
+               if (type == VIRTHBA_TYPE) {
+                       if (add_vhba(&addparams))
+                               return count;   /* success */
+               } else {
+                       if (add_vnic(&addparams))
+                               return count;   /* success */
+               }
+               return -EFAULT;
+
+#ifdef STORAGE_CHANNEL
+       case 2:
+               /* add vhba */
+               i = sscanf(buf, "%x-%x-%d-%d", &type, &action, &busno,
+                          &deviceno);
+               if (i != 4)
+                       break;
+               storagechannel = uislib_storage_channel(0);     /* Get my storage channel */
+               /* ioremap_cache it now */
+               addparams.chanptr =
+                   (void *) ioremap_cache(storagechannel, IO_CHANNEL_SIZE);
+               if (addparams.chanptr == NULL) {
+                       LOGERR("Failure to get remap storage channel.\n");
+                       return -EFAULT;
+               }
+               addparams.busNo = busno;
+               addparams.deviceNo = deviceno;
+               if (type == VIRTHBA_TYPE) {
+                       if (add_vhba(&addparams))
+                               return count;   /* success */
+               }
+               return -EFAULT;
+#endif
+       case 0xf:
+               /* delete all vhbas/vnics */
+               i = sscanf(buf, "%x-%x-%d", &type, &action, &busno);
+               if (i != 3)
+                       break;
+               busdelparams.busNo = busno;
+               delete_all_virt(type, &busdelparams);
+               return count;   /* success */
+       default:
+               break;
+       }
+       PRINT_USAGE_RETURN;
+}
+
+/*****************************************************/
+/* Module Init & Exit functions                      */
+/*****************************************************/
+
+static int __init virtpci_mod_init(void)
+{
+       int ret;
+
+
+       LOGINF("Module build: Date:%s Time:%s...\n", __DATE__, __TIME__);
+
+       POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+       ret = bus_register(&virtpci_bus_type);
+       /* creates /sys/bus/uisvirtpci which contains devices &
+        * drivers directory
+        */
+       if (ret) {
+               LOGERR("bus_register ****FAILED:%d\n", ret);
+               POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret,
+                                POSTCODE_SEVERITY_ERR);
+               return ret;
+       }
+       DBGINF("bus_register successful\n");
+       BusDeviceInfo_Init(&Bus_DriverInfo,
+                          "clientbus", "virtpci",
+                          VERSION, NULL, __DATE__, __TIME__);
+
+       /* create a root bus used to parent all the virtpci buses. */
+       ret = device_register(&virtpci_rootbus_device);
+       if (ret) {
+               LOGERR("device_register FAILED:%d\n", ret);
+               bus_unregister(&virtpci_bus_type);
+               POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret,
+                                POSTCODE_SEVERITY_ERR);
+               return ret;
+       }
+       DBGINF("device_register successful ret:%x\n", ret);
+
+       if (!uisctrl_register_req_handler(2, (void *) &virtpci_ctrlchan_func,
+                                         &Chipset_DriverInfo)) {
+               LOGERR("uisctrl_register_req_handler ****FAILED.\n");
+               POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+               device_unregister(&virtpci_rootbus_device);
+               bus_unregister(&virtpci_bus_type);
+               return -1;
+       }
+
+       LOGINF("successfully registered virtpci_ctrlchan_func (0x%p) as callback.\n",
+            (void *) &virtpci_ctrlchan_func);
+       /* create the proc directories */
+       virtpci_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
+       virt_proc_entry = proc_create(VIRT_PROC_ENTRY_FN, 0, virtpci_proc_dir,
+                                     &proc_virt_fops);
+       info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0, virtpci_proc_dir,
+                                     &proc_info_fops);
+       LOGINF("Leaving\n");
+       POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       return 0;
+}
+
+static void __exit virtpci_mod_exit(void)
+{
+       LOGINF("virtpci_mod_exit...\n");
+
+       /* unregister the callback function */
+       if (!uisctrl_register_req_handler(2, NULL, NULL))
+               LOGERR("uisctrl_register_req_handler ****FAILED.\n");
+
+       device_unregister(&virtpci_rootbus_device);
+       bus_unregister(&virtpci_bus_type);
+
+       if (virt_proc_entry)
+               remove_proc_entry(VIRT_PROC_ENTRY_FN, virtpci_proc_dir);
+
+       if (info_proc_entry)
+               remove_proc_entry(INFO_PROC_ENTRY_FN, virtpci_proc_dir);
+
+       if (virtpci_proc_dir)
+               remove_proc_entry(DIR_PROC_ENTRY, NULL);
+
+       LOGINF("Leaving\n");
+
+}
+
+module_init(virtpci_mod_init);
+module_exit(virtpci_mod_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Usha Srinivasan");
+MODULE_ALIAS("uisvirtpci");
+
diff --git a/drivers/staging/unisys/virtpci/virtpci.h b/drivers/staging/unisys/virtpci/virtpci.h
new file mode 100644 (file)
index 0000000..b8fd07b
--- /dev/null
@@ -0,0 +1,104 @@
+/* virtpci.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys Virtual PCI driver header
+ */
+
+#ifndef __VIRTPCI_H__
+#define __VIRTPCI_H__
+
+#include "uisqueue.h"
+#include <linux/version.h>
+
+#define PCI_DEVICE_ID_VIRTHBA 0xAA00
+#define PCI_DEVICE_ID_VIRTNIC 0xAB00
+
+struct scsi_adap_info {
+       void *scsihost;         /* scsi host if this device is a scsi hba */
+       struct vhba_wwnn wwnn;  /* the world wide node name of vhba */
+       struct vhba_config_max max;     /* various max specifications used
+                                        * to config vhba */
+};
+
+struct net_adap_info {
+       struct net_device *netdev;      /* network device if this
+                                        * device is a NIC */
+       u8 mac_addr[MAX_MACADDR_LEN];
+       int num_rcv_bufs;
+       unsigned mtu;
+       GUID zoneGuid;
+};
+
+typedef enum {
+       VIRTHBA_TYPE = 0,
+       VIRTNIC_TYPE = 1,
+       VIRTBUS_TYPE = 6,
+} VIRTPCI_DEV_TYPE;
+
+struct virtpci_dev {
+       VIRTPCI_DEV_TYPE devtype;       /* indicates type of the
+                                        * virtual pci device */
+       struct virtpci_driver *mydriver;        /* which driver has allocated
+                                                * this device */
+       unsigned short vendor;  /* vendor id for device */
+       unsigned short device;  /* device id for device */
+       U32 busNo;              /* number of bus on which device exists */
+       U32 deviceNo;           /* device's number on the bus */
+       struct InterruptInfo intr;      /* interrupt info */
+       struct device generic_dev;      /* generic device */
+       union {
+               struct scsi_adap_info scsi;
+               struct net_adap_info net;
+       };
+
+       struct uisqueue_info queueinfo; /* holds ptr to channel where cmds &
+                                        * rsps are queued & retrieved */
+       struct virtpci_dev *next;       /* points to next virtpci device */
+};
+
+struct virtpci_driver {
+       struct list_head node;
+       const char *name;       /* the name of the driver in sysfs */
+       const char *version;
+       const char *vertag;
+       const char *build_date;
+       const char *build_time;
+       const struct pci_device_id *id_table;   /* must be non-NULL for probe
+                                                * to be called */
+       int (*probe)(struct virtpci_dev *dev,
+                     const struct pci_device_id *id); /* device inserted */
+       void (*remove)(struct virtpci_dev *dev); /* Device removed (NULL if
+                                                   * not a hot-plug capable
+                                                   * driver) */
+       int (*suspend)(struct virtpci_dev *dev,
+                       u32 state);                /* Device suspended */
+       int (*resume)(struct virtpci_dev *dev); /* Device woken up */
+       int (*enable_wake)(struct virtpci_dev *dev,
+                           u32 state, int enable);     /* Enable wake event */
+       struct device_driver core_driver;       /* VIRTPCI core fills this in */
+};
+
+#define        driver_to_virtpci_driver(in_drv) \
+       container_of(in_drv, struct virtpci_driver, core_driver)
+#define device_to_virtpci_dev(in_dev) \
+       container_of(in_dev, struct virtpci_dev, generic_dev)
+
+int virtpci_register_driver(struct virtpci_driver *);
+void virtpci_unregister_driver(struct virtpci_driver *);
+
+#endif /* __VIRTPCI_H__ */
diff --git a/drivers/staging/unisys/visorchannel/Kconfig b/drivers/staging/unisys/visorchannel/Kconfig
new file mode 100644 (file)
index 0000000..41c3b4b
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys visorchannel configuration
+#
+
+config UNISYS_VISORCHANNEL
+       tristate "Unisys visorchannel driver"
+       depends on UNISYSSPAR && UNISYS_VISORUTIL
+       ---help---
+       If you say Y here, you will enable the Unisys visorchannel driver.
+
diff --git a/drivers/staging/unisys/visorchannel/Makefile b/drivers/staging/unisys/visorchannel/Makefile
new file mode 100644 (file)
index 0000000..f0060be
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for Unisys visorchannel
+#
+
+obj-$(CONFIG_UNISYS_VISORCHANNEL)      += visorchannel.o
+
+visorchannel-y := visorchannel_main.o visorchannel_funcs.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -Idrivers/staging/unisys/visorutil
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/visorchannel/globals.h b/drivers/staging/unisys/visorchannel/globals.h
new file mode 100644 (file)
index 0000000..668f832
--- /dev/null
@@ -0,0 +1,29 @@
+/* globals.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHANNEL_GLOBALS_H__
+#define __VISORCHANNEL_GLOBALS_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "memregion.h"
+#include "version.h"
+
+#define MYDRVNAME "visorchannel"
+
+
+#endif
diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h
new file mode 100644 (file)
index 0000000..4546686
--- /dev/null
@@ -0,0 +1,106 @@
+/* visorchannel.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHANNEL_H__
+#define __VISORCHANNEL_H__
+
+#include "commontypes.h"
+#include "memregion.h"
+#include "channel.h"
+#ifndef HOSTADDRESS
+#define HOSTADDRESS U64
+#endif
+#ifndef BOOL
+#define BOOL int
+#endif
+
+/* VISORCHANNEL is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct VISORCHANNEL_Tag VISORCHANNEL;
+
+/* Note that for visorchannel_create() and visorchannel_create_overlapped(),
+ * <channelBytes> and <guid> arguments may be 0 if we are a channel CLIENT.
+ * In this case, the values can simply be read from the channel header.
+ */
+VISORCHANNEL *visorchannel_create(HOSTADDRESS physaddr,
+                                 ulong channelBytes, GUID guid);
+VISORCHANNEL *visorchannel_create_overlapped(ulong channelBytes,
+                                            VISORCHANNEL *parent, ulong off,
+                                            GUID guid);
+VISORCHANNEL *visorchannel_create_with_lock(HOSTADDRESS physaddr,
+                                           ulong channelBytes, GUID guid);
+VISORCHANNEL *visorchannel_create_overlapped_with_lock(ulong channelBytes,
+                                                      VISORCHANNEL *parent,
+                                                      ulong off, GUID guid);
+void visorchannel_destroy(VISORCHANNEL *channel);
+int visorchannel_read(VISORCHANNEL *channel, ulong offset,
+                     void *local, ulong nbytes);
+int visorchannel_write(VISORCHANNEL *channel, ulong offset,
+                      void *local, ulong nbytes);
+int visorchannel_clear(VISORCHANNEL *channel, ulong offset,
+                      U8 ch, ulong nbytes);
+BOOL visorchannel_signalremove(VISORCHANNEL *channel, U32 queue, void *msg);
+BOOL visorchannel_signalinsert(VISORCHANNEL *channel, U32 queue, void *msg);
+int visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, U32 queue);
+int visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, U32 queue);
+
+HOSTADDRESS visorchannel_get_physaddr(VISORCHANNEL *channel);
+ulong visorchannel_get_nbytes(VISORCHANNEL *channel);
+char *visorchannel_id(VISORCHANNEL *channel, char *s);
+char *visorchannel_zoneid(VISORCHANNEL *channel, char *s);
+U64 visorchannel_get_clientpartition(VISORCHANNEL *channel);
+GUID visorchannel_get_GUID(VISORCHANNEL *channel);
+MEMREGION *visorchannel_get_memregion(VISORCHANNEL *channel);
+char *visorchannel_GUID_id(GUID *guid, char *s);
+void visorchannel_debug(VISORCHANNEL *channel, int nQueues,
+                       struct seq_file *seq, U32 off);
+void visorchannel_dump_section(VISORCHANNEL *chan, char *s,
+                              int off, int len, struct seq_file *seq);
+void *visorchannel_get_header(VISORCHANNEL *channel);
+
+#define        VISORCHANNEL_CHANGE_SERVER_STATE(chan, chanId, newstate)        \
+       do {                                                            \
+               U8 *p = (U8 *)visorchannel_get_header(chan);            \
+               if (p) {                                                \
+                       ULTRA_CHANNEL_SERVER_TRANSITION(p, chanId, SrvState, \
+                                                       newstate, logCtx); \
+                       visorchannel_write                              \
+                               (chan,                                  \
+                                offsetof(ULTRA_CHANNEL_PROTOCOL, SrvState), \
+                                p +                                    \
+                                offsetof(ULTRA_CHANNEL_PROTOCOL, SrvState), \
+                                sizeof(U32));                          \
+               }                                                       \
+       } while (0)
+
+#define        VISORCHANNEL_CHANGE_CLIENT_STATE(chan, chanId, newstate)        \
+       do {                                                            \
+               U8 *p = (U8 *)visorchannel_get_header(chan);            \
+               if (p) {                                                \
+                       ULTRA_CHANNEL_CLIENT_TRANSITION(p, chanId, CliStateOS, \
+                                                       newstate, logCtx); \
+                       visorchannel_write                              \
+                               (chan,                                  \
+                                offsetof(ULTRA_CHANNEL_PROTOCOL, CliStateOS), \
+                                p +                                    \
+                                offsetof(ULTRA_CHANNEL_PROTOCOL, CliStateOS), \
+                                sizeof(U32));                          \
+               }                                                       \
+       } while (0)
+
+#endif
diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c
new file mode 100644 (file)
index 0000000..509c77b
--- /dev/null
@@ -0,0 +1,765 @@
+/* visorchannel_funcs.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This provides Supervisor channel communication primitives, which are
+ *  independent of the mechanism used to access the channel data.  All channel
+ *  data is accessed using the memregion abstraction.  (memregion has both
+ *  a CM2 implementation and a direct memory implementation.)
+ */
+
+#include "globals.h"
+#include "visorchannel.h"
+#include "guidutils.h"
+
+#define MYDRVNAME "visorchannel"
+
+struct VISORCHANNEL_Tag {
+       MEMREGION *memregion;   /* from memregion_create() */
+       CHANNEL_HEADER chan_hdr;
+       GUID guid;
+       ulong size;
+       BOOL needs_lock;
+       spinlock_t insert_lock;
+       spinlock_t remove_lock;
+
+       struct {
+               SIGNAL_QUEUE_HEADER req_queue;
+               SIGNAL_QUEUE_HEADER rsp_queue;
+               SIGNAL_QUEUE_HEADER event_queue;
+               SIGNAL_QUEUE_HEADER ack_queue;
+       } safe_uis_queue;
+};
+
+/* Creates the VISORCHANNEL abstraction for a data area in memory, but does
+ * NOT modify this data area.
+ */
+static VISORCHANNEL *
+visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes,
+                        VISORCHANNEL *parent, ulong off, GUID guid,
+                        BOOL needs_lock)
+{
+       VISORCHANNEL *p = NULL;
+       void *rc = NULL;
+
+       p = kmalloc(sizeof(VISORCHANNEL), GFP_KERNEL|__GFP_NORETRY);
+       if (p == NULL)
+               FAIL("allocation failed", 0);
+       p->memregion = NULL;
+       p->needs_lock = needs_lock;
+       spin_lock_init(&p->insert_lock);
+       spin_lock_init(&p->remove_lock);
+
+       /* prepare chan_hdr (abstraction to read/write channel memory) */
+       if (parent == NULL)
+               p->memregion =
+                   memregion_create(physaddr, sizeof(CHANNEL_HEADER));
+       else
+               p->memregion =
+                   memregion_create_overlapped
+                   (parent->memregion, off, sizeof(CHANNEL_HEADER));
+       if (p->memregion == NULL)
+               FAIL("memregion_create failed", 0);
+       if (memregion_read(p->memregion, 0, &p->chan_hdr,
+                          sizeof(CHANNEL_HEADER)) < 0)
+               FAIL("memregion_read failed", 0);
+       if (channelBytes == 0)
+               /* we had better be a CLIENT of this channel */
+               channelBytes = (ulong) p->chan_hdr.Size;
+       if (STRUCTSEQUAL(guid, Guid0))
+               /* we had better be a CLIENT of this channel */
+               guid = p->chan_hdr.Type;
+       if (memregion_resize(p->memregion, channelBytes) < 0)
+               FAIL("memregion_resize failed", 0);
+       p->size = channelBytes;
+       p->guid = guid;
+
+       RETPTR(p);
+
+Away:
+
+       if (rc == NULL) {
+               if (p != NULL) {
+                       visorchannel_destroy(p);
+                       p = NULL;
+               }
+       }
+       return rc;
+}
+
+VISORCHANNEL *
+visorchannel_create(HOSTADDRESS physaddr, ulong channelBytes, GUID guid)
+{
+       return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid,
+                                       FALSE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create);
+
+VISORCHANNEL *
+visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channelBytes,
+                             GUID guid)
+{
+       return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid,
+                                       TRUE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
+
+VISORCHANNEL *
+visorchannel_create_overlapped(ulong channelBytes,
+                              VISORCHANNEL *parent, ulong off, GUID guid)
+{
+       return visorchannel_create_guts(0, channelBytes, parent, off, guid,
+                                       FALSE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_overlapped);
+
+VISORCHANNEL *
+visorchannel_create_overlapped_with_lock(ulong channelBytes,
+                                        VISORCHANNEL *parent, ulong off,
+                                        GUID guid)
+{
+       return visorchannel_create_guts(0, channelBytes, parent, off, guid,
+                                       TRUE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock);
+
+void
+visorchannel_destroy(VISORCHANNEL *channel)
+{
+       if (channel == NULL)
+               return;
+       if (channel->memregion != NULL) {
+               memregion_destroy(channel->memregion);
+               channel->memregion = NULL;
+       }
+       kfree(channel);
+}
+EXPORT_SYMBOL_GPL(visorchannel_destroy);
+
+HOSTADDRESS
+visorchannel_get_physaddr(VISORCHANNEL *channel)
+{
+       return memregion_get_physaddr(channel->memregion);
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
+
+ulong
+visorchannel_get_nbytes(VISORCHANNEL *channel)
+{
+       return channel->size;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
+
+char *
+visorchannel_GUID_id(GUID *guid, char *s)
+{
+       return GUID_format1(guid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_GUID_id);
+
+char *
+visorchannel_id(VISORCHANNEL *channel, char *s)
+{
+       return visorchannel_GUID_id(&channel->guid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_id);
+
+char *
+visorchannel_zoneid(VISORCHANNEL *channel, char *s)
+{
+       return visorchannel_GUID_id(&channel->chan_hdr.ZoneGuid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_zoneid);
+
+HOSTADDRESS
+visorchannel_get_clientpartition(VISORCHANNEL *channel)
+{
+       return channel->chan_hdr.PartitionHandle;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
+
+GUID
+visorchannel_get_GUID(VISORCHANNEL *channel)
+{
+       return channel->guid;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_GUID);
+
+MEMREGION *
+visorchannel_get_memregion(VISORCHANNEL *channel)
+{
+       return channel->memregion;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_memregion);
+
+pSIGNAL_QUEUE_HEADER
+visorchannel_get_safe_queue(VISORCHANNEL *pchannel, U32 queue)
+{
+       switch (queue) {
+       case 0:
+               return &pchannel->safe_uis_queue.req_queue;
+       case 1:
+               return &pchannel->safe_uis_queue.rsp_queue;
+       case 2:
+               return &pchannel->safe_uis_queue.event_queue;
+       case 3:
+               return &pchannel->safe_uis_queue.ack_queue;
+       default:
+               ERRDRV("Invalid queue value %d\n", queue);
+               return NULL;
+       }
+}                              /* end visorchannel_get_safe_queue */
+
+int
+visorchannel_read(VISORCHANNEL *channel, ulong offset,
+                 void *local, ulong nbytes)
+{
+       int rc = memregion_read(channel->memregion, offset, local, nbytes);
+       if ((rc >= 0) && (offset == 0) && (nbytes >= sizeof(CHANNEL_HEADER)))
+               memcpy(&channel->chan_hdr, local, sizeof(CHANNEL_HEADER));
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_read);
+
+int
+visorchannel_write(VISORCHANNEL *channel, ulong offset,
+                  void *local, ulong nbytes)
+{
+       if (offset == 0 && nbytes >= sizeof(CHANNEL_HEADER))
+               memcpy(&channel->chan_hdr, local, sizeof(CHANNEL_HEADER));
+       return memregion_write(channel->memregion, offset, local, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorchannel_write);
+
+int
+visorchannel_clear(VISORCHANNEL *channel, ulong offset, U8 ch, ulong nbytes)
+{
+       int rc = -1;
+       int bufsize = 65536;
+       int written = 0;
+       U8 *buf = vmalloc(bufsize);
+
+       if (buf == NULL) {
+               ERRDRV("%s failed memory allocation", __func__);
+               RETINT(-1);
+       }
+       memset(buf, ch, bufsize);
+       while (nbytes > 0) {
+               ulong thisbytes = bufsize;
+               int x = -1;
+               if (nbytes < thisbytes)
+                       thisbytes = nbytes;
+               x = memregion_write(channel->memregion, offset + written,
+                                   buf, thisbytes);
+               if (x < 0)
+                       RETINT(x);
+               written += thisbytes;
+               nbytes -= thisbytes;
+       }
+       RETINT(0);
+
+Away:
+       if (buf != NULL) {
+               vfree(buf);
+               buf = NULL;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_clear);
+
+void *
+visorchannel_get_header(VISORCHANNEL *channel)
+{
+       return (void *) &(channel->chan_hdr);
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_header);
+
+/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
+ *  channel header
+ */
+#define SIG_QUEUE_OFFSET(chan_hdr, q) \
+       ((chan_hdr)->oChannelSpace + ((q) * sizeof(SIGNAL_QUEUE_HEADER)))
+
+/** Return offset of a specific queue entry (data) from the beginning of a
+ *  channel header
+ */
+#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
+       (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->oSignalBase + \
+           ((slot) * (sig_hdr)->SignalSize))
+
+/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
+ *  into host memory
+ */
+#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)                \
+       (memregion_write(channel->memregion,                        \
+                        SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+\
+                          offsetof(SIGNAL_QUEUE_HEADER, FIELD),     \
+                        &((sig_hdr)->FIELD),                       \
+                        sizeof((sig_hdr)->FIELD)) >= 0)
+
+static BOOL
+sig_read_header(VISORCHANNEL *channel, U32 queue,
+               SIGNAL_QUEUE_HEADER *sig_hdr)
+{
+       BOOL rc = FALSE;
+
+       if (channel->chan_hdr.oChannelSpace < sizeof(CHANNEL_HEADER))
+               FAIL("oChannelSpace too small", FALSE);
+
+       /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
+
+       if (memregion_read(channel->memregion,
+                          SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
+                          sig_hdr, sizeof(SIGNAL_QUEUE_HEADER)) < 0) {
+               ERRDRV("queue=%d SIG_QUEUE_OFFSET=%d",
+                      queue, (int)SIG_QUEUE_OFFSET(&channel->chan_hdr, queue));
+               FAIL("memregion_read of signal queue failed", FALSE);
+       }
+       RETBOOL(TRUE);
+Away:
+       return rc;
+}
+
+static BOOL
+sig_do_data(VISORCHANNEL *channel, U32 queue,
+           SIGNAL_QUEUE_HEADER *sig_hdr, U32 slot, void *data, BOOL is_write)
+{
+       BOOL rc = FALSE;
+       int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
+                                                sig_hdr, slot);
+       if (is_write) {
+               if (memregion_write(channel->memregion, signal_data_offset,
+                                   data, sig_hdr->SignalSize) < 0)
+                       FAIL("memregion_write of signal data failed", FALSE);
+       } else {
+               if (memregion_read(channel->memregion, signal_data_offset,
+                                  data, sig_hdr->SignalSize) < 0)
+                       FAIL("memregion_read of signal data failed", FALSE);
+       }
+       RETBOOL(TRUE);
+Away:
+       return rc;
+}
+
+static inline BOOL
+sig_read_data(VISORCHANNEL *channel, U32 queue,
+             SIGNAL_QUEUE_HEADER *sig_hdr, U32 slot, void *data)
+{
+       return sig_do_data(channel, queue, sig_hdr, slot, data, FALSE);
+}
+
+static inline BOOL
+sig_write_data(VISORCHANNEL *channel, U32 queue,
+              SIGNAL_QUEUE_HEADER *sig_hdr, U32 slot, void *data)
+{
+       return sig_do_data(channel, queue, sig_hdr, slot, data, TRUE);
+}
+
+static inline unsigned char
+safe_sig_queue_validate(pSIGNAL_QUEUE_HEADER psafe_sqh,
+                       pSIGNAL_QUEUE_HEADER punsafe_sqh,
+                       U32 *phead, U32 *ptail)
+{
+       if ((*phead >= psafe_sqh->MaxSignalSlots)
+           || (*ptail >= psafe_sqh->MaxSignalSlots)) {
+               /* Choose 0 or max, maybe based on current tail value */
+               *phead = 0;
+               *ptail = 0;
+
+               /* Sync with client as necessary */
+               punsafe_sqh->Head = *phead;
+               punsafe_sqh->Tail = *ptail;
+
+               ERRDRV("safe_sig_queue_validate: head = 0x%x, tail = 0x%x, MaxSlots = 0x%x",
+                    *phead, *ptail, psafe_sqh->MaxSignalSlots);
+               return 0;
+       }
+       return 1;
+}                              /* end safe_sig_queue_validate */
+
+BOOL
+visorchannel_signalremove(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+       BOOL rc = FALSE;
+       SIGNAL_QUEUE_HEADER sig_hdr;
+
+       if (channel->needs_lock)
+               spin_lock(&channel->remove_lock);
+
+       if (!sig_read_header(channel, queue, &sig_hdr))
+               RETBOOL(FALSE);
+       if (sig_hdr.Head == sig_hdr.Tail)
+               RETBOOL(FALSE); /* no signals to remove */
+       sig_hdr.Tail = (sig_hdr.Tail + 1) % sig_hdr.MaxSignalSlots;
+       if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.Tail, msg))
+               FAIL("sig_read_data failed", FALSE);
+       sig_hdr.NumSignalsReceived++;
+
+       /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+        * update host memory.
+        */
+       MEMORYBARRIER;
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, Tail))
+               FAIL("memregion_write of Tail failed", FALSE);
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, NumSignalsReceived))
+               FAIL("memregion_write of NumSignalsReceived failed", FALSE);
+
+       RETBOOL(TRUE);
+
+Away:
+       if (channel->needs_lock)
+               spin_unlock(&channel->remove_lock);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalremove);
+
+BOOL
+visorchannel_safesignalremove(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+       BOOL rc = FALSE;
+       SIGNAL_QUEUE_HEADER *psafe_sqh, unsafe_sqh;
+       int stat;
+
+       if (channel->needs_lock)
+               spin_lock(&channel->remove_lock);
+
+       if (!sig_read_header(channel, queue, &unsafe_sqh))
+               RETBOOL(FALSE);
+
+       psafe_sqh = visorchannel_get_safe_queue(channel, queue);
+       if (psafe_sqh == NULL) {
+               ERRDRV("safesignalremove: get_safe_queue failed\n");
+               RETBOOL(FALSE);
+       }
+
+       stat =
+           safe_sig_queue_validate(psafe_sqh, &unsafe_sqh, &unsafe_sqh.Head,
+                                   &unsafe_sqh.Tail);
+       if (stat == 0) {
+               ERRDRV("safe_signal_remove: safe_sig_queue_validate failed, queue = %d",
+                    queue);
+               RETBOOL(FALSE);
+       }
+
+       if (unsafe_sqh.Head == unsafe_sqh.Tail)
+               RETBOOL(FALSE); /* no signals to remove */
+       unsafe_sqh.Tail = (unsafe_sqh.Tail + 1) % psafe_sqh->MaxSignalSlots;
+       if (!sig_read_data(channel, queue, psafe_sqh, unsafe_sqh.Tail, msg))
+               FAIL("sig_read_data failed", FALSE);
+       unsafe_sqh.NumSignalsReceived++;
+
+       /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+        * update host memory.
+        */
+       MEMORYBARRIER;
+       if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, Tail))
+               FAIL("memregion_write of Tail failed", FALSE);
+       if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, NumSignalsReceived))
+               FAIL("memregion_write of NumSignalsReceived failed", FALSE);
+
+       RETBOOL(TRUE);
+
+Away:
+       if (channel->needs_lock)
+               spin_unlock(&channel->remove_lock);
+
+       return rc;
+}                              /* end visorchannel_safesignalremove */
+
+BOOL
+visorchannel_signalinsert(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+       BOOL rc = FALSE;
+       SIGNAL_QUEUE_HEADER sig_hdr;
+
+       if (channel->needs_lock)
+               spin_lock(&channel->insert_lock);
+
+       if (!sig_read_header(channel, queue, &sig_hdr))
+               RETBOOL(FALSE);
+
+       sig_hdr.Head = ((sig_hdr.Head + 1) % sig_hdr.MaxSignalSlots);
+       if (sig_hdr.Head == sig_hdr.Tail) {
+#if 0
+               ERRDRV("visorchannel queue #%d overflow (max slots=%d)",
+                      queue, sig_hdr.MaxSignalSlots);
+#endif
+               sig_hdr.NumOverflows++;
+               if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, NumOverflows))
+                       FAIL("memregion_write of NumOverflows failed", FALSE);
+               RETBOOL(FALSE);
+       }
+
+       if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.Head, msg))
+               FAIL("sig_write_data failed", FALSE);
+       sig_hdr.NumSignalsSent++;
+
+       /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+        * update host memory.
+        */
+       MEMORYBARRIER;
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, Head))
+               FAIL("memregion_write of Head failed", FALSE);
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, NumSignalsSent))
+               FAIL("memregion_write of NumSignalsSent failed", FALSE);
+
+       RETBOOL(TRUE);
+
+Away:
+       if (channel->needs_lock)
+               spin_unlock(&channel->insert_lock);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
+
+
+int
+visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, U32 queue)
+{
+       SIGNAL_QUEUE_HEADER sig_hdr;
+       U32 slots_avail, slots_used;
+       U32 head, tail;
+
+       if (!sig_read_header(channel, queue, &sig_hdr))
+               return 0;
+       head = sig_hdr.Head;
+       tail = sig_hdr.Tail;
+       if (head < tail)
+               head = head + sig_hdr.MaxSignalSlots;
+       slots_used = (head - tail);
+       slots_avail = sig_hdr.MaxSignals - slots_used;
+       return (int) slots_avail;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
+
+int
+visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, U32 queue)
+{
+       SIGNAL_QUEUE_HEADER sig_hdr;
+       if (!sig_read_header(channel, queue, &sig_hdr))
+               return 0;
+       return (int) sig_hdr.MaxSignals;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
+
+BOOL
+visorchannel_safesignalinsert(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+       BOOL rc = FALSE;
+       SIGNAL_QUEUE_HEADER *psafe_sqh, unsafe_sqh;
+       int stat;
+
+       if (channel->needs_lock)
+               spin_lock(&channel->insert_lock);
+
+       if (!sig_read_header(channel, queue, &unsafe_sqh))
+               RETBOOL(FALSE);
+
+       psafe_sqh = visorchannel_get_safe_queue(channel, queue);
+       if (psafe_sqh == NULL) {
+               ERRDRV("safesignalinsert: get_safe_queue failed\n");
+               RETBOOL(FALSE);
+       }
+
+       unsafe_sqh.Head = ((unsafe_sqh.Head + 1) % psafe_sqh->MaxSignalSlots);
+
+       stat =
+           safe_sig_queue_validate(psafe_sqh, &unsafe_sqh, &unsafe_sqh.Head,
+                                   &unsafe_sqh.Tail);
+       if (stat == 0) {
+               ERRDRV("safe_signal_insert: safe_sig_queue_validate failed, queue = %d",
+                    queue);
+               RETBOOL(FALSE);
+       }
+
+       if (unsafe_sqh.Head == unsafe_sqh.Tail) {
+#if 0
+               ERRDRV("visorchannel queue #%d overflow (max slots=%d)",
+                      queue, psafe_sqh->MaxSignalSlots);
+#endif
+               unsafe_sqh.NumOverflows++;
+               if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, NumOverflows))
+                       FAIL("memregion_write of NumOverflows failed", FALSE);
+               RETBOOL(FALSE);
+       }
+
+       if (!sig_write_data(channel, queue, psafe_sqh, unsafe_sqh.Head, msg))
+               FAIL("sig_write_data failed", FALSE);
+       unsafe_sqh.NumSignalsSent++;
+
+       /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+        * update host memory.
+        */
+       MEMORYBARRIER;
+       if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, Head))
+               FAIL("memregion_write of Head failed", FALSE);
+       if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, NumSignalsSent))
+               FAIL("memregion_write of NumSignalsSent failed", FALSE);
+
+       RETBOOL(TRUE);
+
+Away:
+       if (channel->needs_lock)
+               spin_unlock(&channel->insert_lock);
+
+       return rc;
+}                              /* end visorchannel_safesignalinsert */
+
+static void
+sigqueue_debug(SIGNAL_QUEUE_HEADER *q, int which, struct seq_file *seq)
+{
+       seq_printf(seq, "Signal Queue #%d\n", which);
+       seq_printf(seq, "   VersionId          = %lu\n", (ulong) q->VersionId);
+       seq_printf(seq, "   Type               = %lu\n", (ulong) q->Type);
+       seq_printf(seq, "   oSignalBase        = %llu\n",
+                  (long long) q->oSignalBase);
+       seq_printf(seq, "   SignalSize         = %lu\n", (ulong) q->SignalSize);
+       seq_printf(seq, "   MaxSignalSlots     = %lu\n",
+                  (ulong) q->MaxSignalSlots);
+       seq_printf(seq, "   MaxSignals         = %lu\n", (ulong) q->MaxSignals);
+       seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
+                  (long long) q->FeatureFlags);
+       seq_printf(seq, "   NumSignalsSent     = %llu\n",
+                  (long long) q->NumSignalsSent);
+       seq_printf(seq, "   NumSignalsReceived = %llu\n",
+                  (long long) q->NumSignalsReceived);
+       seq_printf(seq, "   NumOverflows       = %llu\n",
+                  (long long) q->NumOverflows);
+       seq_printf(seq, "   Head               = %lu\n", (ulong) q->Head);
+       seq_printf(seq, "   Tail               = %lu\n", (ulong) q->Tail);
+}
+
+void
+visorchannel_debug(VISORCHANNEL *channel, int nQueues,
+                  struct seq_file *seq, U32 off)
+{
+       HOSTADDRESS addr = 0;
+       ulong nbytes = 0, nbytes_region = 0;
+       MEMREGION *memregion = NULL;
+       CHANNEL_HEADER hdr;
+       CHANNEL_HEADER *phdr = &hdr;
+       char s[99];
+       int i = 0;
+       int errcode = 0;
+
+       if (channel == NULL) {
+               ERRDRV("%s no channel", __func__);
+               return;
+       }
+       memregion = channel->memregion;
+       if (memregion == NULL) {
+               ERRDRV("%s no memregion", __func__);
+               return;
+       }
+       addr = memregion_get_physaddr(memregion);
+       nbytes_region = memregion_get_nbytes(memregion);
+       errcode = visorchannel_read(channel, off,
+                                   phdr, sizeof(CHANNEL_HEADER));
+       if (errcode < 0) {
+               seq_printf(seq,
+                          "Read of channel header failed with errcode=%d)\n",
+                          errcode);
+               if (off == 0) {
+                       phdr = &channel->chan_hdr;
+                       seq_puts(seq, "(following data may be stale)\n");
+               } else
+                       return;
+       }
+       nbytes = (ulong) (phdr->Size);
+       seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
+                  addr + off, nbytes, nbytes_region);
+       seq_printf(seq, "Type            = %s\n", GUID_format2(&phdr->Type, s));
+       seq_printf(seq, "ZoneGuid        = %s\n",
+                  GUID_format2(&phdr->ZoneGuid, s));
+       seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
+                  (long long) phdr->Signature);
+       seq_printf(seq, "LegacyState     = %lu\n", (ulong) phdr->LegacyState);
+       seq_printf(seq, "SrvState        = %lu\n", (ulong) phdr->SrvState);
+       seq_printf(seq, "CliStateBoot    = %lu\n", (ulong) phdr->CliStateBoot);
+       seq_printf(seq, "CliStateOS      = %lu\n", (ulong) phdr->CliStateOS);
+       seq_printf(seq, "HeaderSize      = %lu\n", (ulong) phdr->HeaderSize);
+       seq_printf(seq, "Size            = %llu\n", (long long) phdr->Size);
+       seq_printf(seq, "Features        = 0x%-16.16llx\n",
+                  (long long) phdr->Features);
+       seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
+                  (long long) phdr->PartitionHandle);
+       seq_printf(seq, "Handle          = 0x%-16.16llx\n",
+                  (long long) phdr->Handle);
+       seq_printf(seq, "VersionId       = %lu\n", (ulong) phdr->VersionId);
+       seq_printf(seq, "oChannelSpace   = %llu\n",
+                  (long long) phdr->oChannelSpace);
+       if ((phdr->oChannelSpace == 0) || (errcode < 0))
+               ;
+       else
+               for (i = 0; i < nQueues; i++) {
+                       SIGNAL_QUEUE_HEADER q;
+                       errcode = visorchannel_read(channel,
+                                                   off + phdr->oChannelSpace +
+                                                   (i * sizeof(q)),
+                                                   &q, sizeof(q));
+                       if (errcode < 0) {
+                               seq_printf(seq,
+                                          "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
+                                          i, addr, errcode);
+                               continue;
+                       }
+                       sigqueue_debug(&q, i, seq);
+               }
+       seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
+                  addr + off, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorchannel_debug);
+
+void
+visorchannel_dump_section(VISORCHANNEL *chan, char *s,
+                         int off, int len, struct seq_file *seq)
+{
+       char *buf = NULL, *fmtbuf = NULL;
+       int fmtbufsize = 0;
+       int i = 0;
+       int errcode = 0;
+
+       fmtbufsize = 100 * COVQ(len, 16);
+       buf = kmalloc(len, GFP_KERNEL|__GFP_NORETRY);
+       fmtbuf = kmalloc(fmtbufsize, GFP_KERNEL|__GFP_NORETRY);
+       if (buf == NULL || fmtbuf == NULL)
+               goto Away;
+
+       errcode = visorchannel_read(chan, off, buf, len);
+       if (errcode < 0) {
+               ERRDRV("%s failed to read %s from channel errcode=%d",
+                      s, __func__, errcode);
+               goto Away;
+       }
+       seq_printf(seq, "channel %s:\n", s);
+       hexDumpToBuffer(fmtbuf, fmtbufsize, "  ", buf, len, 16);
+       for (i = 0; fmtbuf[i] != '\0'; i++)
+               seq_printf(seq, "%c", fmtbuf[i]);
+
+Away:
+       if (buf != NULL) {
+               kfree(buf);
+               buf = NULL;
+       }
+       if (fmtbuf != NULL) {
+               kfree(fmtbuf);
+               fmtbuf = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(visorchannel_dump_section);
diff --git a/drivers/staging/unisys/visorchannel/visorchannel_main.c b/drivers/staging/unisys/visorchannel/visorchannel_main.c
new file mode 100644 (file)
index 0000000..482ee0a
--- /dev/null
@@ -0,0 +1,49 @@
+/* visorchannel_main.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This is a module "wrapper" around visorchannel_funcs.
+ */
+
+#include "globals.h"
+#include "channel.h"
+#include "visorchannel.h"
+#include "guidutils.h"
+
+#define MYDRVNAME "visorchannel"
+
+static int __init
+visorchannel_init(void)
+{
+       INFODRV("driver version %s loaded", VERSION);
+       return 0;
+}
+
+static void
+visorchannel_exit(void)
+{
+       INFODRV("driver unloaded");
+}
+
+module_init(visorchannel_init);
+module_exit(visorchannel_exit);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Supervisor channel driver for service partition: ver "
+                  VERSION);
+MODULE_VERSION(VERSION);
diff --git a/drivers/staging/unisys/visorchipset/Kconfig b/drivers/staging/unisys/visorchipset/Kconfig
new file mode 100644 (file)
index 0000000..7ca2fbc
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys visorchipset configuration
+#
+
+config UNISYS_VISORCHIPSET
+       tristate "Unisys visorchipset driver"
+       depends on UNISYSSPAR && UNISYS_VISORUTIL && UNISYS_VISORCHANNEL
+       ---help---
+       If you say Y here, you will enable the Unisys visorchipset driver.
+
diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile
new file mode 100644 (file)
index 0000000..f5e8650
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Makefile for Unisys visorchipset
+#
+
+obj-$(CONFIG_UNISYS_VISORCHIPSET)      += visorchipset.o
+
+visorchipset-y := visorchipset_main.o controlvm_direct.o file.o filexfer.o \
+                       parser.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/uislib
+ccflags-y += -Idrivers/staging/unisys/visorchannel
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -Idrivers/staging/unisys/visorutil
+ccflags-y += -Iinclude/generated
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/visorchipset/controlvm.h b/drivers/staging/unisys/visorchipset/controlvm.h
new file mode 100644 (file)
index 0000000..873fa12
--- /dev/null
@@ -0,0 +1,27 @@
+/* controlvm.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CONTROLVM_H__
+#define __CONTROLVM_H__
+
+#include "timskmod.h"
+
+int         controlvm_init(void);
+void        controlvm_deinit(void);
+HOSTADDRESS controlvm_get_channel_address(void);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/controlvm_direct.c b/drivers/staging/unisys/visorchipset/controlvm_direct.c
new file mode 100644 (file)
index 0000000..7fbc589
--- /dev/null
@@ -0,0 +1,61 @@
+/* controlvm_direct.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This is a controlvm-related code that is dependent upon firmware running
+ * on a virtual partition.
+ */
+
+#include "globals.h"
+#include "uisutils.h"
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_controlvm_direct_c
+
+
+/* We can fill in this code when we learn how to make vmcalls... */
+
+
+
+int controlvm_init(void)
+{
+       return 0;
+}
+
+
+
+void controlvm_deinit(void)
+{
+}
+
+
+
+HOSTADDRESS controlvm_get_channel_address(void)
+{
+       static BOOL warned = FALSE;
+       U64 addr = 0;
+
+       U32 size = 0;
+
+       if (!VMCALL_SUCCESSFUL(Issue_VMCALL_IO_CONTROLVM_ADDR(&addr, &size))) {
+               if (!warned) {
+                       ERRDRV("%s - vmcall to determine controlvm channel addr failed",
+                              __func__);
+                       warned = TRUE;
+               }
+               return 0;
+       }
+       INFODRV("controlvm addr=%Lx", addr);
+       return addr;
+}
diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c
new file mode 100644 (file)
index 0000000..b0d28a2
--- /dev/null
@@ -0,0 +1,223 @@
+/* file.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This contains the implementation that allows a usermode program to
+ * communicate with the visorchipset driver using a device/file interface.
+ */
+
+#include "globals.h"
+#include "visorchannel.h"
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include "uisutils.h"
+
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c
+
+static struct cdev Cdev;
+static VISORCHANNEL **PControlVm_channel;
+static dev_t MajorDev = -1; /**< indicates major num for device */
+static BOOL Registered = FALSE;
+
+static int visorchipset_open(struct inode *inode, struct file *file);
+static int visorchipset_release(struct inode *inode, struct file *file);
+static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma);
+#ifdef HAVE_UNLOCKED_IOCTL
+long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+int visorchipset_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg);
+#endif
+
+static const struct file_operations visorchipset_fops = {
+       .owner = THIS_MODULE,
+       .open = visorchipset_open,
+       .read = NULL,
+       .write = NULL,
+#ifdef HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = visorchipset_ioctl,
+#else
+       .ioctl = visorchipset_ioctl,
+#endif
+       .release = visorchipset_release,
+       .mmap = visorchipset_mmap,
+};
+
+int
+visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel)
+{
+       int rc = -1;
+
+       PControlVm_channel = pControlVm_channel;
+       MajorDev = majorDev;
+       cdev_init(&Cdev, &visorchipset_fops);
+       Cdev.owner = THIS_MODULE;
+       if (MAJOR(MajorDev) == 0) {
+               /* dynamic major device number registration required */
+               if (alloc_chrdev_region(&MajorDev, 0, 1, MYDRVNAME) < 0) {
+                       ERRDRV("Unable to allocate+register char device %s",
+                              MYDRVNAME);
+                       RETINT(-1);
+               }
+               Registered = TRUE;
+               INFODRV("New major number %d registered\n", MAJOR(MajorDev));
+       } else {
+               /* static major device number registration required */
+               if (register_chrdev_region(MajorDev, 1, MYDRVNAME) < 0) {
+                       ERRDRV("Unable to register char device %s", MYDRVNAME);
+                       RETINT(-1);
+               }
+               Registered = TRUE;
+               INFODRV("Static major number %d registered\n", MAJOR(MajorDev));
+       }
+       if (cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1) < 0)
+               FAIL("failed to create char device", -1);
+       INFODRV("Registered char device for %s (major=%d)",
+               MYDRVNAME, MAJOR(MajorDev));
+       RETINT(0);
+Away:
+       return rc;
+}
+
+void
+visorchipset_file_cleanup(void)
+{
+       if (Cdev.ops != NULL)
+               cdev_del(&Cdev);
+       Cdev.ops = NULL;
+       if (Registered) {
+               if (MAJOR(MajorDev) >= 0) {
+                       unregister_chrdev_region(MajorDev, 1);
+                       MajorDev = MKDEV(0, 0);
+               }
+               Registered = FALSE;
+       }
+}
+
+static int
+visorchipset_open(struct inode *inode, struct file *file)
+{
+       unsigned minor_number = iminor(inode);
+       int rc = -ENODEV;
+
+       DEBUGDRV("%s", __func__);
+       if (minor_number != 0)
+               RETINT(-ENODEV);
+       file->private_data = NULL;
+       RETINT(0);
+Away:
+       if (rc < 0)
+               ERRDRV("%s minor=%d failed", __func__, minor_number);
+       return rc;
+}
+
+static int
+visorchipset_release(struct inode *inode, struct file *file)
+{
+       int rc = -1;
+       DEBUGDRV("%s", __func__);
+       RETINT(0);
+Away:
+       return rc;
+}
+
+static int
+visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       ulong physAddr = 0;
+       ulong offset = vma->vm_pgoff << PAGE_SHIFT;
+       GUEST_PHYSICAL_ADDRESS addr = 0;
+
+       /* sv_enable_dfp(); */
+       DEBUGDRV("%s", __func__);
+       if (offset & (PAGE_SIZE - 1)) {
+               ERRDRV("%s virtual address NOT page-aligned!", __func__);
+               return -ENXIO;  /* need aligned offsets */
+       }
+       switch (offset) {
+       case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
+               vma->vm_flags |= VM_IO;
+               if (*PControlVm_channel == NULL) {
+                       ERRDRV("%s no controlvm channel yet", __func__);
+                       return -ENXIO;
+               }
+               visorchannel_read(*PControlVm_channel,
+                                 offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                          gpControlChannel), &addr,
+                                 sizeof(addr));
+               if (addr == 0) {
+                       ERRDRV("%s control channel address is 0", __func__);
+                       return -ENXIO;
+               }
+               physAddr = (ulong) (addr);
+               DEBUGDRV("mapping physical address = 0x%lx", physAddr);
+               if (remap_pfn_range(vma, vma->vm_start,
+                                   physAddr >> PAGE_SHIFT,
+                                   vma->vm_end - vma->vm_start,
+                                   /*pgprot_noncached */
+                                   (vma->vm_page_prot))) {
+                       ERRDRV("%s remap_pfn_range failed", __func__);
+                       return -EAGAIN;
+               }
+               break;
+       default:
+               return -ENOSYS;
+       }
+       DEBUGDRV("%s success!", __func__);
+       return 0;
+}
+
+#ifdef HAVE_UNLOCKED_IOCTL
+long
+visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#else
+int
+visorchipset_ioctl(struct inode *inode, struct file *file,
+                  unsigned int cmd, unsigned long arg)
+#endif
+{
+       int rc = SUCCESS;
+       S64 adjustment;
+       S64 vrtc_offset;
+       DBGINF("entered visorchipset_ioctl, cmd=%d", cmd);
+       switch (cmd) {
+       case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
+               /* get the physical rtc offset */
+               vrtc_offset = Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
+               if (copy_to_user
+                   ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset)))
+                       RETINT(-EFAULT);
+               DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld",
+                      cmd, vrtc_offset);
+               break;
+       case VMCALL_UPDATE_PHYSICAL_TIME:
+               if (copy_from_user
+                   (&adjustment, (void __user *)arg, sizeof(adjustment)))
+                       RETINT(-EFAULT);
+               DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd,
+                      adjustment);
+               rc = Issue_VMCALL_UPDATE_PHYSICAL_TIME(adjustment);
+               break;
+       default:
+               LOGERR("visorchipset_ioctl received invalid command");
+               RETINT(-EFAULT);
+               break;
+       }
+       RETINT(rc);
+Away:
+       DBGINF("exiting %d!", rc);
+       return rc;
+}
diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h
new file mode 100644 (file)
index 0000000..597282a
--- /dev/null
@@ -0,0 +1,26 @@
+/* file.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __FILE_H__
+#define __FILE_H__
+
+#include "globals.h"
+
+int visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel);
+void visorchipset_file_cleanup(void);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/filexfer.c b/drivers/staging/unisys/visorchipset/filexfer.c
new file mode 100644 (file)
index 0000000..431cff8
--- /dev/null
@@ -0,0 +1,506 @@
+/* filexfer.c
+ *
+ * Copyright Â© 2013 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* Code here-in is the "glue" that connects controlvm messages with the
+ * sparfilexfer driver, which is used to transfer file contents as payload
+ * across the controlvm channel.
+ */
+
+#include "globals.h"
+#include "controlvm.h"
+#include "visorchipset.h"
+#include "filexfer.h"
+
+#ifdef ENABLE_SPARFILEXFER /* sparfilexfer kernel module enabled in build */
+#include "sparfilexfer.h"
+
+/* Driver-global memory */
+static LIST_HEAD(Request_list);        /* list of struct any_request *, via
+                                * req_list memb */
+
+/* lock for above pool for allocation of any_request structs, and pool
+* name; note that kmem_cache_create requires that we keep the storage
+* for the pool name for the life of the pool
+ */
+static DEFINE_SPINLOCK(Request_list_lock);
+
+static struct kmem_cache *Request_memory_pool;
+static const char Request_memory_pool_name[] = "filexfer_request_pool";
+size_t Caller_req_context_bytes = 0;   /* passed to filexfer_constructor() */
+
+/* This structure defines a single controlvm GETFILE conversation, which
+ * consists of a single controlvm request message and 1 or more controlvm
+ * response messages.
+ */
+struct getfile_request {
+       CONTROLVM_MESSAGE_HEADER controlvm_header;
+       atomic_t buffers_in_use;
+       GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC get_contiguous_controlvm_payload;
+       CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC controlvm_respond_with_payload;
+};
+
+/* This structure defines a single controlvm PUTFILE conversation, which
+ * consists of a single controlvm request with a filename, and additional
+ * controlvm messages with file data.
+ */
+struct putfile_request {
+       GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata;
+       CONTROLVM_RESPOND_FUNC controlvm_end_putFile;
+};
+
+/* This structure defines a single file transfer operation, which can either
+ * be a GETFILE or PUTFILE.
+ */
+struct any_request {
+       struct list_head req_list;
+       ulong2 file_request_number;
+       ulong2 data_sequence_number;
+       TRANSMITFILE_DUMP_FUNC dump_func;
+       BOOL is_get;
+       union {
+               struct getfile_request get;
+               struct putfile_request put;
+       };
+       /* Size of caller_context_data will be
+        * <Caller_req_context_bytes> bytes.  I aligned this because I
+        * am paranoid about what happens when an arbitrary data
+        * structure with unknown alignment requirements gets copied
+        * here.  I want caller_context_data to be aligned to the
+        * coarsest possible alignment boundary that could be required
+        * for any user data structure.
+        */
+       u8 caller_context_data[1] __aligned(sizeof(ulong2);
+};
+
+/*
+ * Links the any_request into the global list of allocated requests
+ * (<Request_list>).
+ */
+static void
+unit_tracking_create(struct list_head *dev_list_link)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&Request_list_lock, flags);
+       list_add(dev_list_link, &Request_list);
+       spin_unlock_irqrestore(&Request_list_lock, flags);
+}
+
+/* Unlinks a any_request from the global list (<Request_list>).
+ */
+static void
+unit_tracking_destroy(struct list_head *dev_list_link)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&Request_list_lock, flags);
+       list_del(dev_list_link);
+       spin_unlock_irqrestore(&Request_list_lock, flags);
+}
+
+/* Allocate memory for and return a new any_request struct, and
+ * link it to the global list of outstanding requests.
+ */
+static struct any_request *
+alloc_request(char *fn, int ln)
+{
+       struct any_request *req = (struct any_request *)
+           (visorchipset_cache_alloc(Request_memory_pool,
+                                     FALSE,
+                                     fn, ln));
+       if (!req)
+               return NULL;
+       memset(req, 0, sizeof(struct any_request) + Caller_req_context_bytes);
+       unit_tracking_create(&req->req_list);
+       return req;
+}
+
+/* Book-end for alloc_request().
+ */
+static void
+free_request(struct any_request *req, char *fn, int ln)
+{
+       unit_tracking_destroy(&req->req_list);
+       visorchipset_cache_free(Request_memory_pool, req, fn, ln);
+}
+
+/* Constructor for filexfer.o.
+ */
+int
+filexfer_constructor(size_t req_context_bytes)
+{
+       int rc = -1;
+
+       Caller_req_context_bytes = req_context_bytes;
+       Request_memory_pool =
+           kmem_cache_create(Request_memory_pool_name,
+                             sizeof(struct any_request) +
+                             Caller_req_context_bytes,
+                             0, SLAB_HWCACHE_ALIGN, NULL);
+       if (!Request_memory_pool) {
+               LOGERR("failed to alloc Request_memory_pool");
+               rc = -ENOMEM;
+               goto Away;
+       }
+       rc = 0;
+Away:
+       if (rc < 0) {
+               if (Request_memory_pool) {
+                       kmem_cache_destroy(Request_memory_pool);
+                       Request_memory_pool = NULL;
+               }
+       }
+       return rc;
+}
+
+/* Destructor for filexfer.o.
+ */
+void
+filexfer_destructor(void)
+{
+       if (Request_memory_pool) {
+               kmem_cache_destroy(Request_memory_pool);
+               Request_memory_pool = NULL;
+       }
+}
+
+/* This function will obtain an available chunk from the controlvm payload area,
+ * store the size in bytes of the chunk in <actual_size>, and return a pointer
+ * to the chunk.  The function is passed to the sparfilexfer driver, which calls
+ * it whenever payload space is required to copy file data into.
+ */
+static void *
+get_empty_bucket_for_getfile_data(void *context,
+                                 ulong min_size, ulong max_size,
+                                 ulong *actual_size)
+{
+       void *bucket;
+       struct any_request *req = (struct any_request *) context;
+
+       if (!req->is_get) {
+               LOGERR("%s - unexpected call", __func__);
+               return NULL;
+       }
+       bucket = (*req->get.get_contiguous_controlvm_payload)
+           (min_size, max_size, actual_size);
+       if (bucket != NULL) {
+               atomic_inc(&req->get.buffers_in_use);
+               DBGINF("%s - sent %lu-byte buffer", __func__, *actual_size);
+       }
+       return bucket;
+}
+
+/* This function will send a controlvm response with data in the payload
+ * (whose space was obtained with get_empty_bucket_for_getfile_data).  The
+ * function is passed to the sparfilexfer driver, which calls it whenever it
+ * wants to send file data back across the controlvm channel.
+ */
+static int
+send_full_getfile_data_bucket(void *context, void *bucket,
+                             ulong bucket_actual_size, ulong bucket_used_size)
+{
+       struct any_request *req = (struct any_request *) context;
+
+       if (!req->is_get) {
+               LOGERR("%s - unexpected call", __func__);
+               return 0;
+       }
+       DBGINF("sending buffer for %lu/%lu",
+              bucket_used_size, bucket_actual_size);
+       if (!(*req->get.controlvm_respond_with_payload)
+           (&req->get.controlvm_header,
+            req->file_request_number,
+            req->data_sequence_number++,
+            0, bucket, bucket_actual_size, bucket_used_size, TRUE))
+               atomic_dec(&req->get.buffers_in_use);
+       return 0;
+}
+
+/* This function will send a controlvm response indicating the end of a
+ * GETFILE transfer.  The function is passed to the sparfilexfer driver.
+ */
+static void
+send_end_of_getfile_data(void *context, int status)
+{
+       struct any_request *req = (struct any_request *) context;
+       if (!req->is_get) {
+               LOGERR("%s - unexpected call", __func__);
+               return;
+       }
+       LOGINF("status=%d", status);
+       (*req->get.controlvm_respond_with_payload)
+           (&req->get.controlvm_header,
+            req->file_request_number,
+            req->data_sequence_number++, status, NULL, 0, 0, FALSE);
+       free_request(req, __FILE__, __LINE__);
+       module_put(THIS_MODULE);
+}
+
+/* This function supplies data for a PUTFILE transfer.
+ * The function is passed to the sparfilexfer driver.
+ */
+static int
+get_putfile_data(void *context, void *pbuf, size_t bufsize,
+                BOOL buf_is_userspace, size_t *bytes_transferred)
+{
+       struct any_request *req = (struct any_request *) context;
+       if (req->is_get) {
+               LOGERR("%s - unexpected call", __func__);
+               return -1;
+       }
+       return (*req->put.get_controlvm_filedata) (&req->caller_context_data[0],
+                                                  pbuf, bufsize,
+                                                  buf_is_userspace,
+                                                  bytes_transferred);
+}
+
+/* This function is called to indicate the end of a PUTFILE transfer.
+ * The function is passed to the sparfilexfer driver.
+ */
+static void
+end_putfile(void *context, int status)
+{
+       struct any_request *req = (struct any_request *) context;
+       if (req->is_get) {
+               LOGERR("%s - unexpected call", __func__);
+               return;
+       }
+       (*req->put.controlvm_end_putFile) (&req->caller_context_data[0],
+                                          status);
+       free_request(req, __FILE__, __LINE__);
+       module_put(THIS_MODULE);
+}
+
+/* Refer to filexfer.h for description. */
+BOOL
+filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                ulong2 file_request_number,
+                uint uplink_index,
+                uint disk_index,
+                char *file_name,
+                GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
+                get_contiguous_controlvm_payload,
+                CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
+                controlvm_respond_with_payload,
+                TRANSMITFILE_DUMP_FUNC dump_func)
+{
+       BOOL use_count_up = FALSE;
+       BOOL failed = TRUE;
+       struct any_request *req = alloc_request(__FILE__, __LINE__);
+
+       if (!req) {
+               LOGERR("allocation of any_request failed");
+               goto Away;
+       }
+       /* We need to increment this module's use count because we're handing
+        * off pointers to functions within this module to be used by
+        * another module.
+        */
+       __module_get(THIS_MODULE);
+       use_count_up = TRUE;
+       req->is_get = TRUE;
+       req->file_request_number = file_request_number;
+       req->data_sequence_number = 0;
+       req->dump_func = dump_func;
+       req->get.controlvm_header = *msgHdr;
+       atomic_set(&req->get.buffers_in_use, 0);
+       req->get.get_contiguous_controlvm_payload =
+           get_contiguous_controlvm_payload;
+       req->get.controlvm_respond_with_payload =
+           controlvm_respond_with_payload;
+       if (sparfilexfer_local2remote(req,      /* context, passed to
+                                                * callback funcs */
+                                     file_name,
+                                     file_request_number,
+                                     uplink_index,
+                                     disk_index,
+                                     get_empty_bucket_for_getfile_data,
+                                     send_full_getfile_data_bucket,
+                                     send_end_of_getfile_data) < 0) {
+               LOGERR("sparfilexfer_local2remote failed");
+               goto Away;
+       }
+       failed = FALSE;
+Away:
+       if (failed) {
+               if (use_count_up) {
+                       module_put(THIS_MODULE);
+                       use_count_up = FALSE;
+               }
+               if (req) {
+                       free_request(req, __FILE__, __LINE__);
+                       req = NULL;
+               }
+               return FALSE;
+       } else {
+               return TRUE;
+               /* success; send callbacks will be called for responses */
+       }
+}
+
+/* Refer to filexfer.h for description. */
+void *
+filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                ulong2 file_request_number,
+                uint uplink_index,
+                uint disk_index,
+                char *file_name,
+                TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
+                GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
+                CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
+                TRANSMITFILE_DUMP_FUNC dump_func)
+{
+       BOOL use_count_up = FALSE;
+       BOOL failed = TRUE;
+       struct any_request *req = alloc_request(__FILE__, __LINE__);
+       void *caller_ctx = NULL;
+
+       if (!req) {
+               LOGERR("allocation of any_request failed");
+               goto Away;
+       }
+       caller_ctx = (void *) (&(req->caller_context_data[0]));
+       /* We need to increment this module's use count because we're handing
+        * off pointers to functions within this module to be used by
+        * another module.
+        */
+       __module_get(THIS_MODULE);
+       use_count_up = TRUE;
+       req->is_get = FALSE;
+       req->file_request_number = file_request_number;
+       req->data_sequence_number = 0;
+       req->dump_func = dump_func;
+       req->put.get_controlvm_filedata = get_controlvm_filedata;
+       req->put.controlvm_end_putFile = controlvm_end_putFile;
+       (*init_context) (caller_ctx, msgHdr, file_request_number);
+       if (sparfilexfer_remote2local(req,      /* context, passed to
+                                                * callback funcs */
+                                     file_name,
+                                     file_request_number,
+                                     uplink_index,
+                                     disk_index,
+                                     get_putfile_data, end_putfile) < 0) {
+               LOGERR("sparfilexfer_remote2local failed");
+               goto Away;
+       }
+       failed = FALSE;
+Away:
+       if (failed) {
+               if (use_count_up) {
+                       module_put(THIS_MODULE);
+                       use_count_up = FALSE;
+               }
+               if (req) {
+                       free_request(req, __FILE__, __LINE__);
+                       req = NULL;
+               }
+               return NULL;
+       } else {
+               return caller_ctx;
+               /* success; callbacks will be called for responses */
+       }
+}
+
+static void
+dump_get_request(struct seq_file *f, struct getfile_request *getreq)
+{
+       seq_printf(f, "  buffers_in_use=%d\n",
+                  atomic_read(&getreq->buffers_in_use));
+}
+
+static void
+dump_put_request(struct seq_file *f, struct putfile_request *putreq)
+{
+}
+
+static void
+dump_request(struct seq_file *f, struct any_request *req)
+{
+       seq_printf(f, "* %s id=%llu seq=%llu\n",
+                  ((req->is_get) ? "Get" : "Put"),
+                  req->file_request_number, req->data_sequence_number);
+       if (req->is_get)
+               dump_get_request(f, &req->get);
+       else
+               dump_put_request(f, &req->put);
+       if (req->dump_func)
+               (*req->dump_func) (f, &(req->caller_context_data[0]), "  ");
+}
+
+void
+filexfer_dump(struct seq_file *f)
+{
+       ulong flags;
+       struct list_head *entry;
+
+       seq_puts(f, "Outstanding TRANSMIT_FILE requests:\n");
+       spin_lock_irqsave(&Request_list_lock, flags);
+       list_for_each(entry, &Request_list) {
+               struct any_request *req;
+               req = list_entry(entry, struct any_request, req_list);
+               dump_request(f, req);
+       }
+       spin_unlock_irqrestore(&Request_list_lock, flags);
+}
+
+#else                          /* ifdef ENABLE_SPARFILEXFER */
+int
+filexfer_constructor(size_t req_context_bytes)
+{
+       return 0;               /* success */
+}
+
+void
+filexfer_destructor(void)
+{
+}
+
+BOOL
+filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                u64 file_request_number,
+                uint uplink_index,
+                uint disk_index,
+                char *file_name,
+                GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
+                get_contiguous_controlvm_payload,
+                CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
+                controlvm_respond_with_payload,
+                TRANSMITFILE_DUMP_FUNC dump_func)
+{
+       /* since no sparfilexfer module exists to call, we just fail */
+       return FALSE;
+}
+
+void *
+filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                u64 file_request_number,
+                uint uplink_index,
+                uint disk_index,
+                char *file_name,
+                TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
+                GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
+                CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
+                TRANSMITFILE_DUMP_FUNC dump_func)
+{
+       /* since no sparfilexfer module exists to call, we just fail */
+       return NULL;
+}
+
+void
+filexfer_dump(struct seq_file *f)
+{
+}
+
+#endif                         /* ifdef ENABLE_SPARFILEXFER */
diff --git a/drivers/staging/unisys/visorchipset/filexfer.h b/drivers/staging/unisys/visorchipset/filexfer.h
new file mode 100644 (file)
index 0000000..a1bfca6
--- /dev/null
@@ -0,0 +1,147 @@
+/* filexfer.h
+ *
+ * Copyright Â© 2013 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This header file defines the interface that filexfer.c provides to other
+ * code in the visorchipset driver.
+ */
+
+#ifndef __FILEXFER_H__
+#define __FILEXFER_H__
+
+#include "globals.h"
+#include "controlvmchannel.h"
+#include <linux/seq_file.h>
+
+typedef void *(*GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC) (ulong min_size,
+                                                       ulong max_size,
+                                                       ulong *actual_size);
+
+typedef BOOL
+(*CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC) (CONTROLVM_MESSAGE_HEADER *msgHdr,
+                                       u64 fileRequestNumber,
+                                       u64 dataSequenceNumber,
+                                       int response,
+                                       void *bucket, ulong payloadChunkSize,
+                                       ulong payloadUsedBytes, BOOL partial);
+
+typedef void
+(*TRANSMITFILE_INIT_CONTEXT_FUNC)(void *ctx,
+                                 const CONTROLVM_MESSAGE_HEADER *hdr,
+                                 u64 file_request_number);
+typedef void (*TRANSMITFILE_DUMP_FUNC) (struct seq_file *f, void *ctx,
+                                       const char *pfx);
+typedef int (*GET_CONTROLVM_FILEDATA_FUNC) (void *ctx,
+                                           void *buf, size_t bufsize,
+                                           BOOL buf_is_userspace,
+                                           size_t *bytes_transferred);
+typedef void (*CONTROLVM_RESPOND_FUNC) (void *ctx, int response);
+
+/* Call once to initialize filexfer.o.
+ * req_context_bytes number of bytes the caller needs to keep track of each file
+ * transfer conversation.  The <ctx_init_value> passed to filexfer_putFile() is
+ * assumed to be this many bytes in size.  Code within filexfer.o will copy this
+ * into a dynamically-allocated area, and pass back a pointer to that area in
+ * callback functions.
+ */
+int filexfer_constructor(size_t req_context_bytes);
+
+/* Call once to clean up filexfer.o */
+void filexfer_destructor(void);
+
+/* Call this to dump diagnostic info about all outstanding getFiles/putFiles */
+void filexfer_dump(struct seq_file *f);
+
+/* Call to transfer a file from the local filesystem (i.e., from the environment
+ * where this driver is running) across the controlvm channel to a remote
+ * environment.  1 or more controlvm responses will be sent as a result, each
+ * of which whose payload contains file data.  Only the last controlvm message
+ * will have Flags.partialCompletion==0.
+ *
+ *   msgHdr      the controlvm message header of the GETFILE request which
+ *               we just received
+ *   file_request_number  this is all data from the GETFILE request that
+ *   uplink_index         define which file is to be transferred
+ *   disk_index
+ *   file_name
+ *   get_contiguous_controlvm_payload  function to call when space is needed
+ *                                     in the payload area
+ *   controlvm_respond_with_payload    function to call to send each controlvm
+ *                                     response containing file data as the
+ *                                     payload; returns FALSE only if the
+ *                                    payload buffer was freed inline
+ *   dump_func                         function to dump context data in
+ *                                     human-readable format
+ *
+ *  Returns TRUE iff the file transfer request has been successfully initiated,
+ *  or FALSE to indicate failure.
+ */
+BOOL
+filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                u64 file_request_number,
+                uint uplink_index,
+                uint disk_index,
+                char *file_name,
+                GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
+                get_contiguous_controlvm_payload,
+                CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
+                controlvm_respond_with_payload,
+                TRANSMITFILE_DUMP_FUNC dump_func);
+
+/* Call to create a file in the local filesystem (i.e., in the environment
+ * where this driver is running) from data received as payload in
+ * controlvm channel messages from a remote environment.  1 or more controlvm
+ * messages will be received for this transfer, and only the last will have
+ * Flags.partialCompletion==0.
+ *
+ *   msgHdr      the controlvm message header of the PUTFILE request which
+ *               we just received
+ *   file_request_number  this is all data from the PUTFILE request that
+ *   uplink_index         define which file is to be created in the local
+ *   disk_index           filesystem
+ *   file_name
+ *   init_context         function to call to initialize the
+ *                        <req_context_bytes>-sized storage area returned by
+ *                        this func; note that it would NOT be sufficient to
+ *                        allow the caller to initialize this upon return, as
+ *                        the the other user-supplied callbacks might have
+ *                        already been called by then
+ *   get_controlvm_filedata   function to call to obtain more data for the file
+ *                            being written; refer to get_controlvm_filedata()
+ *                            in visorchipset_main.c for a complete description
+ *                            of parameters
+ *   controlvm_end_putFile    function to call to indicate that creation of the
+ *                            local file has completed;  set <response> to a
+ *                            negative value to indicate an error
+ *   dump_func                function to dump context data in human-readable
+ *                            format
+ *
+ *  Returns a pointer to a dynamically-allocated storage area of size
+ *  <req_context_bytes> which the caller can use, or NULL for error.  The
+ *  caller should NEVER free the returned pointer, but should expect to receive
+ *  it as the <ctx> argument when callback functions are called.
+ */
+void *filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                      u64 file_request_number,
+                      uint uplink_index,
+                      uint disk_index,
+                      char *file_name,
+                      TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
+                      GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
+                      CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
+                      TRANSMITFILE_DUMP_FUNC dump_func);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h
new file mode 100644 (file)
index 0000000..a0e6d4f
--- /dev/null
@@ -0,0 +1,45 @@
+/* globals.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+
+#ifndef __VISORCHIPSET_GLOBALS_H__
+#define __VISORCHIPSET_GLOBALS_H__
+
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "timskmod.h"
+#include "visorchipset.h"
+#include "visorchipset_umode.h"
+#include "version.h"
+
+#define MYDRVNAME "visorchipset"
+
+
+/* module parameters */
+
+extern int visorchipset_testvnic;
+extern int visorchipset_testvnicclient;
+extern int visorchipset_testmsg;
+extern int visorchipset_major;
+extern int visorchipset_serverregwait;
+extern int visorchipset_clientregwait;
+extern int visorchipset_testteardown;
+extern int visorchipset_disable_controlvm;
+extern int visorchipset_crash_kernel;
+extern int visorchipset_holdchipsetready;
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c
new file mode 100644 (file)
index 0000000..09b3a84
--- /dev/null
@@ -0,0 +1,466 @@
+/* parser.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "parser.h"
+#include "memregion.h"
+#include "controlvmchannel.h"
+#include <linux/ctype.h>
+#include <linux/mm.h>
+
+#define MYDRVNAME "visorchipset_parser"
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_parser_c
+
+/* We will refuse to allocate more than this many bytes to copy data from
+ * incoming payloads.  This serves as a throttling mechanism.
+ */
+#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
+static ulong Controlvm_Payload_Bytes_Buffered;
+
+struct PARSER_CONTEXT_Tag {
+       ulong allocbytes;
+       ulong param_bytes;
+       u8 *curr;
+       ulong bytes_remaining;
+       BOOL byte_stream;
+       char data[0];
+};
+
+static PARSER_CONTEXT *
+parser_init_guts(U64 addr, U32 bytes, BOOL isLocal,
+                BOOL hasStandardPayloadHeader, BOOL *tryAgain)
+{
+       int allocbytes = sizeof(PARSER_CONTEXT) + bytes;
+       PARSER_CONTEXT *rc = NULL;
+       PARSER_CONTEXT *ctx = NULL;
+       MEMREGION *rgn = NULL;
+       ULTRA_CONTROLVM_PARAMETERS_HEADER *phdr = NULL;
+
+       if (tryAgain)
+               *tryAgain = FALSE;
+       if (!hasStandardPayloadHeader)
+               /* alloc and 0 extra byte to ensure payload is
+                * '\0'-terminated
+                */
+               allocbytes++;
+       if ((Controlvm_Payload_Bytes_Buffered + bytes)
+           > MAX_CONTROLVM_PAYLOAD_BYTES) {
+               ERRDRV("%s (%s:%d) - prevented allocation of %d bytes to prevent exceeding throttling max (%d)",
+                      __func__, __FILE__, __LINE__, allocbytes,
+                      MAX_CONTROLVM_PAYLOAD_BYTES);
+               if (tryAgain)
+                       *tryAgain = TRUE;
+               RETPTR(NULL);
+       }
+       ctx = kmalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY);
+       if (ctx == NULL) {
+               ERRDRV("%s (%s:%d) - failed to allocate %d bytes",
+                      __func__, __FILE__, __LINE__, allocbytes);
+               if (tryAgain)
+                       *tryAgain = TRUE;
+               RETPTR(NULL);
+       }
+       memset(ctx, 0, allocbytes);
+       ctx->allocbytes = allocbytes;
+       ctx->param_bytes = bytes;
+       ctx->curr = NULL;
+       ctx->bytes_remaining = 0;
+       ctx->byte_stream = FALSE;
+       if (isLocal) {
+               void *p;
+               if (addr > virt_to_phys(high_memory - 1)) {
+                       ERRDRV("%s - bad local address (0x%-16.16Lx for %lu)",
+                              __func__,
+                              (unsigned long long) addr, (ulong) bytes);
+                       RETPTR(NULL);
+               }
+               p = __va((ulong) (addr));
+               memcpy(ctx->data, p, bytes);
+       } else {
+               rgn = memregion_create(addr, bytes);
+               if (!rgn)
+                       RETPTR(NULL);
+               if (memregion_read(rgn, 0, ctx->data, bytes) < 0)
+                       RETPTR(NULL);
+       }
+       if (!hasStandardPayloadHeader) {
+               ctx->byte_stream = TRUE;
+               RETPTR(ctx);
+       }
+       phdr = (ULTRA_CONTROLVM_PARAMETERS_HEADER *) (ctx->data);
+       if (phdr->TotalLength != bytes) {
+               ERRDRV("%s - bad total length %lu (should be %lu)",
+                      __func__,
+                      (ulong) (phdr->TotalLength), (ulong) (bytes));
+               RETPTR(NULL);
+       }
+       if (phdr->TotalLength < phdr->HeaderLength) {
+               ERRDRV("%s - total length < header length (%lu < %lu)",
+                      __func__,
+                      (ulong) (phdr->TotalLength),
+                      (ulong) (phdr->HeaderLength));
+               RETPTR(NULL);
+       }
+       if (phdr->HeaderLength < sizeof(ULTRA_CONTROLVM_PARAMETERS_HEADER)) {
+               ERRDRV("%s - header is too small (%lu < %lu)",
+                      __func__,
+                      (ulong) (phdr->HeaderLength),
+                      (ulong) (sizeof(ULTRA_CONTROLVM_PARAMETERS_HEADER)));
+               RETPTR(NULL);
+       }
+
+       RETPTR(ctx);
+
+Away:
+       if (rgn) {
+               memregion_destroy(rgn);
+               rgn = NULL;
+       }
+       if (rc)
+               Controlvm_Payload_Bytes_Buffered += ctx->param_bytes;
+       else {
+               if (ctx) {
+                       parser_done(ctx);
+                       ctx = NULL;
+               }
+       }
+       return rc;
+}
+
+PARSER_CONTEXT *
+parser_init(U64 addr, U32 bytes, BOOL isLocal, BOOL *tryAgain)
+{
+       return parser_init_guts(addr, bytes, isLocal, TRUE, tryAgain);
+}
+
+/* Call this instead of parser_init() if the payload area consists of just
+ * a sequence of bytes, rather than a ULTRA_CONTROLVM_PARAMETERS_HEADER
+ * structures.  Afterwards, you can call parser_simpleString_get() or
+ * parser_byteStream_get() to obtain the data.
+ */
+PARSER_CONTEXT *
+parser_init_byteStream(U64 addr, U32 bytes, BOOL isLocal, BOOL *tryAgain)
+{
+       return parser_init_guts(addr, bytes, isLocal, FALSE, tryAgain);
+}
+
+/* Obtain '\0'-terminated copy of string in payload area.
+ */
+char *
+parser_simpleString_get(PARSER_CONTEXT *ctx)
+{
+       if (!ctx->byte_stream)
+               return NULL;
+       return ctx->data;       /* note this IS '\0'-terminated, because of
+                                * the num of bytes we alloc+clear in
+                                * parser_init_byteStream() */
+}
+
+/* Obtain a copy of the buffer in the payload area.
+ */
+void *
+parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes)
+{
+       if (!ctx->byte_stream)
+               return NULL;
+       if (nbytes)
+               *nbytes = ctx->param_bytes;
+       return (void *) ctx->data;
+}
+
+GUID
+parser_id_get(PARSER_CONTEXT *ctx)
+{
+       ULTRA_CONTROLVM_PARAMETERS_HEADER *phdr = NULL;
+
+       if (ctx == NULL) {
+               ERRDRV("%s (%s:%d) - no context",
+                      __func__, __FILE__, __LINE__);
+               return Guid0;
+       }
+       phdr = (ULTRA_CONTROLVM_PARAMETERS_HEADER *) (ctx->data);
+       return phdr->Id;
+}
+
+void
+parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string)
+{
+       ULTRA_CONTROLVM_PARAMETERS_HEADER *phdr = NULL;
+
+       if (ctx == NULL) {
+               ERRDRV("%s (%s:%d) - no context",
+                      __func__, __FILE__, __LINE__);
+               RETVOID;
+       }
+       phdr = (ULTRA_CONTROLVM_PARAMETERS_HEADER *) (ctx->data);
+       switch (which_string) {
+       case PARSERSTRING_INITIATOR:
+               ctx->curr = ctx->data + phdr->InitiatorOffset;
+               ctx->bytes_remaining = phdr->InitiatorLength;
+               break;
+       case PARSERSTRING_TARGET:
+               ctx->curr = ctx->data + phdr->TargetOffset;
+               ctx->bytes_remaining = phdr->TargetLength;
+               break;
+       case PARSERSTRING_CONNECTION:
+               ctx->curr = ctx->data + phdr->ConnectionOffset;
+               ctx->bytes_remaining = phdr->ConnectionLength;
+               break;
+       case PARSERSTRING_NAME:
+               ctx->curr = ctx->data + phdr->NameOffset;
+               ctx->bytes_remaining = phdr->NameLength;
+               break;
+       default:
+               ERRDRV("%s - bad which_string %d", __func__, which_string);
+               RETVOID;
+               break;
+       }
+       RETVOID;
+
+Away:
+       return;
+}
+
+void
+parser_done(PARSER_CONTEXT *ctx)
+{
+       if (!ctx)
+               return;
+       Controlvm_Payload_Bytes_Buffered -= ctx->param_bytes;
+       kfree(ctx);
+}
+
+/** Return length of string not counting trailing spaces. */
+static int
+string_length_no_trail(char *s, int len)
+{
+       int i = len - 1;
+       while (i >= 0) {
+               if (!isspace(s[i]))
+                       return i + 1;
+               i--;
+       }
+       return 0;
+}
+
+/** Grab the next name and value out of the parameter buffer.
+ *  The entire parameter buffer looks like this:
+ *      <name>=<value>\0
+ *      <name>=<value>\0
+ *      ...
+ *      \0
+ *  If successful, the next <name> value is returned within the supplied
+ *  <nam> buffer (the value is always upper-cased), and the corresponding
+ *  <value> is returned within a kmalloc()ed buffer, whose pointer is
+ *  provided as the return value of this function.
+ *  (The total number of bytes allocated is strlen(<value>)+1.)
+ *
+ *  NULL is returned to indicate failure, which can occur for several reasons:
+ *  - all <name>=<value> pairs have already been processed
+ *  - bad parameter
+ *  - parameter buffer ends prematurely (couldn't find an '=' or '\0' within
+ *    the confines of the parameter buffer)
+ *  - the <nam> buffer is not large enough to hold the <name> of the next
+ *    parameter
+ */
+void *
+parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
+{
+       u8 *pscan, *pnam = nam;
+       ulong nscan;
+       int value_length = -1, orig_value_length = -1;
+       void *value = NULL;
+       int i;
+       int closing_quote = 0;
+
+       if (!ctx)
+               return NULL;
+       pscan = ctx->curr;
+       nscan = ctx->bytes_remaining;
+       if (nscan == 0)
+               return NULL;
+       if (*pscan == '\0')
+               /*  This is the normal return point after you have processed
+                *  all of the <name>=<value> pairs in a syntactically-valid
+                *  parameter buffer.
+                */
+               return NULL;
+
+       /* skip whitespace */
+       while (isspace(*pscan)) {
+               pscan++;
+               nscan--;
+               if (nscan == 0)
+                       return NULL;
+       }
+
+       while (*pscan != ':') {
+               if (namesize <= 0) {
+                       ERRDRV("%s - name too big", __func__);
+                       return NULL;
+               }
+               *pnam = toupper(*pscan);
+               pnam++;
+               namesize--;
+               pscan++;
+               nscan--;
+               if (nscan == 0) {
+                       ERRDRV("%s - unexpected end of input parsing name",
+                              __func__);
+                       return NULL;
+               }
+       }
+       if (namesize <= 0) {
+               ERRDRV("%s - name too big", __func__);
+               return NULL;
+       }
+       *pnam = '\0';
+       nam[string_length_no_trail(nam, strlen(nam))] = '\0';
+
+       /* point to char immediately after ":" in "<name>:<value>" */
+       pscan++;
+       nscan--;
+       /* skip whitespace */
+       while (isspace(*pscan)) {
+               pscan++;
+               nscan--;
+               if (nscan == 0) {
+                       ERRDRV("%s - unexpected end of input looking for value",
+                              __func__);
+                       return NULL;
+               }
+       }
+       if (nscan == 0) {
+               ERRDRV("%s - unexpected end of input looking for value",
+                      __func__);
+               return NULL;
+       }
+       if (*pscan == '\'' || *pscan == '"') {
+               closing_quote = *pscan;
+               pscan++;
+               nscan--;
+               if (nscan == 0) {
+                       ERRDRV("%s - unexpected end of input after %c",
+                              __func__, closing_quote);
+                       return NULL;
+               }
+       }
+
+       /* look for a separator character, terminator character, or
+        * end of data
+        */
+       for (i = 0, value_length = -1; i < nscan; i++) {
+               if (closing_quote) {
+                       if (pscan[i] == '\0') {
+                               ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
+                               return NULL;
+                       }
+                       if (pscan[i] == closing_quote) {
+                               value_length = i;
+                               break;
+                       }
+               } else
+                   if (pscan[i] == ',' || pscan[i] == ';'
+                       || pscan[i] == '\0') {
+                       value_length = i;
+                       break;
+               }
+       }
+       if (value_length < 0) {
+               if (closing_quote) {
+                       ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
+                       return NULL;
+               }
+               value_length = nscan;
+       }
+       orig_value_length = value_length;
+       if (closing_quote == 0)
+               value_length = string_length_no_trail(pscan, orig_value_length);
+       value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
+       if (value == NULL)
+               return NULL;
+       memcpy(value, pscan, value_length);
+       ((u8 *) (value))[value_length] = '\0';
+
+       pscan += orig_value_length;
+       nscan -= orig_value_length;
+
+       /* skip past separator or closing quote */
+       if (nscan > 0) {
+               if (*pscan != '\0') {
+                       pscan++;
+                       nscan--;
+               }
+       }
+
+       if (closing_quote && (nscan > 0)) {
+               /* we still need to skip around the real separator if present */
+               /* first, skip whitespace */
+               while (isspace(*pscan)) {
+                       pscan++;
+                       nscan--;
+                       if (nscan == 0)
+                               break;
+               }
+               if (nscan > 0) {
+                       if (*pscan == ',' || *pscan == ';') {
+                               pscan++;
+                               nscan--;
+                       } else if (*pscan != '\0') {
+                               ERRDRV("%s - missing separator after quoted string", __func__);
+                               kfree(value);
+                               value = NULL;
+                               return NULL;
+                       }
+               }
+       }
+       ctx->curr = pscan;
+       ctx->bytes_remaining = nscan;
+       return value;
+}
+
+void *
+parser_string_get(PARSER_CONTEXT *ctx)
+{
+       u8 *pscan;
+       ulong nscan;
+       int value_length = -1;
+       void *value = NULL;
+       int i;
+
+       if (!ctx)
+               return NULL;
+       pscan = ctx->curr;
+       nscan = ctx->bytes_remaining;
+       if (nscan == 0)
+               return NULL;
+       if (!pscan)
+               return NULL;
+       for (i = 0, value_length = -1; i < nscan; i++)
+               if (pscan[i] == '\0') {
+                       value_length = i;
+                       break;
+               }
+       if (value_length < 0)   /* '\0' was not included in the length */
+               value_length = nscan;
+       value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
+       if (value == NULL)
+               return NULL;
+       if (value_length > 0)
+               memcpy(value, pscan, value_length);
+       ((u8 *) (value))[value_length] = '\0';
+       return value;
+}
diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h
new file mode 100644 (file)
index 0000000..a0cc50a
--- /dev/null
@@ -0,0 +1,45 @@
+/* parser.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __PARSER_H__
+#define __PARSER_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "channel.h"
+
+typedef enum {
+       PARSERSTRING_INITIATOR,
+       PARSERSTRING_TARGET,
+       PARSERSTRING_CONNECTION,
+       PARSERSTRING_NAME,
+} PARSER_WHICH_STRING;
+
+typedef struct PARSER_CONTEXT_Tag PARSER_CONTEXT;
+
+PARSER_CONTEXT *parser_init(U64 addr, U32 bytes, BOOL isLocal, BOOL *tryAgain);
+PARSER_CONTEXT *parser_init_byteStream(U64 addr, U32 bytes, BOOL isLocal,
+                                      BOOL *tryAgain);
+void parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string);
+void *parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize);
+void *parser_string_get(PARSER_CONTEXT *ctx);
+GUID parser_id_get(PARSER_CONTEXT *ctx);
+char *parser_simpleString_get(PARSER_CONTEXT *ctx);
+void *parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes);
+void parser_done(PARSER_CONTEXT *ctx);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/testing.h b/drivers/staging/unisys/visorchipset/testing.h
new file mode 100644 (file)
index 0000000..a44f555
--- /dev/null
@@ -0,0 +1,41 @@
+/* testing.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHIPSET_TESTING_H__
+#define __VISORCHIPSET_TESTING_H__
+
+#define VISORCHIPSET_TEST_PROC
+#include "globals.h"
+#include "controlvmchannel.h"
+
+void test_produce_test_message(CONTROLVM_MESSAGE *msg, int isLocalTestAddr);
+BOOL test_consume_test_message(CONTROLVM_MESSAGE *msg);
+void test_manufacture_vnic_client_add(void *p);
+void test_manufacture_vnic_client_add_phys(HOSTADDRESS addr);
+void test_manufacture_preamble_messages(void);
+void test_manufacture_device_attach(ulong busNo, ulong devNo);
+void test_manufacture_device_add(ulong busNo, ulong devNo, GUID dataTypeGuid,
+                                void *pChannel);
+void test_manufacture_add_bus(ulong busNo, ulong maxDevices,
+                             GUID id, u8 *name, BOOL isServer);
+void test_manufacture_device_destroy(ulong busNo, ulong devNo);
+void test_manufacture_bus_destroy(ulong busNo);
+void test_manufacture_detach_externalPort(ulong switchNo, ulong externalPortNo);
+void test_manufacture_detach_internalPort(ulong switchNo, ulong internalPortNo);
+void test_cleanup(void);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h
new file mode 100644 (file)
index 0000000..8e62a89
--- /dev/null
@@ -0,0 +1,307 @@
+/* visorchipset.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHIPSET_H__
+#define __VISORCHIPSET_H__
+
+#include "timskmod.h"
+#include "channel.h"
+#include "controlvmchannel.h"
+#include "parser.h"
+#include "procobjecttree.h"
+#include "vbusdeviceinfo.h"
+#include "vbushelper.h"
+
+/** Describes the state from the perspective of which controlvm messages have
+ *  been received for a bus or device.
+ */
+typedef struct {
+       U32 created:1;
+       U32 attached:1;
+       U32 configured:1;
+       U32 running:1;
+       /* Add new fields above. */
+       /* Remaining bits in this 32-bit word are unused. */
+} VISORCHIPSET_STATE;
+
+typedef enum {
+       /** address is guest physical, but outside of the physical memory
+        *  region that is controlled by the running OS (this is the normal
+        *  address type for Supervisor channels)
+        */
+       ADDRTYPE_localPhysical,
+
+       /** address is guest physical, and withIN the confines of the
+        *  physical memory controlled by the running OS.
+        */
+       ADDRTYPE_localTest,
+} VISORCHIPSET_ADDRESSTYPE;
+
+typedef enum {
+       CRASH_dev,
+       CRASH_bus,
+} CRASH_OBJ_TYPE;
+
+/** Attributes for a particular Supervisor channel.
+ */
+typedef struct {
+       VISORCHIPSET_ADDRESSTYPE addrType;
+       HOSTADDRESS channelAddr;
+       struct InterruptInfo intr;
+       U64 nChannelBytes;
+       GUID channelTypeGuid;
+       GUID channelInstGuid;
+
+} VISORCHIPSET_CHANNEL_INFO;
+
+/** Attributes for a particular Supervisor device.
+ *  Any visorchipset client can query these attributes using
+ *  visorchipset_get_client_device_info() or
+ *  visorchipset_get_server_device_info().
+ */
+typedef struct {
+       struct list_head entry;
+       U32 busNo;
+       U32 devNo;
+       GUID devInstGuid;
+       VISORCHIPSET_STATE state;
+       VISORCHIPSET_CHANNEL_INFO chanInfo;
+       U32 Reserved1;          /* CONTROLVM_ID */
+       U64 Reserved2;
+       U32 switchNo;           /* when devState.attached==1 */
+       U32 internalPortNo;     /* when devState.attached==1 */
+       CONTROLVM_MESSAGE_HEADER pendingMsgHdr; /* CONTROLVM_MESSAGE */
+       /** For private use by the bus driver */
+       void *bus_driver_context;
+
+} VISORCHIPSET_DEVICE_INFO;
+
+static inline VISORCHIPSET_DEVICE_INFO *
+finddevice(struct list_head *list, U32 busNo, U32 devNo)
+{
+       VISORCHIPSET_DEVICE_INFO *p;
+
+       list_for_each_entry(p, list, entry) {
+               if (p->busNo == busNo && p->devNo == devNo)
+                       return p;
+       }
+       return NULL;
+}
+
+static inline void delbusdevices(struct list_head *list, U32 busNo)
+{
+       VISORCHIPSET_DEVICE_INFO *p;
+
+       list_for_each_entry(p, list, entry) {
+               if (p->busNo == busNo) {
+                       list_del(&p->entry);
+                       kfree(p);
+               }
+       }
+}
+
+/** Attributes for a particular Supervisor bus.
+ *  (For a service partition acting as the server for buses/devices, there
+ *  is a 1-to-1 relationship between busses and guest partitions.)
+ *  Any visorchipset client can query these attributes using
+ *  visorchipset_get_client_bus_info() or visorchipset_get_bus_info().
+ */
+typedef struct {
+       struct list_head entry;
+       U32 busNo;
+       VISORCHIPSET_STATE state;
+       VISORCHIPSET_CHANNEL_INFO chanInfo;
+       GUID partitionGuid;
+       U64 partitionHandle;
+       U8 *name;               /* UTF8 */
+       U8 *description;        /* UTF8 */
+       U64 Reserved1;
+       U32 Reserved2;
+       MYPROCOBJECT *procObject;
+       struct {
+               U32 server:1;
+               /* Add new fields above. */
+               /* Remaining bits in this 32-bit word are unused. */
+       } flags;
+       CONTROLVM_MESSAGE_HEADER pendingMsgHdr; /* CONTROLVM MsgHdr */
+       /** For private use by the bus driver */
+       void *bus_driver_context;
+       U64 devNo;
+
+} VISORCHIPSET_BUS_INFO;
+
+static inline VISORCHIPSET_BUS_INFO *
+findbus(struct list_head *list, U32 busNo)
+{
+       VISORCHIPSET_BUS_INFO *p;
+
+       list_for_each_entry(p, list, entry) {
+               if (p->busNo == busNo)
+                       return p;
+       }
+       return NULL;
+}
+
+/** Attributes for a particular Supervisor switch.
+ */
+typedef struct {
+       U32 switchNo;
+       VISORCHIPSET_STATE state;
+       GUID switchTypeGuid;
+       U8 *authService1;
+       U8 *authService2;
+       U8 *authService3;
+       U8 *securityContext;
+       U64 Reserved;
+       U32 Reserved2;          /* CONTROLVM_ID */
+       struct device dev;
+       BOOL dev_exists;
+       CONTROLVM_MESSAGE_HEADER pendingMsgHdr;
+
+} VISORCHIPSET_SWITCH_INFO;
+
+/** Attributes for a particular Supervisor external port, which is connected
+ *  to a specific switch.
+ */
+typedef struct {
+       U32 switchNo;
+       U32 externalPortNo;
+       VISORCHIPSET_STATE state;
+       GUID networkZoneGuid;
+       int pdPort;
+       U8 *ip;
+       U8 *ipNetmask;
+       U8 *ipBroadcast;
+       U8 *ipNetwork;
+       U8 *ipGateway;
+       U8 *ipDNS;
+       U64 Reserved1;
+       U32 Reserved2;          /* CONTROLVM_ID */
+       struct device dev;
+       BOOL dev_exists;
+       CONTROLVM_MESSAGE_HEADER pendingMsgHdr;
+
+} VISORCHIPSET_EXTERNALPORT_INFO;
+
+/** Attributes for a particular Supervisor internal port, which is how a
+ *  device connects to a particular switch.
+ */
+typedef struct {
+       U32 switchNo;
+       U32 internalPortNo;
+       VISORCHIPSET_STATE state;
+       U32 busNo;              /* valid only when state.attached == 1 */
+       U32 devNo;              /* valid only when state.attached == 1 */
+       U64 Reserved1;
+       U32 Reserved2;          /* CONTROLVM_ID */
+       CONTROLVM_MESSAGE_HEADER pendingMsgHdr;
+       MYPROCOBJECT *procObject;
+
+} VISORCHIPSET_INTERNALPORT_INFO;
+
+/*  These functions will be called from within visorchipset when certain
+ *  events happen.  (The implementation of these functions is outside of
+ *  visorchipset.)
+ */
+typedef struct {
+       void (*bus_create)(ulong busNo);
+       void (*bus_destroy)(ulong busNo);
+       void (*device_create)(ulong busNo, ulong devNo);
+       void (*device_destroy)(ulong busNo, ulong devNo);
+       void (*device_pause)(ulong busNo, ulong devNo);
+       void (*device_resume)(ulong busNo, ulong devNo);
+       int (*get_channel_info)(GUID typeGuid, ulong *minSize,
+                                ulong *maxSize);
+} VISORCHIPSET_BUSDEV_NOTIFIERS;
+
+/*  These functions live inside visorchipset, and will be called to indicate
+ *  responses to specific events (by code outside of visorchipset).
+ *  For now, the value for each response is simply either:
+ *       0 = it worked
+ *      -1 = it failed
+ */
+typedef struct {
+       void (*bus_create)(ulong busNo, int response);
+       void (*bus_destroy)(ulong busNo, int response);
+       void (*device_create)(ulong busNo, ulong devNo, int response);
+       void (*device_destroy)(ulong busNo, ulong devNo, int response);
+       void (*device_pause)(ulong busNo, ulong devNo, int response);
+       void (*device_resume)(ulong busNo, ulong devNo, int response);
+} VISORCHIPSET_BUSDEV_RESPONDERS;
+
+/** Register functions (in the bus driver) to get called by visorchipset
+ *  whenever a bus or device appears for which this service partition is
+ *  to be the server for.  visorchipset will fill in <responders>, to
+ *  indicate functions the bus driver should call to indicate message
+ *  responses.
+ */
+void
+visorchipset_register_busdev_client(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+                                   VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+                                   ULTRA_VBUS_DEVICEINFO *driverInfo);
+
+/** Register functions (in the bus driver) to get called by visorchipset
+ *  whenever a bus or device appears for which this service partition is
+ *  to be the client for.  visorchipset will fill in <responders>, to
+ *  indicate functions the bus driver should call to indicate message
+ *  responses.
+ */
+void
+visorchipset_register_busdev_server(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+                                   VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+                                   ULTRA_VBUS_DEVICEINFO *driverInfo);
+
+typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (CONTROLVM_MESSAGE *msg,
+                                              int status);
+
+void device_pause_response(ulong busNo, ulong devNo, int response);
+
+BOOL visorchipset_get_bus_info(ulong busNo, VISORCHIPSET_BUS_INFO *busInfo);
+BOOL visorchipset_get_device_info(ulong busNo, ulong devNo,
+                                 VISORCHIPSET_DEVICE_INFO *devInfo);
+BOOL visorchipset_get_switch_info(ulong switchNo,
+                                 VISORCHIPSET_SWITCH_INFO *switchInfo);
+BOOL visorchipset_get_externalport_info(ulong switchNo, ulong externalPortNo,
+                                       VISORCHIPSET_EXTERNALPORT_INFO
+                                       *externalPortInfo);
+BOOL visorchipset_set_bus_context(ulong busNo, void *context);
+BOOL visorchipset_set_device_context(ulong busNo, ulong devNo, void *context);
+int visorchipset_chipset_ready(void);
+int visorchipset_chipset_selftest(void);
+int visorchipset_chipset_notready(void);
+void visorchipset_controlvm_respond_reportEvent(CONTROLVM_MESSAGE *msg,
+                                               void *payload);
+void visorchipset_save_message(CONTROLVM_MESSAGE *msg, CRASH_OBJ_TYPE type);
+void *visorchipset_cache_alloc(struct kmem_cache *pool,
+                              BOOL ok_to_block, char *fn, int ln);
+void visorchipset_cache_free(struct kmem_cache *pool, void *p,
+                            char *fn, int ln);
+
+#if defined(TRANSMITFILE_DEBUG) || defined(DEBUG)
+#define DBG_GETFILE_PAYLOAD(msg, controlvm_header)      \
+       LOGINF(msg,                                     \
+              (ulong)controlvm_header.PayloadVmOffset, \
+              (ulong)controlvm_header.PayloadMaxBytes)
+#define DBG_GETFILE(fmt, ...)  LOGINF(fmt, ##__VA_ARGS__)
+#define DBG_PUTFILE(fmt, ...)  LOGINF(fmt, ##__VA_ARGS__)
+#else
+#define DBG_GETFILE_PAYLOAD(msg, controlvm_header)
+#define DBG_GETFILE(fmt, ...)
+#define DBG_PUTFILE(fmt, ...)
+#endif
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c
new file mode 100644 (file)
index 0000000..e0ec3a4
--- /dev/null
@@ -0,0 +1,2912 @@
+/* visorchipset_main.c
+ *
+ * Copyright ï¿½ 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "globals.h"
+#include "controlvm.h"
+#include "visorchipset.h"
+#include "procobjecttree.h"
+#include "visorchannel.h"
+#include "periodic_work.h"
+#include "testing.h"
+#include "file.h"
+#include "parser.h"
+#include "uniklog.h"
+#include "uisutils.h"
+#include "guidutils.h"
+#include "controlvmcompletionstatus.h"
+#include "guestlinuxdebug.h"
+#include "filexfer.h"
+
+#include <linux/nls.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
+#define TEST_VNIC_PHYSITF "eth0"       /* physical network itf for
+                                        * vnic loopback test */
+#define TEST_VNIC_SWITCHNO 1
+#define TEST_VNIC_BUSNO 9
+
+#define MAX_NAME_SIZE 128
+#define MAX_IP_SIZE   50
+#define MAXOUTSTANDINGCHANNELCOMMAND 256
+#define POLLJIFFIES_CONTROLVMCHANNEL_FAST   1
+#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
+
+/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS,
+* we switch to slow polling mode.  As soon as we get a controlvm
+* message, we switch back to fast polling mode.
+*/
+#define MIN_IDLE_SECONDS 10
+ulong Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+ulong Most_recent_message_jiffies;     /* when we got our last
+                                        * controlvm message */
+static inline char *
+NONULLSTR(char *s)
+{
+       if (s)
+               return s;
+       else
+               return "";
+}
+
+static int serverregistered;
+static int clientregistered;
+
+#define MAX_CHIPSET_EVENTS 2
+static U8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 };
+
+static struct delayed_work Periodic_controlvm_work;
+static struct workqueue_struct *Periodic_controlvm_workqueue;
+DEFINE_SEMAPHORE(NotifierLock);
+
+typedef struct {
+       CONTROLVM_MESSAGE message;
+       unsigned int crc;
+} MESSAGE_ENVELOPE;
+
+static CONTROLVM_MESSAGE_HEADER g_DiagMsgHdr;
+static CONTROLVM_MESSAGE_HEADER g_ChipSetMsgHdr;
+static CONTROLVM_MESSAGE_HEADER g_DelDumpMsgHdr;
+static const GUID UltraDiagPoolChannelProtocolGuid =
+       ULTRA_DIAG_POOL_CHANNEL_PROTOCOL_GUID;
+/* 0xffffff is an invalid Bus/Device number */
+static ulong g_diagpoolBusNo = 0xffffff;
+static ulong g_diagpoolDevNo = 0xffffff;
+static CONTROLVM_MESSAGE_PACKET g_DeviceChangeStatePacket;
+
+/* Only VNIC and VHBA channels are sent to visorclientbus (aka
+ * "visorhackbus")
+ */
+#define FOR_VISORHACKBUS(channel_type_guid) \
+       ((memcmp(&channel_type_guid, &UltraVnicChannelProtocolGuid, \
+                sizeof(GUID)) == 0) ||                             \
+        (memcmp(&channel_type_guid, &UltraVhbaChannelProtocolGuid, \
+                sizeof(GUID)) == 0))
+#define FOR_VISORBUS(channel_type_guid) (!(FOR_VISORHACKBUS(channel_type_guid)))
+
+#define is_diagpool_channel(channel_type_guid) \
+        (memcmp(&channel_type_guid, \
+                &UltraDiagPoolChannelProtocolGuid, sizeof(GUID)) == 0)
+
+typedef enum {
+       PARTPROP_invalid,
+       PARTPROP_name,
+       PARTPROP_description,
+       PARTPROP_handle,
+       PARTPROP_busNumber,
+       /* add new properties above, but don't forget to change
+        * InitPartitionProperties() and show_partition_property() also...
+        */
+       PARTPROP_last
+} PARTITION_property;
+static const char *PartitionTypeNames[] = { "partition", NULL };
+
+static char *PartitionPropertyNames[PARTPROP_last + 1];
+static void
+InitPartitionProperties(void)
+{
+       char **p = PartitionPropertyNames;
+       p[PARTPROP_invalid] = "";
+       p[PARTPROP_name] = "name";
+       p[PARTPROP_description] = "description";
+       p[PARTPROP_handle] = "handle";
+       p[PARTPROP_busNumber] = "busNumber";
+       p[PARTPROP_last] = NULL;
+}
+
+typedef enum {
+       CTLVMPROP_invalid,
+       CTLVMPROP_physAddr,
+       CTLVMPROP_controlChannelAddr,
+       CTLVMPROP_controlChannelBytes,
+       CTLVMPROP_sparBootPart,
+       CTLVMPROP_sparStoragePart,
+       CTLVMPROP_livedumpLength,
+       CTLVMPROP_livedumpCrc32,
+       /* add new properties above, but don't forget to change
+        * InitControlVmProperties() show_controlvm_property() also...
+        */
+       CTLVMPROP_last
+} CONTROLVM_property;
+
+static const char *ControlVmTypeNames[] = { "controlvm", NULL };
+
+static char *ControlVmPropertyNames[CTLVMPROP_last + 1];
+static void
+InitControlVmProperties(void)
+{
+       char **p = ControlVmPropertyNames;
+       p[CTLVMPROP_invalid] = "";
+       p[CTLVMPROP_physAddr] = "physAddr";
+       p[CTLVMPROP_controlChannelAddr] = "controlChannelAddr";
+       p[CTLVMPROP_controlChannelBytes] = "controlChannelBytes";
+       p[CTLVMPROP_sparBootPart] = "spar_boot_part";
+       p[CTLVMPROP_sparStoragePart] = "spar_storage_part";
+       p[CTLVMPROP_livedumpLength] = "livedumpLength";
+       p[CTLVMPROP_livedumpCrc32] = "livedumpCrc32";
+       p[CTLVMPROP_last] = NULL;
+}
+
+static MYPROCOBJECT *ControlVmObject;
+static MYPROCTYPE *PartitionType;
+static MYPROCTYPE *ControlVmType;
+
+#define VISORCHIPSET_DIAG_PROC_ENTRY_FN "diagdump"
+static struct proc_dir_entry *diag_proc_dir;
+
+#define VISORCHIPSET_CHIPSET_PROC_ENTRY_FN "chipsetready"
+static struct proc_dir_entry *chipset_proc_dir;
+
+#define VISORCHIPSET_PARAHOTPLUG_PROC_ENTRY_FN "parahotplug"
+static struct proc_dir_entry *parahotplug_proc_dir;
+
+static LIST_HEAD(BusInfoList);
+static LIST_HEAD(DevInfoList);
+
+static struct proc_dir_entry *ProcDir;
+static VISORCHANNEL *ControlVm_channel;
+
+static ssize_t visorchipset_proc_read_writeonly(struct file *file,
+                                               char __user *buf,
+                                               size_t len, loff_t *offset);
+static ssize_t proc_read_installer(struct file *file, char __user *buf,
+                                  size_t len, loff_t *offset);
+static ssize_t proc_write_installer(struct file *file,
+                                   const char __user *buffer,
+                                   size_t count, loff_t *ppos);
+static ssize_t proc_read_toolaction(struct file *file, char __user *buf,
+                                   size_t len, loff_t *offset);
+static ssize_t proc_write_toolaction(struct file *file,
+                                    const char __user *buffer,
+                                    size_t count, loff_t *ppos);
+static ssize_t proc_read_bootToTool(struct file *file, char __user *buf,
+                                   size_t len, loff_t *offset);
+static ssize_t proc_write_bootToTool(struct file *file,
+                                    const char __user *buffer,
+                                    size_t count, loff_t *ppos);
+static const struct file_operations proc_installer_fops = {
+       .read = proc_read_installer,
+       .write = proc_write_installer,
+};
+
+static const struct file_operations proc_toolaction_fops = {
+       .read = proc_read_toolaction,
+       .write = proc_write_toolaction,
+};
+
+static const struct file_operations proc_bootToTool_fops = {
+       .read = proc_read_bootToTool,
+       .write = proc_write_bootToTool,
+};
+
+typedef struct {
+       U8 *ptr;                /* pointer to base address of payload pool */
+       U64 offset;             /* offset from beginning of controlvm
+                                * channel to beginning of payload * pool */
+       U32 bytes;              /* number of bytes in payload pool */
+} CONTROLVM_PAYLOAD_INFO;
+
+/* Manages the request payload in the controlvm channel */
+static CONTROLVM_PAYLOAD_INFO ControlVm_payload_info;
+
+static pCHANNEL_HEADER Test_Vnic_channel;
+
+typedef struct {
+       CONTROLVM_MESSAGE_HEADER Dumpcapture_header;
+       CONTROLVM_MESSAGE_HEADER Gettextdump_header;
+       CONTROLVM_MESSAGE_HEADER Dumpcomplete_header;
+       BOOL Gettextdump_outstanding;
+       u32 crc32;
+       ulong length;
+       atomic_t buffers_in_use;
+       ulong destination;
+} LIVEDUMP_INFO;
+/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
+ * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation.
+ */
+static LIVEDUMP_INFO LiveDump_info;
+
+/* The following globals are used to handle the scenario where we are unable to
+ * offload the payload from a controlvm message due to memory requirements.  In
+ * this scenario, we simply stash the controlvm message, then attempt to
+ * process it again the next time controlvm_periodic_work() runs.
+ */
+static CONTROLVM_MESSAGE ControlVm_Pending_Msg;
+static BOOL ControlVm_Pending_Msg_Valid = FALSE;
+
+/* Pool of struct putfile_buffer_entry, for keeping track of pending (incoming)
+ * TRANSMIT_FILE PutFile payloads.
+ */
+static struct kmem_cache *Putfile_buffer_list_pool;
+static const char Putfile_buffer_list_pool_name[] =
+       "controlvm_putfile_buffer_list_pool";
+
+/* This identifies a data buffer that has been received via a controlvm messages
+ * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation.
+ */
+struct putfile_buffer_entry {
+       struct list_head next;  /* putfile_buffer_entry list */
+       PARSER_CONTEXT *parser_ctx; /* points to buffer containing input data */
+};
+
+/* List of struct putfile_request *, via next_putfile_request member.
+ * Each entry in this list identifies an outstanding TRANSMIT_FILE
+ * conversation.
+ */
+static LIST_HEAD(Putfile_request_list);
+
+/* This describes a buffer and its current state of transfer (e.g., how many
+ * bytes have already been supplied as putfile data, and how many bytes are
+ * remaining) for a putfile_request.
+ */
+struct putfile_active_buffer {
+       /* a payload from a controlvm message, containing a file data buffer */
+       PARSER_CONTEXT *parser_ctx;
+       /* points within data area of parser_ctx to next byte of data */
+       u8 *pnext;
+       /* # bytes left from <pnext> to the end of this data buffer */
+       size_t bytes_remaining;
+};
+
+#define PUTFILE_REQUEST_SIG 0x0906101302281211
+/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE
+ * conversation.  Structs of this type are dynamically linked into
+ * <Putfile_request_list>.
+ */
+struct putfile_request {
+       u64 sig;                /* PUTFILE_REQUEST_SIG */
+
+       /* header from original TransmitFile request */
+       CONTROLVM_MESSAGE_HEADER controlvm_header;
+       u64 file_request_number;        /* from original TransmitFile request */
+
+       /* link to next struct putfile_request */
+       struct list_head next_putfile_request;
+
+       /* most-recent sequence number supplied via a controlvm message */
+       u64 data_sequence_number;
+
+       /* head of putfile_buffer_entry list, which describes the data to be
+        * supplied as putfile data;
+        * - this list is added to when controlvm messages come in that supply
+        * file data
+        * - this list is removed from via the hotplug program that is actually
+        * consuming these buffers to write as file data */
+       struct list_head input_buffer_list;
+       spinlock_t req_list_lock;       /* lock for input_buffer_list */
+
+       /* waiters for input_buffer_list to go non-empty */
+       wait_queue_head_t input_buffer_wq;
+
+       /* data not yet read within current putfile_buffer_entry */
+       struct putfile_active_buffer active_buf;
+
+       /* <0 = failed, 0 = in-progress, >0 = successful; */
+       /* note that this must be set with req_list_lock, and if you set <0, */
+       /* it is your responsibility to also free up all of the other objects */
+       /* in this struct (like input_buffer_list, active_buf.parser_ctx) */
+       /* before releasing the lock */
+       int completion_status;
+};
+
+atomic_t Visorchipset_cache_buffers_in_use = ATOMIC_INIT(0);
+
+struct parahotplug_request {
+       struct list_head list;
+       int id;
+       unsigned long expiration;
+       CONTROLVM_MESSAGE msg;
+};
+
+static LIST_HEAD(Parahotplug_request_list);
+static DEFINE_SPINLOCK(Parahotplug_request_list_lock); /* lock for above */
+static void parahotplug_process_list(void);
+
+/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
+ * CONTROLVM_REPORTEVENT.
+ */
+static VISORCHIPSET_BUSDEV_NOTIFIERS BusDev_Server_Notifiers;
+static VISORCHIPSET_BUSDEV_NOTIFIERS BusDev_Client_Notifiers;
+
+static void bus_create_response(ulong busNo, int response);
+static void bus_destroy_response(ulong busNo, int response);
+static void device_create_response(ulong busNo, ulong devNo, int response);
+static void device_destroy_response(ulong busNo, ulong devNo, int response);
+static void device_resume_response(ulong busNo, ulong devNo, int response);
+
+static VISORCHIPSET_BUSDEV_RESPONDERS BusDev_Responders = {
+       .bus_create = bus_create_response,
+       .bus_destroy = bus_destroy_response,
+       .device_create = device_create_response,
+       .device_destroy = device_destroy_response,
+       .device_pause = device_pause_response,
+       .device_resume = device_resume_response,
+};
+
+/* info for /dev/visorchipset */
+static dev_t MajorDev = -1; /**< indicates major num for device */
+
+/* /sys/devices/platform/visorchipset */
+static struct platform_device Visorchipset_platform_device = {
+       .name = "visorchipset",
+       .id = -1,
+};
+
+/* Function prototypes */
+static void controlvm_respond(CONTROLVM_MESSAGE_HEADER *msgHdr, int response);
+static void controlvm_respond_chipset_init(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                                          int response,
+                                          ULTRA_CHIPSET_FEATURE features);
+static void controlvm_respond_physdev_changestate(CONTROLVM_MESSAGE_HEADER *
+                                                 msgHdr, int response,
+                                                 ULTRA_SEGMENT_STATE state);
+
+static void
+show_partition_property(struct seq_file *f, void *ctx, int property)
+{
+       VISORCHIPSET_BUS_INFO *info = (VISORCHIPSET_BUS_INFO *) (ctx);
+
+       switch (property) {
+       case PARTPROP_name:
+               seq_printf(f, "%s\n", NONULLSTR(info->name));
+               break;
+       case PARTPROP_description:
+               seq_printf(f, "%s\n", NONULLSTR(info->description));
+               break;
+       case PARTPROP_handle:
+               seq_printf(f, "0x%-16.16Lx\n", info->partitionHandle);
+               break;
+       case PARTPROP_busNumber:
+               seq_printf(f, "%d\n", info->busNo);
+               break;
+       default:
+               seq_printf(f, "(%d??)\n", property);
+               break;
+       }
+}
+
+static void
+show_controlvm_property(struct seq_file *f, void *ctx, int property)
+{
+       /* Note: ctx is not needed since we only have 1 controlvm channel */
+       switch (property) {
+       case CTLVMPROP_physAddr:
+               if (ControlVm_channel == NULL)
+                       seq_puts(f, "0x0\n");
+               else
+                       seq_printf(f, "0x%-16.16Lx\n",
+                                  visorchannel_get_physaddr
+                                  (ControlVm_channel));
+               break;
+       case CTLVMPROP_controlChannelAddr:
+               if (ControlVm_channel == NULL)
+                       seq_puts(f, "0x0\n");
+               else {
+                       GUEST_PHYSICAL_ADDRESS addr = 0;
+                       visorchannel_read(ControlVm_channel,
+                                         offsetof
+                                         (ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                          gpControlChannel), &addr,
+                                         sizeof(addr));
+                       seq_printf(f, "0x%-16.16Lx\n", (u64) (addr));
+               }
+               break;
+       case CTLVMPROP_controlChannelBytes:
+               if (ControlVm_channel == NULL)
+                       seq_puts(f, "0x0\n");
+               else {
+                       U32 bytes = 0;
+                       visorchannel_read(ControlVm_channel,
+                                         offsetof
+                                         (ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                          ControlChannelBytes), &bytes,
+                                         sizeof(bytes));
+                       seq_printf(f, "%lu\n", (ulong) (bytes));
+               }
+               break;
+       case CTLVMPROP_sparBootPart:
+               seq_puts(f, "0:0:0:0/1\n");
+               break;
+       case CTLVMPROP_sparStoragePart:
+               seq_puts(f, "0:0:0:0/2\n");
+               break;
+       case CTLVMPROP_livedumpLength:
+               seq_printf(f, "%lu\n", LiveDump_info.length);
+               break;
+       case CTLVMPROP_livedumpCrc32:
+               seq_printf(f, "%lu\n", (ulong) LiveDump_info.crc32);
+               break;
+       default:
+               seq_printf(f, "(%d??)\n", property);
+               break;
+       }
+}
+
+static void
+proc_Init(void)
+{
+       if (ProcDir == NULL) {
+               ProcDir = proc_mkdir(MYDRVNAME, NULL);
+               if (ProcDir == NULL) {
+                       LOGERR("failed to create /proc directory %s",
+                              MYDRVNAME);
+                       POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC,
+                                        POSTCODE_SEVERITY_ERR);
+               }
+       }
+}
+
+static void
+proc_DeInit(void)
+{
+       if (ProcDir != NULL)
+               remove_proc_entry(MYDRVNAME, NULL);
+       ProcDir = NULL;
+}
+
+#if 0
+static void
+testUnicode(void)
+{
+       wchar_t unicodeString[] = { 'a', 'b', 'c', 0 };
+       char s[sizeof(unicodeString) * NLS_MAX_CHARSET_SIZE];
+       wchar_t unicode2[99];
+
+       /* NOTE: Either due to a bug, or feature I don't understand, the
+        *       kernel utf8_mbstowcs() and utf_wcstombs() do NOT copy the
+        *       trailed NUL byte!!   REALLY!!!!!    Arrrrgggghhhhh
+        */
+
+       LOGINF("sizeof(wchar_t) = %d", sizeof(wchar_t));
+       LOGINF("utf8_wcstombs=%d",
+              chrs = utf8_wcstombs(s, unicodeString, sizeof(s)));
+       if (chrs >= 0)
+               s[chrs] = '\0'; /* GRRRRRRRR */
+       LOGINF("s='%s'", s);
+       LOGINF("utf8_mbstowcs=%d", chrs = utf8_mbstowcs(unicode2, s, 100));
+       if (chrs >= 0)
+               unicode2[chrs] = 0;     /* GRRRRRRRR */
+       if (memcmp(unicodeString, unicode2, sizeof(unicodeString)) == 0)
+               LOGINF("strings match... good");
+       else
+               LOGINF("strings did not match!!");
+}
+#endif
+
+static void
+busInfo_clear(void *v)
+{
+       VISORCHIPSET_BUS_INFO *p = (VISORCHIPSET_BUS_INFO *) (v);
+
+       if (p->procObject) {
+               proc_DestroyObject(p->procObject);
+               p->procObject = NULL;
+       }
+       kfree(p->name);
+       p->name = NULL;
+
+       kfree(p->description);
+       p->description = NULL;
+
+       p->state.created = 0;
+       memset(p, 0, sizeof(VISORCHIPSET_BUS_INFO));
+}
+
+static void
+devInfo_clear(void *v)
+{
+       VISORCHIPSET_DEVICE_INFO *p = (VISORCHIPSET_DEVICE_INFO *) (v);
+       p->state.created = 0;
+       memset(p, 0, sizeof(VISORCHIPSET_DEVICE_INFO));
+}
+
+static U8
+check_chipset_events(void)
+{
+       int i;
+       U8 send_msg = 1;
+       /* Check events to determine if response should be sent */
+       for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
+               send_msg &= chipset_events[i];
+       return send_msg;
+}
+
+static void
+clear_chipset_events(void)
+{
+       int i;
+       /* Clear chipset_events */
+       for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
+               chipset_events[i] = 0;
+}
+
+void
+visorchipset_register_busdev_server(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+                                   VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+                                   ULTRA_VBUS_DEVICEINFO *driverInfo)
+{
+       LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+       if (notifiers == NULL) {
+               memset(&BusDev_Server_Notifiers, 0,
+                      sizeof(BusDev_Server_Notifiers));
+               serverregistered = 0;   /* clear flag */
+       } else {
+               BusDev_Server_Notifiers = *notifiers;
+               serverregistered = 1;   /* set flag */
+       }
+       if (responders)
+               *responders = BusDev_Responders;
+       if (driverInfo)
+               BusDeviceInfo_Init(driverInfo, "chipset", "visorchipset",
+                                  VERSION, NULL, __DATE__, __TIME__);
+
+       UNLOCKSEM(&NotifierLock);
+}
+EXPORT_SYMBOL_GPL(visorchipset_register_busdev_server);
+
+void
+visorchipset_register_busdev_client(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+                                   VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+                                   ULTRA_VBUS_DEVICEINFO *driverInfo)
+{
+       LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+       if (notifiers == NULL) {
+               memset(&BusDev_Client_Notifiers, 0,
+                      sizeof(BusDev_Client_Notifiers));
+               clientregistered = 0;   /* clear flag */
+       } else {
+               BusDev_Client_Notifiers = *notifiers;
+               clientregistered = 1;   /* set flag */
+       }
+       if (responders)
+               *responders = BusDev_Responders;
+       if (driverInfo)
+               BusDeviceInfo_Init(driverInfo, "chipset(bolts)", "visorchipset",
+                                  VERSION, NULL, __DATE__, __TIME__);
+       UNLOCKSEM(&NotifierLock);
+}
+EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client);
+
+static void
+cleanup_controlvm_structures(void)
+{
+       VISORCHIPSET_BUS_INFO *bi;
+       VISORCHIPSET_DEVICE_INFO *di;
+
+       list_for_each_entry(bi, &BusInfoList, entry) {
+               busInfo_clear(bi);
+               list_del(&bi->entry);
+               kfree(bi);
+       }
+
+       list_for_each_entry(di, &DevInfoList, entry) {
+               devInfo_clear(di);
+               list_del(&di->entry);
+               kfree(di);
+       }
+}
+
+static void
+chipset_init(CONTROLVM_MESSAGE *inmsg)
+{
+       static int chipset_inited;
+       ULTRA_CHIPSET_FEATURE features = 0;
+       int rc = CONTROLVM_RESP_SUCCESS;
+
+       POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+       if (chipset_inited) {
+               LOGERR("CONTROLVM_CHIPSET_INIT Failed: Already Done.");
+               RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+       }
+       chipset_inited = 1;
+       POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+       /* Set features to indicate we support parahotplug (if Command
+        * also supports it). */
+       features =
+           inmsg->cmd.initChipset.
+           features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
+
+       /* Set the "reply" bit so Command knows this is a
+        * features-aware driver. */
+       features |= ULTRA_CHIPSET_FEATURE_REPLY;
+
+Away:
+       if (rc < 0)
+               cleanup_controlvm_structures();
+       if (inmsg->hdr.Flags.responseExpected)
+               controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
+}
+
+static void
+controlvm_init_response(CONTROLVM_MESSAGE *msg,
+                       CONTROLVM_MESSAGE_HEADER *msgHdr, int response)
+{
+       memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
+       memcpy(&msg->hdr, msgHdr, sizeof(CONTROLVM_MESSAGE_HEADER));
+       msg->hdr.PayloadBytes = 0;
+       msg->hdr.PayloadVmOffset = 0;
+       msg->hdr.PayloadMaxBytes = 0;
+       if (response < 0) {
+               msg->hdr.Flags.failed = 1;
+               msg->hdr.CompletionStatus = (U32) (-response);
+       }
+}
+
+static void
+controlvm_respond(CONTROLVM_MESSAGE_HEADER *msgHdr, int response)
+{
+       CONTROLVM_MESSAGE outmsg;
+       if (!ControlVm_channel)
+               return;
+       controlvm_init_response(&outmsg, msgHdr, response);
+       /* For DiagPool channel DEVICE_CHANGESTATE, we need to send
+       * back the deviceChangeState structure in the packet. */
+       if (msgHdr->Id == CONTROLVM_DEVICE_CHANGESTATE
+           && g_DeviceChangeStatePacket.deviceChangeState.busNo ==
+           g_diagpoolBusNo
+           && g_DeviceChangeStatePacket.deviceChangeState.devNo ==
+           g_diagpoolDevNo)
+               outmsg.cmd = g_DeviceChangeStatePacket;
+       if (outmsg.hdr.Flags.testMessage == 1) {
+               LOGINF("%s controlvm_msg=0x%x response=%d for test message",
+                      __func__, outmsg.hdr.Id, response);
+               return;
+       }
+       if (!visorchannel_signalinsert(ControlVm_channel,
+                                      CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+               LOGERR("signalinsert failed!");
+               return;
+       }
+}
+
+static void
+controlvm_respond_chipset_init(CONTROLVM_MESSAGE_HEADER *msgHdr, int response,
+                              ULTRA_CHIPSET_FEATURE features)
+{
+       CONTROLVM_MESSAGE outmsg;
+       if (!ControlVm_channel)
+               return;
+       controlvm_init_response(&outmsg, msgHdr, response);
+       outmsg.cmd.initChipset.features = features;
+       if (!visorchannel_signalinsert(ControlVm_channel,
+                                      CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+               LOGERR("signalinsert failed!");
+               return;
+       }
+}
+
+static void
+controlvm_respond_physdev_changestate(CONTROLVM_MESSAGE_HEADER *msgHdr,
+                                     int response, ULTRA_SEGMENT_STATE state)
+{
+       CONTROLVM_MESSAGE outmsg;
+       if (!ControlVm_channel)
+               return;
+       controlvm_init_response(&outmsg, msgHdr, response);
+       outmsg.cmd.deviceChangeState.state = state;
+       outmsg.cmd.deviceChangeState.flags.physicalDevice = 1;
+       if (!visorchannel_signalinsert(ControlVm_channel,
+                                      CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+               LOGERR("signalinsert failed!");
+               return;
+       }
+}
+
+void
+visorchipset_save_message(CONTROLVM_MESSAGE *msg, CRASH_OBJ_TYPE type)
+{
+       U32 localSavedCrashMsgOffset;
+       U16 localSavedCrashMsgCount;
+
+       /* get saved message count */
+       if (visorchannel_read(ControlVm_channel,
+                             offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                      SavedCrashMsgCount),
+                             &localSavedCrashMsgCount, sizeof(U16)) < 0) {
+               LOGERR("failed to get Saved Message Count");
+               POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       if (localSavedCrashMsgCount != CONTROLVM_CRASHMSG_MAX) {
+               LOGERR("Saved Message Count incorrect %d",
+                      localSavedCrashMsgCount);
+               POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
+                                localSavedCrashMsgCount,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* get saved crash message offset */
+       if (visorchannel_read(ControlVm_channel,
+                             offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                      SavedCrashMsgOffset),
+                             &localSavedCrashMsgOffset, sizeof(U32)) < 0) {
+               LOGERR("failed to get Saved Message Offset");
+               POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       if (type == CRASH_bus) {
+               if (visorchannel_write(ControlVm_channel,
+                                      localSavedCrashMsgOffset,
+                                      msg, sizeof(CONTROLVM_MESSAGE)) < 0) {
+                       LOGERR("SAVE_MSG_BUS_FAILURE: Failed to write CrashCreateBusMsg!");
+                       POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
+                                        POSTCODE_SEVERITY_ERR);
+                       return;
+               }
+       } else {
+               if (visorchannel_write(ControlVm_channel,
+                                      localSavedCrashMsgOffset +
+                                      sizeof(CONTROLVM_MESSAGE), msg,
+                                      sizeof(CONTROLVM_MESSAGE)) < 0) {
+                       LOGERR("SAVE_MSG_DEV_FAILURE: Failed to write CrashCreateDevMsg!");
+                       POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
+                                        POSTCODE_SEVERITY_ERR);
+                       return;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(visorchipset_save_message);
+
+static void
+bus_responder(CONTROLVM_ID cmdId, ulong busNo, int response)
+{
+       VISORCHIPSET_BUS_INFO *p = NULL;
+       BOOL need_clear = FALSE;
+
+       p = findbus(&BusInfoList, busNo);
+       if (!p) {
+               LOGERR("internal error busNo=%lu", busNo);
+               return;
+       }
+       if (response < 0) {
+               if ((cmdId == CONTROLVM_BUS_CREATE) &&
+                   (response != (-CONTROLVM_RESP_ERROR_ALREADY_DONE)))
+                       /* undo the row we just created... */
+                       delbusdevices(&DevInfoList, busNo);
+       } else {
+               if (cmdId == CONTROLVM_BUS_CREATE)
+                       p->state.created = 1;
+               if (cmdId == CONTROLVM_BUS_DESTROY)
+                       need_clear = TRUE;
+       }
+
+       if (p->pendingMsgHdr.Id == CONTROLVM_INVALID) {
+               LOGERR("bus_responder no pending msg");
+               return;         /* no controlvm response needed */
+       }
+       if (p->pendingMsgHdr.Id != (U32) cmdId) {
+               LOGERR("expected=%d, found=%d", cmdId, p->pendingMsgHdr.Id);
+               return;
+       }
+       controlvm_respond(&p->pendingMsgHdr, response);
+       p->pendingMsgHdr.Id = CONTROLVM_INVALID;
+       if (need_clear) {
+               busInfo_clear(p);
+               delbusdevices(&DevInfoList, busNo);
+       }
+}
+
+static void
+device_changestate_responder(CONTROLVM_ID cmdId,
+                            ulong busNo, ulong devNo, int response,
+                            ULTRA_SEGMENT_STATE responseState)
+{
+       VISORCHIPSET_DEVICE_INFO *p = NULL;
+       CONTROLVM_MESSAGE outmsg;
+
+       if (!ControlVm_channel)
+               return;
+
+       p = finddevice(&DevInfoList, busNo, devNo);
+       if (!p) {
+               LOGERR("internal error; busNo=%lu, devNo=%lu", busNo, devNo);
+               return;
+       }
+       if (p->pendingMsgHdr.Id == CONTROLVM_INVALID) {
+               LOGERR("device_responder no pending msg");
+               return;         /* no controlvm response needed */
+       }
+       if (p->pendingMsgHdr.Id != cmdId) {
+               LOGERR("expected=%d, found=%d", cmdId, p->pendingMsgHdr.Id);
+               return;
+       }
+
+       controlvm_init_response(&outmsg, &p->pendingMsgHdr, response);
+
+       outmsg.cmd.deviceChangeState.busNo = busNo;
+       outmsg.cmd.deviceChangeState.devNo = devNo;
+       outmsg.cmd.deviceChangeState.state = responseState;
+
+       if (!visorchannel_signalinsert(ControlVm_channel,
+                                      CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+               LOGERR("signalinsert failed!");
+               return;
+       }
+
+       p->pendingMsgHdr.Id = CONTROLVM_INVALID;
+}
+
+static void
+device_responder(CONTROLVM_ID cmdId, ulong busNo, ulong devNo, int response)
+{
+       VISORCHIPSET_DEVICE_INFO *p = NULL;
+       BOOL need_clear = FALSE;
+
+       p = finddevice(&DevInfoList, busNo, devNo);
+       if (!p) {
+               LOGERR("internal error; busNo=%lu, devNo=%lu", busNo, devNo);
+               return;
+       }
+       if (response >= 0) {
+               if (cmdId == CONTROLVM_DEVICE_CREATE)
+                       p->state.created = 1;
+               if (cmdId == CONTROLVM_DEVICE_DESTROY)
+                       need_clear = TRUE;
+       }
+
+       if (p->pendingMsgHdr.Id == CONTROLVM_INVALID) {
+               LOGERR("device_responder no pending msg");
+               return;         /* no controlvm response needed */
+       }
+       if (p->pendingMsgHdr.Id != (U32) cmdId) {
+               LOGERR("expected=%d, found=%d", cmdId, p->pendingMsgHdr.Id);
+               return;
+       }
+       controlvm_respond(&p->pendingMsgHdr, response);
+       p->pendingMsgHdr.Id = CONTROLVM_INVALID;
+       if (need_clear)
+               devInfo_clear(p);
+}
+
+static void
+bus_epilog(U32 busNo,
+          U32 cmd, CONTROLVM_MESSAGE_HEADER *msgHdr,
+          int response, BOOL needResponse)
+{
+       BOOL notified = FALSE;
+
+       VISORCHIPSET_BUS_INFO *pBusInfo = findbus(&BusInfoList, busNo);
+
+       if (!pBusInfo) {
+               LOGERR("HUH? bad busNo=%d", busNo);
+               return;
+       }
+       if (needResponse) {
+               memcpy(&pBusInfo->pendingMsgHdr, msgHdr,
+                      sizeof(CONTROLVM_MESSAGE_HEADER));
+       } else
+               pBusInfo->pendingMsgHdr.Id = CONTROLVM_INVALID;
+
+       LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+       if (response == CONTROLVM_RESP_SUCCESS) {
+               switch (cmd) {
+               case CONTROLVM_BUS_CREATE:
+                       /* We can't tell from the bus_create
+                       * information which of our 2 bus flavors the
+                       * devices on this bus will ultimately end up.
+                       * FORTUNATELY, it turns out it is harmless to
+                       * send the bus_create to both of them.  We can
+                       * narrow things down a little bit, though,
+                       * because we know: - BusDev_Server can handle
+                       * either server or client devices
+                       * - BusDev_Client can handle ONLY client
+                       * devices */
+                       if (BusDev_Server_Notifiers.bus_create) {
+                               (*BusDev_Server_Notifiers.bus_create) (busNo);
+                               notified = TRUE;
+                       }
+                       if ((!pBusInfo->flags.server) /*client */ &&
+                           BusDev_Client_Notifiers.bus_create) {
+                               (*BusDev_Client_Notifiers.bus_create) (busNo);
+                               notified = TRUE;
+                       }
+                       break;
+               case CONTROLVM_BUS_DESTROY:
+                       if (BusDev_Server_Notifiers.bus_destroy) {
+                               (*BusDev_Server_Notifiers.bus_destroy) (busNo);
+                               notified = TRUE;
+                       }
+                       if ((!pBusInfo->flags.server) /*client */ &&
+                           BusDev_Client_Notifiers.bus_destroy) {
+                               (*BusDev_Client_Notifiers.bus_destroy) (busNo);
+                               notified = TRUE;
+                       }
+                       break;
+               }
+       }
+       if (notified)
+               /* The callback function just called above is responsible
+                * for calling the appropriate VISORCHIPSET_BUSDEV_RESPONDERS
+                * function, which will call bus_responder()
+                */
+               ;
+       else
+               bus_responder(cmd, busNo, response);
+       UNLOCKSEM(&NotifierLock);
+}
+
+static void
+device_epilog(U32 busNo, U32 devNo, ULTRA_SEGMENT_STATE state, U32 cmd,
+             CONTROLVM_MESSAGE_HEADER *msgHdr, int response,
+             BOOL needResponse, BOOL for_visorbus)
+{
+       VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers = NULL;
+       BOOL notified = FALSE;
+
+       VISORCHIPSET_DEVICE_INFO *pDevInfo =
+               finddevice(&DevInfoList, busNo, devNo);
+       char *envp[] = {
+               "SPARSP_DIAGPOOL_PAUSED_STATE = 1",
+               NULL
+       };
+
+       if (!pDevInfo) {
+               LOGERR("HUH? bad busNo=%d, devNo=%d", busNo, devNo);
+               return;
+       }
+       if (for_visorbus)
+               notifiers = &BusDev_Server_Notifiers;
+       else
+               notifiers = &BusDev_Client_Notifiers;
+       if (needResponse) {
+               memcpy(&pDevInfo->pendingMsgHdr, msgHdr,
+                      sizeof(CONTROLVM_MESSAGE_HEADER));
+       } else
+               pDevInfo->pendingMsgHdr.Id = CONTROLVM_INVALID;
+
+       LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+       if (response >= 0) {
+               switch (cmd) {
+               case CONTROLVM_DEVICE_CREATE:
+                       if (notifiers->device_create) {
+                               (*notifiers->device_create) (busNo, devNo);
+                               notified = TRUE;
+                       }
+                       break;
+               case CONTROLVM_DEVICE_CHANGESTATE:
+                       /* ServerReady / ServerRunning / SegmentStateRunning */
+                       if (state.Alive == SegmentStateRunning.Alive &&
+                           state.Operating == SegmentStateRunning.Operating) {
+                               if (notifiers->device_resume) {
+                                       (*notifiers->device_resume) (busNo,
+                                                                    devNo);
+                                       notified = TRUE;
+                               }
+                       }
+                       /* ServerNotReady / ServerLost / SegmentStateStandby */
+                       else if (state.Alive == SegmentStateStandby.Alive &&
+                                state.Operating ==
+                                SegmentStateStandby.Operating) {
+                               /* technically this is standby case
+                                * where server is lost
+                                */
+                               if (notifiers->device_pause) {
+                                       (*notifiers->device_pause) (busNo,
+                                                                   devNo);
+                                       notified = TRUE;
+                               }
+                       } else if (state.Alive == SegmentStatePaused.Alive &&
+                                  state.Operating ==
+                                  SegmentStatePaused.Operating) {
+                               /* this is lite pause where channel is
+                                * still valid just 'pause' of it
+                                */
+                               if (busNo == g_diagpoolBusNo
+                                   && devNo == g_diagpoolDevNo) {
+                                       LOGINF("DEVICE_CHANGESTATE(DiagpoolChannel busNo=%d devNo=%d is pausing...)",
+                                            busNo, devNo);
+                                       /* this will trigger the
+                                        * diag_shutdown.sh script in
+                                        * the visorchipset hotplug */
+                                       kobject_uevent_env
+                                           (&Visorchipset_platform_device.dev.
+                                            kobj, KOBJ_ONLINE, envp);
+                               }
+                       }
+                       break;
+               case CONTROLVM_DEVICE_DESTROY:
+                       if (notifiers->device_destroy) {
+                               (*notifiers->device_destroy) (busNo, devNo);
+                               notified = TRUE;
+                       }
+                       break;
+               }
+       }
+       if (notified)
+               /* The callback function just called above is responsible
+                * for calling the appropriate VISORCHIPSET_BUSDEV_RESPONDERS
+                * function, which will call device_responder()
+                */
+               ;
+       else
+               device_responder(cmd, busNo, devNo, response);
+       UNLOCKSEM(&NotifierLock);
+}
+
+static void
+bus_create(CONTROLVM_MESSAGE *inmsg)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+       ulong busNo = cmd->createBus.busNo;
+       int rc = CONTROLVM_RESP_SUCCESS;
+       VISORCHIPSET_BUS_INFO *pBusInfo = NULL;
+
+
+       pBusInfo = findbus(&BusInfoList, busNo);
+       if (pBusInfo && (pBusInfo->state.created == 1)) {
+               LOGERR("CONTROLVM_BUS_CREATE Failed: bus %lu already exists",
+                      busNo);
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+       }
+       pBusInfo = kmalloc(sizeof(VISORCHIPSET_BUS_INFO), GFP_KERNEL);
+       if (pBusInfo == NULL) {
+               LOGERR("CONTROLVM_BUS_CREATE Failed: bus %lu kmalloc failed",
+                      busNo);
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_KMALLOC_FAILED);
+       }
+
+       memset(pBusInfo, 0, sizeof(VISORCHIPSET_BUS_INFO));
+       INIT_LIST_HEAD(&pBusInfo->entry);
+       pBusInfo->busNo = busNo;
+       pBusInfo->devNo = cmd->createBus.deviceCount;
+
+       POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+       if (inmsg->hdr.Flags.testMessage == 1)
+               pBusInfo->chanInfo.addrType = ADDRTYPE_localTest;
+       else
+               pBusInfo->chanInfo.addrType = ADDRTYPE_localPhysical;
+
+       pBusInfo->flags.server = inmsg->hdr.Flags.server;
+       pBusInfo->chanInfo.channelAddr = cmd->createBus.channelAddr;
+       pBusInfo->chanInfo.nChannelBytes = cmd->createBus.channelBytes;
+       pBusInfo->chanInfo.channelTypeGuid = cmd->createBus.busDataTypeGuid;
+       pBusInfo->chanInfo.channelInstGuid = cmd->createBus.busInstGuid;
+
+       list_add(&pBusInfo->entry, &BusInfoList);
+
+       POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+Away:
+       bus_epilog(busNo, CONTROLVM_BUS_CREATE, &inmsg->hdr,
+                  rc, inmsg->hdr.Flags.responseExpected == 1);
+}
+
+static void
+bus_destroy(CONTROLVM_MESSAGE *inmsg)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+       ulong busNo = cmd->destroyBus.busNo;
+       VISORCHIPSET_BUS_INFO *pBusInfo;
+       int rc = CONTROLVM_RESP_SUCCESS;
+
+       pBusInfo = findbus(&BusInfoList, busNo);
+       if (!pBusInfo) {
+               LOGERR("CONTROLVM_BUS_DESTROY Failed: bus %lu invalid", busNo);
+               RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+       }
+       if (pBusInfo->state.created == 0) {
+               LOGERR("CONTROLVM_BUS_DESTROY Failed: bus %lu already destroyed",
+                    busNo);
+               RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+       }
+
+Away:
+       bus_epilog(busNo, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
+                  rc, inmsg->hdr.Flags.responseExpected == 1);
+}
+
+static void
+bus_configure(CONTROLVM_MESSAGE *inmsg, PARSER_CONTEXT *parser_ctx)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+       ulong busNo = cmd->configureBus.busNo;
+       VISORCHIPSET_BUS_INFO *pBusInfo = NULL;
+       int rc = CONTROLVM_RESP_SUCCESS;
+       char s[99];
+
+       busNo = cmd->configureBus.busNo;
+       POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+       pBusInfo = findbus(&BusInfoList, busNo);
+       if (!pBusInfo) {
+               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: bus %lu invalid",
+                      busNo);
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+       }
+       if (pBusInfo->state.created == 0) {
+               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: Invalid bus %lu - not created yet",
+                    busNo);
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+       }
+       /* TBD - add this check to other commands also... */
+       if (pBusInfo->pendingMsgHdr.Id != CONTROLVM_INVALID) {
+               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: bus %lu MsgId=%u outstanding",
+                    busNo, (uint) pBusInfo->pendingMsgHdr.Id);
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT);
+       }
+
+       pBusInfo->partitionHandle = cmd->configureBus.guestHandle;
+       pBusInfo->partitionGuid = parser_id_get(parser_ctx);
+       parser_param_start(parser_ctx, PARSERSTRING_NAME);
+       pBusInfo->name = parser_string_get(parser_ctx);
+
+       visorchannel_GUID_id(&pBusInfo->partitionGuid, s);
+       pBusInfo->procObject =
+           proc_CreateObject(PartitionType, s, (void *) (pBusInfo));
+       if (pBusInfo->procObject == NULL) {
+               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: busNo=%lu failed to create /proc entry",
+                    busNo);
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_KMALLOC_FAILED);
+       }
+       POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+Away:
+       bus_epilog(busNo, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
+                  rc, inmsg->hdr.Flags.responseExpected == 1);
+}
+
+static void
+my_device_create(CONTROLVM_MESSAGE *inmsg)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+       ulong busNo = cmd->createDevice.busNo;
+       ulong devNo = cmd->createDevice.devNo;
+       VISORCHIPSET_DEVICE_INFO *pDevInfo = NULL;
+       VISORCHIPSET_BUS_INFO *pBusInfo = NULL;
+       int rc = CONTROLVM_RESP_SUCCESS;
+
+       pDevInfo = finddevice(&DevInfoList, busNo, devNo);
+       if (pDevInfo && (pDevInfo->state.created == 1)) {
+               LOGERR("CONTROLVM_DEVICE_CREATE Failed: busNo=%lu, devNo=%lu already exists",
+                    busNo, devNo);
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+       }
+       pBusInfo = findbus(&BusInfoList, busNo);
+       if (!pBusInfo) {
+               LOGERR("CONTROLVM_DEVICE_CREATE Failed: Invalid bus %lu - out of range",
+                    busNo);
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+       }
+       if (pBusInfo->state.created == 0) {
+               LOGERR("CONTROLVM_DEVICE_CREATE Failed: Invalid bus %lu - not created yet",
+                    busNo);
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+       }
+       pDevInfo = kmalloc(sizeof(VISORCHIPSET_DEVICE_INFO), GFP_KERNEL);
+       if (pDevInfo == NULL) {
+               LOGERR("CONTROLVM_DEVICE_CREATE Failed: busNo=%lu, devNo=%lu kmaloc failed",
+                    busNo, devNo);
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_KMALLOC_FAILED);
+       }
+       memset(pDevInfo, 0, sizeof(VISORCHIPSET_DEVICE_INFO));
+       INIT_LIST_HEAD(&pDevInfo->entry);
+       pDevInfo->busNo = busNo;
+       pDevInfo->devNo = devNo;
+       pDevInfo->devInstGuid = cmd->createDevice.devInstGuid;
+       POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+
+       if (inmsg->hdr.Flags.testMessage == 1)
+               pDevInfo->chanInfo.addrType = ADDRTYPE_localTest;
+       else
+               pDevInfo->chanInfo.addrType = ADDRTYPE_localPhysical;
+       pDevInfo->chanInfo.channelAddr = cmd->createDevice.channelAddr;
+       pDevInfo->chanInfo.nChannelBytes = cmd->createDevice.channelBytes;
+       pDevInfo->chanInfo.channelTypeGuid = cmd->createDevice.dataTypeGuid;
+       pDevInfo->chanInfo.intr = cmd->createDevice.intr;
+       list_add(&pDevInfo->entry, &DevInfoList);
+       POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, devNo, busNo,
+                        POSTCODE_SEVERITY_INFO);
+Away:
+       /* get the bus and devNo for DiagPool channel */
+       if (is_diagpool_channel(pDevInfo->chanInfo.channelTypeGuid)) {
+               g_diagpoolBusNo = busNo;
+               g_diagpoolDevNo = devNo;
+               LOGINF("CONTROLVM_DEVICE_CREATE for DiagPool channel: busNo=%lu, devNo=%lu",
+                    g_diagpoolBusNo, g_diagpoolDevNo);
+       }
+       device_epilog(busNo, devNo, SegmentStateRunning,
+                     CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
+                     inmsg->hdr.Flags.responseExpected == 1,
+                     FOR_VISORBUS(pDevInfo->chanInfo.channelTypeGuid));
+}
+
+static void
+my_device_changestate(CONTROLVM_MESSAGE *inmsg)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+       ulong busNo = cmd->deviceChangeState.busNo;
+       ulong devNo = cmd->deviceChangeState.devNo;
+       ULTRA_SEGMENT_STATE state = cmd->deviceChangeState.state;
+       VISORCHIPSET_DEVICE_INFO *pDevInfo = NULL;
+       int rc = CONTROLVM_RESP_SUCCESS;
+
+       pDevInfo = finddevice(&DevInfoList, busNo, devNo);
+       if (!pDevInfo) {
+               LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: busNo=%lu, devNo=%lu invalid (doesn't exist)",
+                    busNo, devNo);
+               POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_DEVICE_INVALID);
+       }
+       if (pDevInfo->state.created == 0) {
+               LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: busNo=%lu, devNo=%lu invalid (not created)",
+                    busNo, devNo);
+               POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, devNo, busNo,
+                                POSTCODE_SEVERITY_ERR);
+               RETINT(-CONTROLVM_RESP_ERROR_DEVICE_INVALID);
+       }
+Away:
+       if ((rc >= CONTROLVM_RESP_SUCCESS) && pDevInfo)
+               device_epilog(busNo, devNo, state, CONTROLVM_DEVICE_CHANGESTATE,
+                             &inmsg->hdr, rc,
+                             inmsg->hdr.Flags.responseExpected == 1,
+                             FOR_VISORBUS(pDevInfo->chanInfo.channelTypeGuid));
+}
+
+static void
+my_device_destroy(CONTROLVM_MESSAGE *inmsg)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+       ulong busNo = cmd->destroyDevice.busNo;
+       ulong devNo = cmd->destroyDevice.devNo;
+       VISORCHIPSET_DEVICE_INFO *pDevInfo = NULL;
+       int rc = CONTROLVM_RESP_SUCCESS;
+
+       pDevInfo = finddevice(&DevInfoList, busNo, devNo);
+       if (!pDevInfo) {
+               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: busNo=%lu, devNo=%lu invalid",
+                    busNo, devNo);
+               RETINT(-CONTROLVM_RESP_ERROR_DEVICE_INVALID);
+       }
+       if (pDevInfo->state.created == 0) {
+               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: busNo=%lu, devNo=%lu already destroyed",
+                    busNo, devNo);
+               RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+       }
+
+Away:
+       if ((rc >= CONTROLVM_RESP_SUCCESS) && pDevInfo)
+               device_epilog(busNo, devNo, SegmentStateRunning,
+                             CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
+                             inmsg->hdr.Flags.responseExpected == 1,
+                             FOR_VISORBUS(pDevInfo->chanInfo.channelTypeGuid));
+}
+
+/* When provided with the physical address of the controlvm channel
+ * (phys_addr), the offset to the payload area we need to manage
+ * (offset), and the size of this payload area (bytes), fills in the
+ * CONTROLVM_PAYLOAD_INFO struct.  Returns TRUE for success or FALSE
+ * for failure.
+ */
+static int
+initialize_controlvm_payload_info(HOSTADDRESS phys_addr, U64 offset, U32 bytes,
+                                 CONTROLVM_PAYLOAD_INFO *info)
+{
+       U8 *payload = NULL;
+       int rc = CONTROLVM_RESP_SUCCESS;
+
+       if (info == NULL) {
+               LOGERR("HUH ? CONTROLVM_PAYLOAD_INIT Failed : Programmer check at %s:%d",
+                    __FILE__, __LINE__);
+               RETINT(-CONTROLVM_RESP_ERROR_PAYLOAD_INVALID);
+       }
+       memset(info, 0, sizeof(CONTROLVM_PAYLOAD_INFO));
+       if ((offset == 0) || (bytes == 0)) {
+               LOGERR("CONTROLVM_PAYLOAD_INIT Failed: RequestPayloadOffset=%llu RequestPayloadBytes=%llu!",
+                    (u64) offset, (u64) bytes);
+               RETINT(-CONTROLVM_RESP_ERROR_PAYLOAD_INVALID);
+       }
+       payload = ioremap_cache(phys_addr + offset, bytes);
+       if (payload == NULL) {
+               LOGERR("CONTROLVM_PAYLOAD_INIT Failed: ioremap_cache %llu for %llu bytes failed",
+                    (u64) offset, (u64) bytes);
+               RETINT(-CONTROLVM_RESP_ERROR_IOREMAP_FAILED);
+       }
+
+       info->offset = offset;
+       info->bytes = bytes;
+       info->ptr = payload;
+       LOGINF("offset=%llu, bytes=%lu, ptr=%p",
+              (u64) (info->offset), (ulong) (info->bytes), info->ptr);
+
+Away:
+       if (rc < 0) {
+               if (payload != NULL) {
+                       iounmap(payload);
+                       payload = NULL;
+               }
+       }
+       return rc;
+}
+
+static void
+destroy_controlvm_payload_info(CONTROLVM_PAYLOAD_INFO *info)
+{
+       if (info->ptr != NULL) {
+               iounmap(info->ptr);
+               info->ptr = NULL;
+       }
+       memset(info, 0, sizeof(CONTROLVM_PAYLOAD_INFO));
+}
+
+static void
+initialize_controlvm_payload(void)
+{
+       HOSTADDRESS phys_addr = visorchannel_get_physaddr(ControlVm_channel);
+       U64 payloadOffset = 0;
+       U32 payloadBytes = 0;
+       if (visorchannel_read(ControlVm_channel,
+                             offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                      RequestPayloadOffset),
+                             &payloadOffset, sizeof(payloadOffset)) < 0) {
+               LOGERR("CONTROLVM_PAYLOAD_INIT Failed to read controlvm channel!");
+               POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+       if (visorchannel_read(ControlVm_channel,
+                             offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                      RequestPayloadBytes),
+                             &payloadBytes, sizeof(payloadBytes)) < 0) {
+               LOGERR("CONTROLVM_PAYLOAD_INIT Failed to read controlvm channel!");
+               POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+       initialize_controlvm_payload_info(phys_addr,
+                                         payloadOffset, payloadBytes,
+                                         &ControlVm_payload_info);
+}
+
+/*  Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
+ *  Returns CONTROLVM_RESP_xxx code.
+ */
+int
+visorchipset_chipset_ready(void)
+{
+       kobject_uevent(&Visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
+       return CONTROLVM_RESP_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(visorchipset_chipset_ready);
+
+int
+visorchipset_chipset_selftest(void)
+{
+       char env_selftest[20];
+       char *envp[] = { env_selftest, NULL };
+       sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
+       kobject_uevent_env(&Visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
+                          envp);
+       return CONTROLVM_RESP_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(visorchipset_chipset_selftest);
+
+/*  Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
+ *  Returns CONTROLVM_RESP_xxx code.
+ */
+int
+visorchipset_chipset_notready(void)
+{
+       kobject_uevent(&Visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
+       return CONTROLVM_RESP_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(visorchipset_chipset_notready);
+
+static void
+chipset_ready(CONTROLVM_MESSAGE_HEADER *msgHdr)
+{
+       int rc = visorchipset_chipset_ready();
+       if (rc != CONTROLVM_RESP_SUCCESS)
+               rc = -rc;
+       if (msgHdr->Flags.responseExpected && !visorchipset_holdchipsetready)
+               controlvm_respond(msgHdr, rc);
+       if (msgHdr->Flags.responseExpected && visorchipset_holdchipsetready) {
+               /* Send CHIPSET_READY response when all modules have been loaded
+                * and disks mounted for the partition
+                */
+               g_ChipSetMsgHdr = *msgHdr;
+               LOGINF("Holding CHIPSET_READY response");
+       }
+}
+
+static void
+chipset_selftest(CONTROLVM_MESSAGE_HEADER *msgHdr)
+{
+       int rc = visorchipset_chipset_selftest();
+       if (rc != CONTROLVM_RESP_SUCCESS)
+               rc = -rc;
+       if (msgHdr->Flags.responseExpected)
+               controlvm_respond(msgHdr, rc);
+}
+
+static void
+chipset_notready(CONTROLVM_MESSAGE_HEADER *msgHdr)
+{
+       int rc = visorchipset_chipset_notready();
+       if (rc != CONTROLVM_RESP_SUCCESS)
+               rc = -rc;
+       if (msgHdr->Flags.responseExpected)
+               controlvm_respond(msgHdr, rc);
+}
+
+/* This is your "one-stop" shop for grabbing the next message from the
+ * CONTROLVM_QUEUE_EVENT queue in the controlvm channel.
+ */
+static BOOL
+read_controlvm_event(CONTROLVM_MESSAGE *msg)
+{
+       if (visorchannel_signalremove(ControlVm_channel,
+                                     CONTROLVM_QUEUE_EVENT, msg)) {
+               /* got a message */
+               if (msg->hdr.Flags.testMessage == 1) {
+                       LOGERR("ignoring bad CONTROLVM_QUEUE_EVENT msg with controlvm_msg_id=0x%x because Flags.testMessage is nonsensical (=1)", msg->hdr.Id);
+                       return FALSE;
+               } else
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+/*
+ * The general parahotplug flow works as follows.  The visorchipset
+ * driver receives a DEVICE_CHANGESTATE message from Command
+ * specifying a physical device to enable or disable.  The CONTROLVM
+ * message handler calls parahotplug_process_message, which then adds
+ * the message to a global list and kicks off a udev event which
+ * causes a user level script to enable or disable the specified
+ * device.  The udev script then writes to
+ * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write
+ * to get called, at which point the appropriate CONTROLVM message is
+ * retrieved from the list and responded to.
+ */
+
+#define PARAHOTPLUG_TIMEOUT_MS 2000
+
+/*
+ * Generate unique int to match an outstanding CONTROLVM message with a
+ * udev script /proc response
+ */
+static int
+parahotplug_next_id(void)
+{
+       static atomic_t id = ATOMIC_INIT(0);
+       return atomic_inc_return(&id);
+}
+
+/*
+ * Returns the time (in jiffies) when a CONTROLVM message on the list
+ * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future
+ */
+static unsigned long
+parahotplug_next_expiration(void)
+{
+       return jiffies + PARAHOTPLUG_TIMEOUT_MS * HZ / 1000;
+}
+
+/*
+ * Create a parahotplug_request, which is basically a wrapper for a
+ * CONTROLVM_MESSAGE that we can stick on a list
+ */
+static struct parahotplug_request *
+parahotplug_request_create(CONTROLVM_MESSAGE *msg)
+{
+       struct parahotplug_request *req =
+           kmalloc(sizeof(struct parahotplug_request),
+                   GFP_KERNEL|__GFP_NORETRY);
+       if (req == NULL)
+               return NULL;
+
+       req->id = parahotplug_next_id();
+       req->expiration = parahotplug_next_expiration();
+       req->msg = *msg;
+
+       return req;
+}
+
+/*
+ * Free a parahotplug_request.
+ */
+static void
+parahotplug_request_destroy(struct parahotplug_request *req)
+{
+       kfree(req);
+}
+
+/*
+ * Cause uevent to run the user level script to do the disable/enable
+ * specified in (the CONTROLVM message in) the specified
+ * parahotplug_request
+ */
+static void
+parahotplug_request_kickoff(struct parahotplug_request *req)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &req->msg.cmd;
+       char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
+           env_func[40];
+       char *envp[] = {
+               env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
+       };
+
+       sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
+       sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
+       sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
+               cmd->deviceChangeState.state.Active);
+       sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
+               cmd->deviceChangeState.busNo);
+       sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
+               cmd->deviceChangeState.devNo >> 3);
+       sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
+               cmd->deviceChangeState.devNo & 0x7);
+
+       LOGINF("parahotplug_request_kickoff: state=%d, bdf=%d/%d/%d, id=%u\n",
+              cmd->deviceChangeState.state.Active,
+              cmd->deviceChangeState.busNo, cmd->deviceChangeState.devNo >> 3,
+              cmd->deviceChangeState.devNo & 7, req->id);
+
+       kobject_uevent_env(&Visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
+                          envp);
+}
+
+/*
+ * Remove any request from the list that's been on there too long and
+ * respond with an error.
+ */
+static void
+parahotplug_process_list(void)
+{
+       struct list_head *pos = NULL;
+       struct list_head *tmp = NULL;
+
+       spin_lock(&Parahotplug_request_list_lock);
+
+       list_for_each_safe(pos, tmp, &Parahotplug_request_list) {
+               struct parahotplug_request *req =
+                   list_entry(pos, struct parahotplug_request, list);
+               if (time_after_eq(jiffies, req->expiration)) {
+                       list_del(pos);
+                       if (req->msg.hdr.Flags.responseExpected)
+                               controlvm_respond_physdev_changestate(
+                                       &req->msg.hdr,
+                                       CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
+                                       req->msg.cmd.deviceChangeState.state);
+                       parahotplug_request_destroy(req);
+               }
+       }
+
+       spin_unlock(&Parahotplug_request_list_lock);
+}
+
+/*
+ * Called from the /proc handler, which means the user script has
+ * finished the enable/disable.  Find the matching identifier, and
+ * respond to the CONTROLVM message with success.
+ */
+static int
+parahotplug_request_complete(int id, U16 active)
+{
+       struct list_head *pos = NULL;
+       struct list_head *tmp = NULL;
+
+       spin_lock(&Parahotplug_request_list_lock);
+
+       /* Look for a request matching "id". */
+       list_for_each_safe(pos, tmp, &Parahotplug_request_list) {
+               struct parahotplug_request *req =
+                   list_entry(pos, struct parahotplug_request, list);
+               if (req->id == id) {
+                       /* Found a match.  Remove it from the list and
+                        * respond.
+                        */
+                       list_del(pos);
+                       spin_unlock(&Parahotplug_request_list_lock);
+                       req->msg.cmd.deviceChangeState.state.Active = active;
+                       if (req->msg.hdr.Flags.responseExpected)
+                               controlvm_respond_physdev_changestate(
+                                       &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
+                                       req->msg.cmd.deviceChangeState.state);
+                       parahotplug_request_destroy(req);
+                       return 0;
+               }
+       }
+
+       spin_unlock(&Parahotplug_request_list_lock);
+       return -1;
+}
+
+/*
+ * Enables or disables a PCI device by kicking off a udev script
+ */
+void
+parahotplug_process_message(CONTROLVM_MESSAGE *inmsg)
+{
+       struct parahotplug_request *req;
+
+       req = parahotplug_request_create(inmsg);
+
+       if (req == NULL) {
+               LOGERR("parahotplug_process_message: couldn't allocate request");
+               return;
+       }
+
+       if (inmsg->cmd.deviceChangeState.state.Active) {
+               /* For enable messages, just respond with success
+               * right away.  This is a bit of a hack, but there are
+               * issues with the early enable messages we get (with
+               * either the udev script not detecting that the device
+               * is up, or not getting called at all).  Fortunately
+               * the messages that get lost don't matter anyway, as
+               * devices are automatically enabled at
+               * initialization.
+               */
+               parahotplug_request_kickoff(req);
+               controlvm_respond_physdev_changestate(&inmsg->hdr,
+                                                     CONTROLVM_RESP_SUCCESS,
+                                                     inmsg->cmd.
+                                                     deviceChangeState.state);
+               parahotplug_request_destroy(req);
+       } else {
+               /* For disable messages, add the request to the
+               * request list before kicking off the udev script.  It
+               * won't get responded to until the script has
+               * indicated it's done.
+               */
+               spin_lock(&Parahotplug_request_list_lock);
+               list_add_tail(&(req->list), &Parahotplug_request_list);
+               spin_unlock(&Parahotplug_request_list_lock);
+
+               parahotplug_request_kickoff(req);
+       }
+}
+
+/*
+ * Gets called when the udev script writes to
+ * /proc/visorchipset/parahotplug.  Expects input in the form of "<id>
+ * <active>" where <id> is the identifier passed to the script that
+ * matches a request on the request list, and <active> is 0 or 1
+ * indicating whether the device is now enabled or not.
+ */
+static ssize_t
+parahotplug_proc_write(struct file *file, const char __user *buffer,
+                      size_t count, loff_t *ppos)
+{
+       char buf[64];
+       uint id;
+       ushort active;
+
+       if (count > sizeof(buf) - 1) {
+               LOGERR("parahotplug_proc_write: count (%d) exceeds size of buffer (%d)",
+                    (int) count, (int) sizeof(buf));
+               return -EINVAL;
+       }
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("parahotplug_proc_write: copy_from_user failed");
+               return -EFAULT;
+       }
+       buf[count] = '\0';
+
+       if (sscanf(buf, "%u %hu", &id, &active) != 2) {
+               id = 0;
+               active = 0;
+       }
+
+       if (active != 1 && active != 0) {
+               LOGERR("parahotplug_proc_write: invalid active field");
+               return -EINVAL;
+       }
+
+       parahotplug_request_complete((int) id, (U16) active);
+
+       return count;
+}
+
+static const struct file_operations parahotplug_proc_fops = {
+       .owner = THIS_MODULE,
+       .read = visorchipset_proc_read_writeonly,
+       .write = parahotplug_proc_write,
+};
+
+/* Process a controlvm message.
+ * Return result:
+ *    FALSE - this function will return FALSE only in the case where the
+ *            controlvm message was NOT processed, but processing must be
+ *            retried before reading the next controlvm message; a
+ *            scenario where this can occur is when we need to throttle
+ *            the allocation of memory in which to copy out controlvm
+ *            payload data
+ *    TRUE  - processing of the controlvm message completed,
+ *            either successfully or with an error.
+ */
+static BOOL
+handle_command(CONTROLVM_MESSAGE inmsg, HOSTADDRESS channel_addr)
+{
+       CONTROLVM_MESSAGE_PACKET *cmd = &inmsg.cmd;
+       U64 parametersAddr = 0;
+       U32 parametersBytes = 0;
+       PARSER_CONTEXT *parser_ctx = NULL;
+       BOOL isLocalAddr = FALSE;
+       CONTROLVM_MESSAGE ackmsg;
+
+       /* create parsing context if necessary */
+       isLocalAddr = (inmsg.hdr.Flags.testMessage == 1);
+       if (channel_addr == 0) {
+               LOGERR("HUH? channel_addr is 0!");
+               return TRUE;
+       }
+       parametersAddr = channel_addr + inmsg.hdr.PayloadVmOffset;
+       parametersBytes = inmsg.hdr.PayloadBytes;
+
+       /* Parameter and channel addresses within test messages actually lie
+        * within our OS-controlled memory.  We need to know that, because it
+        * makes a difference in how we compute the virtual address.
+        */
+       if (parametersAddr != 0 && parametersBytes != 0) {
+               BOOL retry = FALSE;
+               parser_ctx =
+                   parser_init_byteStream(parametersAddr, parametersBytes,
+                                          isLocalAddr, &retry);
+               if (!parser_ctx) {
+                       if (retry) {
+                               LOGWRN("throttling to copy payload");
+                               return FALSE;
+                       }
+                       LOGWRN("parsing failed");
+                       LOGWRN("inmsg.hdr.Id=0x%lx", (ulong) inmsg.hdr.Id);
+                       LOGWRN("parametersAddr=0x%llx", (u64) parametersAddr);
+                       LOGWRN("parametersBytes=%lu", (ulong) parametersBytes);
+                       LOGWRN("isLocalAddr=%d", isLocalAddr);
+               }
+       }
+
+       if (!isLocalAddr) {
+               controlvm_init_response(&ackmsg, &inmsg.hdr,
+                                       CONTROLVM_RESP_SUCCESS);
+               if ((ControlVm_channel)
+                   &&
+                   (!visorchannel_signalinsert
+                    (ControlVm_channel, CONTROLVM_QUEUE_ACK, &ackmsg)))
+                       LOGWRN("failed to send ACK failed");
+       }
+       switch (inmsg.hdr.Id) {
+       case CONTROLVM_CHIPSET_INIT:
+               LOGINF("CHIPSET_INIT(#busses=%lu,#switches=%lu)",
+                      (ulong) inmsg.cmd.initChipset.busCount,
+                      (ulong) inmsg.cmd.initChipset.switchCount);
+               chipset_init(&inmsg);
+               break;
+       case CONTROLVM_BUS_CREATE:
+               LOGINF("BUS_CREATE(%lu,#devs=%lu)",
+                      (ulong) cmd->createBus.busNo,
+                      (ulong) cmd->createBus.deviceCount);
+               bus_create(&inmsg);
+               break;
+       case CONTROLVM_BUS_DESTROY:
+               LOGINF("BUS_DESTROY(%lu)", (ulong) cmd->destroyBus.busNo);
+               bus_destroy(&inmsg);
+               break;
+       case CONTROLVM_BUS_CONFIGURE:
+               LOGINF("BUS_CONFIGURE(%lu)", (ulong) cmd->configureBus.busNo);
+               bus_configure(&inmsg, parser_ctx);
+               break;
+       case CONTROLVM_DEVICE_CREATE:
+               LOGINF("DEVICE_CREATE(%lu,%lu)",
+                      (ulong) cmd->createDevice.busNo,
+                      (ulong) cmd->createDevice.devNo);
+               my_device_create(&inmsg);
+               break;
+       case CONTROLVM_DEVICE_CHANGESTATE:
+               if (cmd->deviceChangeState.flags.physicalDevice) {
+                       LOGINF("DEVICE_CHANGESTATE for physical device (%lu,%lu, active=%lu)",
+                            (ulong) cmd->deviceChangeState.busNo,
+                            (ulong) cmd->deviceChangeState.devNo,
+                            (ulong) cmd->deviceChangeState.state.Active);
+                       parahotplug_process_message(&inmsg);
+               } else {
+                       LOGINF("DEVICE_CHANGESTATE for virtual device (%lu,%lu, state.Alive=0x%lx)",
+                            (ulong) cmd->deviceChangeState.busNo,
+                            (ulong) cmd->deviceChangeState.devNo,
+                            (ulong) cmd->deviceChangeState.state.Alive);
+                       /* save the hdr and cmd structures for later use */
+                       /* when sending back the response to Command */
+                       my_device_changestate(&inmsg);
+                       g_DiagMsgHdr = inmsg.hdr;
+                       g_DeviceChangeStatePacket = inmsg.cmd;
+                       break;
+               }
+               break;
+       case CONTROLVM_DEVICE_DESTROY:
+               LOGINF("DEVICE_DESTROY(%lu,%lu)",
+                      (ulong) cmd->destroyDevice.busNo,
+                      (ulong) cmd->destroyDevice.devNo);
+               my_device_destroy(&inmsg);
+               break;
+       case CONTROLVM_DEVICE_CONFIGURE:
+               LOGINF("DEVICE_CONFIGURE(%lu,%lu)",
+                      (ulong) cmd->configureDevice.busNo,
+                      (ulong) cmd->configureDevice.devNo);
+               /* no op for now, just send a respond that we passed */
+               if (inmsg.hdr.Flags.responseExpected)
+                       controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
+               break;
+       case CONTROLVM_CHIPSET_READY:
+               LOGINF("CHIPSET_READY");
+               chipset_ready(&inmsg.hdr);
+               break;
+       case CONTROLVM_CHIPSET_SELFTEST:
+               LOGINF("CHIPSET_SELFTEST");
+               chipset_selftest(&inmsg.hdr);
+               break;
+       case CONTROLVM_CHIPSET_STOP:
+               LOGINF("CHIPSET_STOP");
+               chipset_notready(&inmsg.hdr);
+               break;
+       default:
+               LOGERR("unrecognized controlvm cmd=%d", (int) inmsg.hdr.Id);
+               if (inmsg.hdr.Flags.responseExpected)
+                       controlvm_respond(&inmsg.hdr,
+                                         -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
+               break;
+       }
+
+       if (parser_ctx != NULL) {
+               parser_done(parser_ctx);
+               parser_ctx = NULL;
+       }
+       return TRUE;
+}
+
+static void
+controlvm_periodic_work(struct work_struct *work)
+{
+       VISORCHIPSET_CHANNEL_INFO chanInfo;
+       CONTROLVM_MESSAGE inmsg;
+       char s[99];
+       BOOL gotACommand = FALSE;
+       BOOL handle_command_failed = FALSE;
+       static U64 Poll_Count;
+
+       /* make sure visorbus server is registered for controlvm callbacks */
+       if (visorchipset_serverregwait && !serverregistered)
+               RETVOID;
+       /* make sure visorclientbus server is regsitered for controlvm
+        * callbacks
+        */
+       if (visorchipset_clientregwait && !clientregistered)
+               RETVOID;
+
+       memset(&chanInfo, 0, sizeof(VISORCHIPSET_CHANNEL_INFO));
+       if (!ControlVm_channel) {
+               HOSTADDRESS addr = controlvm_get_channel_address();
+               if (addr != 0) {
+                       ControlVm_channel =
+                           visorchannel_create_with_lock
+                           (addr,
+                            sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL),
+                            UltraControlvmChannelProtocolGuid);
+                       if (ControlVm_channel == NULL)
+                               LOGERR("failed to create controlvm channel");
+                       else if (ULTRA_CONTROLVM_CHANNEL_OK_CLIENT
+                                (visorchannel_get_header(ControlVm_channel),
+                                 NULL)) {
+                               LOGINF("Channel %s (ControlVm) discovered",
+                                      visorchannel_id(ControlVm_channel, s));
+                               initialize_controlvm_payload();
+                       } else {
+                               LOGERR("controlvm channel is invalid");
+                               visorchannel_destroy(ControlVm_channel);
+                               ControlVm_channel = NULL;
+                       }
+               }
+       }
+
+       Poll_Count++;
+       if ((ControlVm_channel != NULL) || (Poll_Count >= 250))
+               ;       /* keep going */
+       else
+               RETVOID;
+
+       /* Check events to determine if response to CHIPSET_READY
+        * should be sent
+        */
+       if (visorchipset_holdchipsetready
+           && (g_ChipSetMsgHdr.Id != CONTROLVM_INVALID)) {
+               if (check_chipset_events() == 1) {
+                       LOGINF("Sending CHIPSET_READY response");
+                       controlvm_respond(&g_ChipSetMsgHdr, 0);
+                       clear_chipset_events();
+                       memset(&g_ChipSetMsgHdr, 0,
+                              sizeof(CONTROLVM_MESSAGE_HEADER));
+               }
+       }
+
+       if (ControlVm_channel) {
+               while (visorchannel_signalremove(ControlVm_channel,
+                                                CONTROLVM_QUEUE_RESPONSE,
+                                                &inmsg)) {
+                       if (inmsg.hdr.PayloadMaxBytes != 0) {
+                               LOGERR("Payload of size %lu returned @%lu with unexpected message id %d.",
+                                    (ulong) inmsg.hdr.PayloadMaxBytes,
+                                    (ulong) inmsg.hdr.PayloadVmOffset,
+                                    inmsg.hdr.Id);
+                       }
+               }
+               if (!gotACommand) {
+                       if (ControlVm_Pending_Msg_Valid) {
+                               /* we throttled processing of a prior
+                               * msg, so try to process it again
+                               * rather than reading a new one
+                               */
+                               inmsg = ControlVm_Pending_Msg;
+                               ControlVm_Pending_Msg_Valid = FALSE;
+                               gotACommand = TRUE;
+                       } else
+                               gotACommand = read_controlvm_event(&inmsg);
+               }
+       }
+
+       handle_command_failed = FALSE;
+       while (gotACommand && (!handle_command_failed)) {
+               Most_recent_message_jiffies = jiffies;
+               if (ControlVm_channel) {
+                       if (handle_command(inmsg,
+                                          visorchannel_get_physaddr
+                                          (ControlVm_channel)))
+                               gotACommand = read_controlvm_event(&inmsg);
+                       else {
+                               /* this is a scenario where throttling
+                               * is required, but probably NOT an
+                               * error...; we stash the current
+                               * controlvm msg so we will attempt to
+                               * reprocess it on our next loop
+                               */
+                               handle_command_failed = TRUE;
+                               ControlVm_Pending_Msg = inmsg;
+                               ControlVm_Pending_Msg_Valid = TRUE;
+                       }
+
+               } else {
+                       handle_command(inmsg, 0);
+                       gotACommand = FALSE;
+               }
+       }
+
+       /* parahotplug_worker */
+       parahotplug_process_list();
+
+       RETVOID;
+
+Away:
+
+       if (time_after(jiffies,
+                      Most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
+               /* it's been longer than MIN_IDLE_SECONDS since we
+               * processed our last controlvm message; slow down the
+               * polling
+               */
+               if (Poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) {
+                       LOGINF("switched to slow controlvm polling");
+                       Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+               }
+       } else {
+               if (Poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) {
+                       Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+                       LOGINF("switched to fast controlvm polling");
+               }
+       }
+
+       if (queue_delayed_work(Periodic_controlvm_workqueue,
+                              &Periodic_controlvm_work, Poll_jiffies) < 0) {
+               LOGERR("queue_delayed_work failed!");
+               POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, POSTCODE_SEVERITY_ERR);
+       }
+}
+
+static void
+setup_crash_devices_work_queue(struct work_struct *work)
+{
+
+       CONTROLVM_MESSAGE localCrashCreateBusMsg;
+       CONTROLVM_MESSAGE localCrashCreateDevMsg;
+       CONTROLVM_MESSAGE msg;
+       HOSTADDRESS host_addr;
+       U32 localSavedCrashMsgOffset;
+       U16 localSavedCrashMsgCount;
+
+       /* make sure visorbus server is registered for controlvm callbacks */
+       if (visorchipset_serverregwait && !serverregistered)
+               RETVOID;
+
+       /* make sure visorclientbus server is regsitered for controlvm
+        * callbacks
+        */
+       if (visorchipset_clientregwait && !clientregistered)
+               RETVOID;
+
+       POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+       /* send init chipset msg */
+       msg.hdr.Id = CONTROLVM_CHIPSET_INIT;
+       msg.cmd.initChipset.busCount = 23;
+       msg.cmd.initChipset.switchCount = 0;
+
+       chipset_init(&msg);
+
+       host_addr = controlvm_get_channel_address();
+       if (!host_addr) {
+               LOGERR("Huh?  Host address is NULL");
+               POSTCODE_LINUX_2(CRASH_DEV_HADDR_NULL, POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       ControlVm_channel =
+           visorchannel_create_with_lock
+           (host_addr,
+            sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL),
+            UltraControlvmChannelProtocolGuid);
+
+       if (ControlVm_channel == NULL) {
+               LOGERR("failed to create controlvm channel");
+               POSTCODE_LINUX_2(CRASH_DEV_CONTROLVM_NULL,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* get saved message count */
+       if (visorchannel_read(ControlVm_channel,
+                             offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                      SavedCrashMsgCount),
+                             &localSavedCrashMsgCount, sizeof(U16)) < 0) {
+               LOGERR("failed to get Saved Message Count");
+               POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       if (localSavedCrashMsgCount != CONTROLVM_CRASHMSG_MAX) {
+               LOGERR("Saved Message Count incorrect %d",
+                      localSavedCrashMsgCount);
+               POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
+                                localSavedCrashMsgCount,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* get saved crash message offset */
+       if (visorchannel_read(ControlVm_channel,
+                             offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                      SavedCrashMsgOffset),
+                             &localSavedCrashMsgOffset, sizeof(U32)) < 0) {
+               LOGERR("failed to get Saved Message Offset");
+               POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* read create device message for storage bus offset */
+       if (visorchannel_read(ControlVm_channel,
+                             localSavedCrashMsgOffset,
+                             &localCrashCreateBusMsg,
+                             sizeof(CONTROLVM_MESSAGE)) < 0) {
+               LOGERR("CRASH_DEV_RD_BUS_FAIULRE: Failed to read CrashCreateBusMsg!");
+               POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* read create device message for storage device */
+       if (visorchannel_read(ControlVm_channel,
+                             localSavedCrashMsgOffset +
+                             sizeof(CONTROLVM_MESSAGE),
+                             &localCrashCreateDevMsg,
+                             sizeof(CONTROLVM_MESSAGE)) < 0) {
+               LOGERR("CRASH_DEV_RD_DEV_FAIULRE: Failed to read CrashCreateDevMsg!");
+               POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* reuse IOVM create bus message */
+       if (localCrashCreateBusMsg.cmd.createBus.channelAddr != 0)
+               bus_create(&localCrashCreateBusMsg);
+       else {
+               LOGERR("CrashCreateBusMsg is null, no dump will be taken");
+               POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+
+       /* reuse create device message for storage device */
+       if (localCrashCreateDevMsg.cmd.createDevice.channelAddr != 0)
+               my_device_create(&localCrashCreateDevMsg);
+       else {
+               LOGERR("CrashCreateDevMsg is null, no dump will be taken");
+               POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
+                                POSTCODE_SEVERITY_ERR);
+               return;
+       }
+       LOGINF("Bus and device ready for dumping");
+       POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       return;
+
+Away:
+
+       Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+
+       if (queue_delayed_work(Periodic_controlvm_workqueue,
+                              &Periodic_controlvm_work, Poll_jiffies) < 0) {
+               LOGERR("queue_delayed_work failed!");
+               POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, POSTCODE_SEVERITY_ERR);
+       }
+}
+
+static void
+bus_create_response(ulong busNo, int response)
+{
+       bus_responder(CONTROLVM_BUS_CREATE, busNo, response);
+}
+
+static void
+bus_destroy_response(ulong busNo, int response)
+{
+       bus_responder(CONTROLVM_BUS_DESTROY, busNo, response);
+}
+
+static void
+device_create_response(ulong busNo, ulong devNo, int response)
+{
+       device_responder(CONTROLVM_DEVICE_CREATE, busNo, devNo, response);
+}
+
+static void
+device_destroy_response(ulong busNo, ulong devNo, int response)
+{
+       device_responder(CONTROLVM_DEVICE_DESTROY, busNo, devNo, response);
+}
+
+void
+device_pause_response(ulong busNo, ulong devNo, int response)
+{
+
+       device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
+                                    busNo, devNo, response,
+                                    SegmentStateStandby);
+}
+EXPORT_SYMBOL_GPL(device_pause_response);
+
+static void
+device_resume_response(ulong busNo, ulong devNo, int response)
+{
+       device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
+                                    busNo, devNo, response,
+                                    SegmentStateRunning);
+}
+
+BOOL
+visorchipset_get_bus_info(ulong busNo, VISORCHIPSET_BUS_INFO *busInfo)
+{
+       void *p = findbus(&BusInfoList, busNo);
+       if (!p) {
+               LOGERR("(%lu) failed", busNo);
+               return FALSE;
+       }
+       memcpy(busInfo, p, sizeof(VISORCHIPSET_BUS_INFO));
+       return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_get_bus_info);
+
+BOOL
+visorchipset_set_bus_context(ulong busNo, void *context)
+{
+       VISORCHIPSET_BUS_INFO *p = findbus(&BusInfoList, busNo);
+       if (!p) {
+               LOGERR("(%lu) failed", busNo);
+               return FALSE;
+       }
+       p->bus_driver_context = context;
+       return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_set_bus_context);
+
+BOOL
+visorchipset_get_device_info(ulong busNo, ulong devNo,
+                            VISORCHIPSET_DEVICE_INFO *devInfo)
+{
+       void *p = finddevice(&DevInfoList, busNo, devNo);
+       if (!p) {
+               LOGERR("(%lu,%lu) failed", busNo, devNo);
+               return FALSE;
+       }
+       memcpy(devInfo, p, sizeof(VISORCHIPSET_DEVICE_INFO));
+       return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_get_device_info);
+
+BOOL
+visorchipset_set_device_context(ulong busNo, ulong devNo, void *context)
+{
+       VISORCHIPSET_DEVICE_INFO *p = finddevice(&DevInfoList, busNo, devNo);
+       if (!p) {
+               LOGERR("(%lu,%lu) failed", busNo, devNo);
+               return FALSE;
+       }
+       p->bus_driver_context = context;
+       return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_set_device_context);
+
+/* Generic wrapper function for allocating memory from a kmem_cache pool.
+ */
+void *
+visorchipset_cache_alloc(struct kmem_cache *pool, BOOL ok_to_block,
+                        char *fn, int ln)
+{
+       gfp_t gfp;
+       void *p;
+
+       if (ok_to_block)
+               gfp = GFP_KERNEL;
+       else
+               gfp = GFP_ATOMIC;
+       /* __GFP_NORETRY means "ok to fail", meaning
+        * kmem_cache_alloc() can return NULL, implying the caller CAN
+        * cope with failure.  If you do NOT specify __GFP_NORETRY,
+        * Linux will go to extreme measures to get memory for you
+        * (like, invoke oom killer), which will probably cripple the
+        * system.
+        */
+       gfp |= __GFP_NORETRY;
+       p = kmem_cache_alloc(pool, gfp);
+       if (!p) {
+               LOGERR("kmem_cache_alloc failed early @%s:%d\n", fn, ln);
+               return NULL;
+       }
+       atomic_inc(&Visorchipset_cache_buffers_in_use);
+       return p;
+}
+
+/* Generic wrapper function for freeing memory from a kmem_cache pool.
+ */
+void
+visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln)
+{
+       if (!p) {
+               LOGERR("NULL pointer @%s:%d\n", fn, ln);
+               return;
+       }
+       atomic_dec(&Visorchipset_cache_buffers_in_use);
+       kmem_cache_free(pool, p);
+}
+
+#define gettoken(bufp) strsep(bufp, " -\t\n")
+
+static ssize_t
+chipset_proc_write(struct file *file, const char __user *buffer,
+                  size_t count, loff_t *ppos)
+{
+       char buf[512];
+       char *token, *p;
+
+       if (count > sizeof(buf) - 1) {
+               LOGERR("chipset_proc_write: count (%d) exceeds size of buffer (%d)",
+                    (int) count, (int) sizeof(buffer));
+               return -EINVAL;
+       }
+       if (copy_from_user(buf, buffer, count)) {
+               LOGERR("chipset_proc_write: copy_from_user failed");
+               return -EFAULT;
+       }
+       buf[count] = '\0';
+
+       p = buf;
+       token = gettoken(&p);
+
+       if (strcmp(token, "CALLHOMEDISK_MOUNTED") == 0) {
+               token = gettoken(&p);
+               /* The Call Home Disk has been mounted */
+               if (strcmp(token, "0") == 0)
+                       chipset_events[0] = 1;
+       } else if (strcmp(token, "MODULES_LOADED") == 0) {
+               token = gettoken(&p);
+               /* All modules for the partition have been loaded */
+               if (strcmp(token, "0") == 0)
+                       chipset_events[1] = 1;
+       } else if (token == NULL) {
+               /* No event specified */
+               LOGERR("No event was specified to send CHIPSET_READY response");
+               return -1;
+       } else {
+               /* Unsupported event specified */
+               LOGERR("%s is an invalid event for sending CHIPSET_READY response",                  token);
+               return -1;
+       }
+
+       return count;
+}
+
+static ssize_t
+visorchipset_proc_read_writeonly(struct file *file, char __user *buf,
+                                size_t len, loff_t *offset)
+{
+       return 0;
+}
+
+/**
+ * Reads the InstallationError, InstallationTextId,
+ * InstallationRemainingSteps fields of ControlVMChannel.
+ */
+static ssize_t
+proc_read_installer(struct file *file, char __user *buf,
+                   size_t len, loff_t *offset)
+{
+       int length = 0;
+       U16 remainingSteps;
+       U32 error, textId;
+       char *vbuf;
+       loff_t pos = *offset;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos > 0 || !len)
+               return 0;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       visorchannel_read(ControlVm_channel,
+                         offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                  InstallationRemainingSteps), &remainingSteps,
+                         sizeof(U16));
+       visorchannel_read(ControlVm_channel,
+                         offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                  InstallationError), &error, sizeof(U32));
+       visorchannel_read(ControlVm_channel,
+                         offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                  InstallationTextId), &textId, sizeof(U32));
+
+       length = sprintf(vbuf, "%u %u %u\n", remainingSteps, error, textId);
+       if (copy_to_user(buf, vbuf, length)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+
+       kfree(vbuf);
+       *offset += length;
+       return length;
+}
+
+/**
+ * Writes to the InstallationError, InstallationTextId,
+ * InstallationRemainingSteps fields of
+ * ControlVMChannel.
+ * Input: RemainingSteps Error TextId
+ * Limit 32 characters input
+ */
+#define UINT16_MAX             (65535U)
+#define UINT32_MAX             (4294967295U)
+static ssize_t
+proc_write_installer(struct file *file,
+                    const char __user *buffer, size_t count, loff_t *ppos)
+{
+       char buf[32];
+       U16 remainingSteps;
+       U32 error, textId;
+
+       /* Check to make sure there is no buffer overflow */
+       if (count > (sizeof(buf) - 1))
+               return -EINVAL;
+
+       if (copy_from_user(buf, buffer, count)) {
+               WARN(1, "Error copying from user space\n");
+               return -EFAULT;
+       }
+
+       if (sscanf(buf, "%hu %i %i", &remainingSteps, &error, &textId) != 3) {
+               remainingSteps = UINT16_MAX;
+               error = UINT32_MAX;
+               textId = UINT32_MAX;
+       }
+
+       if (remainingSteps != UINT16_MAX) {
+               if (visorchannel_write
+                   (ControlVm_channel,
+                    offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                             InstallationRemainingSteps), &remainingSteps,
+                    sizeof(U16)) < 0)
+                       WARN(1, "Installation Status Write Failed - Write function error - RemainingSteps = %d\n",
+                            remainingSteps);
+       }
+
+       if (error != UINT32_MAX) {
+               if (visorchannel_write
+                   (ControlVm_channel,
+                    offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                             InstallationError), &error, sizeof(U32)) < 0)
+                       WARN(1, "Installation Status Write Failed - Write function error - Error = %d\n",
+                            error);
+       }
+
+       if (textId != UINT32_MAX) {
+               if (visorchannel_write
+                   (ControlVm_channel,
+                    offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                             InstallationTextId), &textId, sizeof(U32)) < 0)
+                       WARN(1, "Installation Status Write Failed - Write function error - TextId = %d\n",
+                            textId);
+       }
+
+       /* So this function isn't called multiple times, must return
+        * size of buffer
+        */
+       return count;
+}
+
+/**
+ * Reads the ToolAction field of ControlVMChannel.
+ */
+static ssize_t
+proc_read_toolaction(struct file *file, char __user *buf,
+                    size_t len, loff_t *offset)
+{
+       int length = 0;
+       U8 toolAction;
+       char *vbuf;
+       loff_t pos = *offset;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos > 0 || !len)
+               return 0;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       visorchannel_read(ControlVm_channel,
+                         offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                  ToolAction), &toolAction, sizeof(U8));
+
+       length = sprintf(vbuf, "%u\n", toolAction);
+       if (copy_to_user(buf, vbuf, length)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+
+       kfree(vbuf);
+       *offset += length;
+       return length;
+}
+
+/**
+ * Writes to the ToolAction field of ControlVMChannel.
+ * Input: ToolAction
+ * Limit 3 characters input
+ */
+#define UINT8_MAX (255U)
+static ssize_t
+proc_write_toolaction(struct file *file,
+                     const char __user *buffer, size_t count, loff_t *ppos)
+{
+       char buf[3];
+       U8 toolAction;
+
+       /* Check to make sure there is no buffer overflow */
+       if (count > (sizeof(buf) - 1))
+               return -EINVAL;
+
+       if (copy_from_user(buf, buffer, count)) {
+               WARN(1, "Error copying from user space\n");
+               return -EFAULT;
+       }
+
+       if (sscanf(buf, "%hhd", &toolAction) != 1)
+               toolAction = UINT8_MAX;
+
+       if (toolAction != UINT8_MAX) {
+               if (visorchannel_write
+                   (ControlVm_channel,
+                    offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, ToolAction),
+                    &toolAction, sizeof(U8)) < 0)
+                       WARN(1, "Installation ToolAction Write Failed - ToolAction = %d\n",
+                            toolAction);
+       }
+
+       /* So this function isn't called multiple times, must return
+        * size of buffer
+        */
+       return count;
+}
+
+/**
+ * Reads the EfiSparIndication.BootToTool field of ControlVMChannel.
+ */
+static ssize_t
+proc_read_bootToTool(struct file *file, char __user *buf,
+                    size_t len, loff_t *offset)
+{
+       int length = 0;
+       ULTRA_EFI_SPAR_INDICATION efiSparIndication;
+       char *vbuf;
+       loff_t pos = *offset;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos > 0 || !len)
+               return 0;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       visorchannel_read(ControlVm_channel,
+                         offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+                                  EfiSparIndication), &efiSparIndication,
+                         sizeof(ULTRA_EFI_SPAR_INDICATION));
+
+       length = sprintf(vbuf, "%d\n", (int) efiSparIndication.BootToTool);
+       if (copy_to_user(buf, vbuf, length)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+
+       kfree(vbuf);
+       *offset += length;
+       return length;
+}
+
+/**
+ * Writes to the EfiSparIndication.BootToTool field of ControlVMChannel.
+ * Input: 1 or 0 (1 being on, 0 being off)
+ */
+static ssize_t
+proc_write_bootToTool(struct file *file,
+                     const char __user *buffer, size_t count, loff_t *ppos)
+{
+       char buf[3];
+       int inputVal;
+       ULTRA_EFI_SPAR_INDICATION efiSparIndication;
+
+       /* Check to make sure there is no buffer overflow */
+       if (count > (sizeof(buf) - 1))
+               return -EINVAL;
+
+       if (copy_from_user(buf, buffer, count)) {
+               WARN(1, "Error copying from user space\n");
+               return -EFAULT;
+       }
+
+       if (sscanf(buf, "%i", &inputVal) != 1)
+               inputVal = 0;
+
+       efiSparIndication.BootToTool = (inputVal == 1 ? 1 : 0);
+
+       if (visorchannel_write
+           (ControlVm_channel,
+            offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EfiSparIndication),
+            &efiSparIndication, sizeof(ULTRA_EFI_SPAR_INDICATION)) < 0)
+               printk
+                   ("Installation BootToTool Write Failed - BootToTool = %d\n",
+                    (int) efiSparIndication.BootToTool);
+
+       /* So this function isn't called multiple times, must return
+        * size of buffer
+        */
+       return count;
+}
+
+static const struct file_operations chipset_proc_fops = {
+       .owner = THIS_MODULE,
+       .read = visorchipset_proc_read_writeonly,
+       .write = chipset_proc_write,
+};
+
+static int __init
+visorchipset_init(void)
+{
+       int rc = 0, x = 0;
+       struct proc_dir_entry *installer_file;
+       struct proc_dir_entry *toolaction_file;
+       struct proc_dir_entry *bootToTool_file;
+
+       LOGINF("chipset driver version %s loaded", VERSION);
+       /* process module options */
+       POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+       LOGINF("option - testvnic=%d", visorchipset_testvnic);
+       LOGINF("option - testvnicclient=%d", visorchipset_testvnicclient);
+       LOGINF("option - testmsg=%d", visorchipset_testmsg);
+       LOGINF("option - testteardown=%d", visorchipset_testteardown);
+       LOGINF("option - major=%d", visorchipset_major);
+       LOGINF("option - serverregwait=%d", visorchipset_serverregwait);
+       LOGINF("option - clientregwait=%d", visorchipset_clientregwait);
+       LOGINF("option - holdchipsetready=%d", visorchipset_holdchipsetready);
+
+       memset(&BusDev_Server_Notifiers, 0, sizeof(BusDev_Server_Notifiers));
+       memset(&BusDev_Client_Notifiers, 0, sizeof(BusDev_Client_Notifiers));
+       memset(&ControlVm_payload_info, 0, sizeof(ControlVm_payload_info));
+       memset(&LiveDump_info, 0, sizeof(LiveDump_info));
+       atomic_set(&LiveDump_info.buffers_in_use, 0);
+
+       if (visorchipset_testvnic)
+               FAIL_WPOSTCODE_2("testvnic option no longer supported", x,
+                                CHIPSET_INIT_FAILURE_PC, x);
+
+       controlvm_init();
+       MajorDev = MKDEV(visorchipset_major, 0);
+       TRY_WPOSTCODE_1(visorchipset_file_init(MajorDev, &ControlVm_channel),
+                       CHIPSET_INIT_FAILURE_PC);
+       proc_Init();
+       memset(PartitionPropertyNames, 0, sizeof(PartitionPropertyNames));
+       memset(ControlVmPropertyNames, 0, sizeof(ControlVmPropertyNames));
+       InitPartitionProperties();
+       InitControlVmProperties();
+
+       PartitionType = proc_CreateType(ProcDir, PartitionTypeNames,
+                                       (const char **) PartitionPropertyNames,
+                                       &show_partition_property);
+       ControlVmType =
+           proc_CreateType(ProcDir, ControlVmTypeNames,
+                           (const char **) ControlVmPropertyNames,
+                           &show_controlvm_property);
+
+       ControlVmObject = proc_CreateObject(ControlVmType, NULL, NULL);
+
+       /* Setup Installation fields */
+       installer_file = proc_create("installer", 0644, ProcDir,
+                                    &proc_installer_fops);
+       /* Setup the ToolAction field */
+       toolaction_file = proc_create("toolaction", 0644, ProcDir,
+                                     &proc_toolaction_fops);
+       /* Setup the BootToTool field */
+       bootToTool_file = proc_create("boottotool", 0644, ProcDir,
+                                     &proc_bootToTool_fops);
+
+       memset(&g_DiagMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+       chipset_proc_dir = proc_create(VISORCHIPSET_CHIPSET_PROC_ENTRY_FN,
+                                      0644, ProcDir, &chipset_proc_fops);
+       memset(&g_ChipSetMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+       parahotplug_proc_dir =
+           proc_create(VISORCHIPSET_PARAHOTPLUG_PROC_ENTRY_FN, 0200,
+                       ProcDir, &parahotplug_proc_fops);
+       memset(&g_DelDumpMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+       if (filexfer_constructor(sizeof(struct putfile_request)) < 0) {
+               FAIL_WPOSTCODE_1("filexfer_constructor failed", -1,
+                                CHIPSET_INIT_FAILURE_PC);
+       }
+       Putfile_buffer_list_pool =
+           kmem_cache_create(Putfile_buffer_list_pool_name,
+                             sizeof(struct putfile_buffer_entry),
+                             0, SLAB_HWCACHE_ALIGN, NULL);
+       if (!Putfile_buffer_list_pool) {
+               FAIL_WPOSTCODE_1("failed to alloc Putfile_buffer_list_pool", -1,
+                                CHIPSET_INIT_FAILURE_PC);
+       }
+       if (visorchipset_disable_controlvm) {
+               LOGINF("visorchipset_init:controlvm disabled");
+       } else {
+               /* if booting in a crash kernel */
+               if (visorchipset_crash_kernel)
+                       INIT_DELAYED_WORK(&Periodic_controlvm_work,
+                                         setup_crash_devices_work_queue);
+               else
+                       INIT_DELAYED_WORK(&Periodic_controlvm_work,
+                                         controlvm_periodic_work);
+               Periodic_controlvm_workqueue =
+                   create_singlethread_workqueue("visorchipset_controlvm");
+
+               if (Periodic_controlvm_workqueue == NULL)
+                       FAIL_WPOSTCODE_1("cannot create controlvm workqueue",
+                                        -ENOMEM, CREATE_WORKQUEUE_FAILED_PC);
+               Most_recent_message_jiffies = jiffies;
+               Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+               TRY_WPOSTCODE_1(queue_delayed_work
+                               (Periodic_controlvm_workqueue,
+                                &Periodic_controlvm_work, Poll_jiffies),
+                               QUEUE_DELAYED_WORK_PC);
+       }
+
+       Visorchipset_platform_device.dev.devt = MajorDev;
+       if (platform_device_register(&Visorchipset_platform_device) < 0)
+               FAIL_WPOSTCODE_1
+                   ("platform_device_register(visorchipset) failed", -1,
+                    DEVICE_REGISTER_FAILURE_PC);
+       LOGINF("visorchipset device created");
+       POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
+       RETINT(0);
+
+Away:
+
+       if (rc) {
+               LOGERR("visorchipset_init failed");
+               POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
+                                POSTCODE_SEVERITY_ERR);
+       }
+       return rc;
+}
+
+static void
+visorchipset_exit(void)
+{
+       char s[99];
+       POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+       if (visorchipset_disable_controlvm) {
+               ;
+       } else {
+               cancel_delayed_work(&Periodic_controlvm_work);
+               flush_workqueue(Periodic_controlvm_workqueue);
+               destroy_workqueue(Periodic_controlvm_workqueue);
+               Periodic_controlvm_workqueue = NULL;
+               destroy_controlvm_payload_info(&ControlVm_payload_info);
+       }
+       Test_Vnic_channel = NULL;
+       if (Putfile_buffer_list_pool) {
+               kmem_cache_destroy(Putfile_buffer_list_pool);
+               Putfile_buffer_list_pool = NULL;
+       }
+       filexfer_destructor();
+       if (ControlVmObject) {
+               proc_DestroyObject(ControlVmObject);
+               ControlVmObject = NULL;
+       }
+       cleanup_controlvm_structures();
+
+       if (ControlVmType) {
+               proc_DestroyType(ControlVmType);
+               ControlVmType = NULL;
+       }
+       if (PartitionType) {
+               proc_DestroyType(PartitionType);
+               PartitionType = NULL;
+       }
+       if (diag_proc_dir) {
+               remove_proc_entry(VISORCHIPSET_DIAG_PROC_ENTRY_FN, ProcDir);
+               diag_proc_dir = NULL;
+       }
+       memset(&g_DiagMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+       if (chipset_proc_dir) {
+               remove_proc_entry(VISORCHIPSET_CHIPSET_PROC_ENTRY_FN, ProcDir);
+               chipset_proc_dir = NULL;
+       }
+       memset(&g_ChipSetMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+       if (parahotplug_proc_dir) {
+               remove_proc_entry(VISORCHIPSET_PARAHOTPLUG_PROC_ENTRY_FN,
+                                 ProcDir);
+               parahotplug_proc_dir = NULL;
+       }
+
+       memset(&g_DelDumpMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+       proc_DeInit();
+       if (ControlVm_channel != NULL) {
+               LOGINF("Channel %s (ControlVm) disconnected",
+                      visorchannel_id(ControlVm_channel, s));
+               visorchannel_destroy(ControlVm_channel);
+               ControlVm_channel = NULL;
+       }
+       controlvm_deinit();
+       visorchipset_file_cleanup();
+       POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
+       LOGINF("chipset driver unloaded");
+}
+
+module_param_named(testvnic, visorchipset_testvnic, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testvnic, "1 to test vnic, using dummy VNIC connected via a loopback to a physical ethernet");
+int visorchipset_testvnic = 0;
+
+module_param_named(testvnicclient, visorchipset_testvnicclient, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testvnicclient, "1 to test vnic, using real VNIC channel attached to a separate IOVM guest");
+int visorchipset_testvnicclient = 0;
+
+module_param_named(testmsg, visorchipset_testmsg, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testmsg,
+                "1 to manufacture the chipset, bus, and switch messages");
+int visorchipset_testmsg = 0;
+
+module_param_named(major, visorchipset_major, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_major, "major device number to use for the device node");
+int visorchipset_major = 0;
+
+module_param_named(serverregwait, visorchipset_serverregwait, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_serverreqwait,
+                "1 to have the module wait for the visor bus to register");
+int visorchipset_serverregwait = 0;    /* default is off */
+module_param_named(clientregwait, visorchipset_clientregwait, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_clientregwait, "1 to have the module wait for the visorclientbus to register");
+int visorchipset_clientregwait = 1;    /* default is on */
+module_param_named(testteardown, visorchipset_testteardown, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testteardown,
+                "1 to test teardown of the chipset, bus, and switch");
+int visorchipset_testteardown = 0;     /* default is off */
+module_param_named(disable_controlvm, visorchipset_disable_controlvm, int,
+                  S_IRUGO);
+MODULE_PARM_DESC(visorchipset_disable_controlvm,
+                "1 to disable polling of controlVm channel");
+int visorchipset_disable_controlvm = 0;        /* default is off */
+module_param_named(crash_kernel, visorchipset_crash_kernel, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_crash_kernel,
+                "1 means we are running in crash kernel");
+int visorchipset_crash_kernel = 0; /* default is running in non-crash kernel */
+module_param_named(holdchipsetready, visorchipset_holdchipsetready,
+                  int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_holdchipsetready,
+                "1 to hold response to CHIPSET_READY");
+int visorchipset_holdchipsetready = 0; /* default is to send CHIPSET_READY
+                                     * response immediately */
+module_init(visorchipset_init);
+module_exit(visorchipset_exit);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver "
+                  VERSION);
+MODULE_VERSION(VERSION);
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_umode.h b/drivers/staging/unisys/visorchipset/visorchipset_umode.h
new file mode 100644 (file)
index 0000000..259e840
--- /dev/null
@@ -0,0 +1,37 @@
+/* visorchipset_umode.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes structures needed for the interface between the
+ *  visorchipset driver and a user-mode component that opens the device.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __VISORCHIPSET_UMODE_H
+#define __VISORCHIPSET_UMODE_H
+
+
+
+/** The user-mode program can access the control channel buffer directly
+ *  via this memory map.
+ */
+#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET    (0x00000000)
+#define VISORCHIPSET_MMAP_CONTROLCHANSIZE      (0x00400000)  /* 4MB */
+
+#endif /* __VISORCHIPSET_UMODE_H */
diff --git a/drivers/staging/unisys/visorutil/Kconfig b/drivers/staging/unisys/visorutil/Kconfig
new file mode 100644 (file)
index 0000000..4ff61a7
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys timskmod configuration
+#
+
+config UNISYS_VISORUTIL
+       tristate "Unisys visorutil driver"
+       depends on UNISYSSPAR
+       ---help---
+       If you say Y here, you will enable the Unisys visorutil driver.
+
diff --git a/drivers/staging/unisys/visorutil/Makefile b/drivers/staging/unisys/visorutil/Makefile
new file mode 100644 (file)
index 0000000..3f46388
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for Unisys timskmod
+#
+
+obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil.o
+
+visorutil-y := charqueue.o  easyproc.o  periodic_work.o  procobjecttree.o  \
+               memregion_direct.o visorkmodutils.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
diff --git a/drivers/staging/unisys/visorutil/charqueue.c b/drivers/staging/unisys/visorutil/charqueue.c
new file mode 100644 (file)
index 0000000..2bce94e
--- /dev/null
@@ -0,0 +1,144 @@
+/* charqueue.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Simple character queue implementation for Linux kernel mode.
+ */
+
+#include "charqueue.h"
+
+#define MYDRVNAME "charqueue"
+
+#define IS_EMPTY(charqueue) (charqueue->head == charqueue->tail)
+
+
+
+struct CHARQUEUE_Tag {
+       int alloc_size;
+       int nslots;
+       spinlock_t lock;
+       int head, tail;
+       unsigned char buf[0];
+};
+
+
+
+CHARQUEUE *charqueue_create(ulong nslots)
+{
+       int alloc_size = sizeof(CHARQUEUE) + nslots + 1;
+       CHARQUEUE *cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);
+       if (cq == NULL) {
+               ERRDRV("charqueue_create allocation failed (alloc_size=%d)",
+                      alloc_size);
+               return NULL;
+       }
+       cq->alloc_size = alloc_size;
+       cq->nslots = nslots;
+       cq->head = cq->tail = 0;
+       spin_lock_init(&cq->lock);
+       return cq;
+}
+EXPORT_SYMBOL_GPL(charqueue_create);
+
+
+
+void charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c)
+{
+       int alloc_slots = charqueue->nslots+1;  /* 1 slot is always empty */
+
+       spin_lock(&charqueue->lock);
+       charqueue->head = (charqueue->head+1) % alloc_slots;
+       if (charqueue->head == charqueue->tail)
+               /* overflow; overwrite the oldest entry */
+               charqueue->tail = (charqueue->tail+1) % alloc_slots;
+       charqueue->buf[charqueue->head] = c;
+       spin_unlock(&charqueue->lock);
+}
+EXPORT_SYMBOL_GPL(charqueue_enqueue);
+
+
+
+BOOL charqueue_is_empty(CHARQUEUE *charqueue)
+{
+       BOOL b;
+       spin_lock(&charqueue->lock);
+       b = IS_EMPTY(charqueue);
+       spin_unlock(&charqueue->lock);
+       return b;
+}
+EXPORT_SYMBOL_GPL(charqueue_is_empty);
+
+
+
+static int charqueue_dequeue_1(CHARQUEUE *charqueue)
+{
+       int alloc_slots = charqueue->nslots + 1;  /* 1 slot is always empty */
+
+       if (IS_EMPTY(charqueue))
+               return -1;
+       charqueue->tail = (charqueue->tail+1) % alloc_slots;
+       return charqueue->buf[charqueue->tail];
+}
+
+
+
+int charqueue_dequeue(CHARQUEUE *charqueue)
+{
+       int rc = -1;
+
+       spin_lock(&charqueue->lock);
+       RETINT(charqueue_dequeue_1(charqueue));
+Away:
+       spin_unlock(&charqueue->lock);
+       return rc;
+}
+
+
+
+int charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n)
+{
+       int rc = -1, counter = 0, c;
+
+       spin_lock(&charqueue->lock);
+       for (;;) {
+               if (n <= 0)
+                       break;  /* no more buffer space */
+               c = charqueue_dequeue_1(charqueue);
+               if (c < 0)
+                       break;  /* no more input */
+               *buf = (unsigned char)(c);
+               buf++;
+               n--;
+               counter++;
+       }
+       RETINT(counter);
+
+Away:
+       spin_unlock(&charqueue->lock);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(charqueue_dequeue_n);
+
+
+
+void charqueue_destroy(CHARQUEUE *charqueue)
+{
+       if (charqueue == NULL)
+               return;
+       kfree(charqueue);
+}
+EXPORT_SYMBOL_GPL(charqueue_destroy);
diff --git a/drivers/staging/unisys/visorutil/charqueue.h b/drivers/staging/unisys/visorutil/charqueue.h
new file mode 100644 (file)
index 0000000..e9ce0a9
--- /dev/null
@@ -0,0 +1,37 @@
+/* charqueue.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHARQUEUE_H__
+#define __CHARQUEUE_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+/* CHARQUEUE is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct CHARQUEUE_Tag CHARQUEUE;
+
+CHARQUEUE *charqueue_create(ulong nslots);
+void charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c);
+int charqueue_dequeue(CHARQUEUE *charqueue);
+int charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n);
+BOOL charqueue_is_empty(CHARQUEUE *charqueue);
+void charqueue_destroy(CHARQUEUE *charqueue);
+
+#endif
+
diff --git a/drivers/staging/unisys/visorutil/easyproc.c b/drivers/staging/unisys/visorutil/easyproc.c
new file mode 100644 (file)
index 0000000..2b750ee
--- /dev/null
@@ -0,0 +1,365 @@
+/* Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  Handle procfs-specific tasks.
+ *  Note that this file does not know about any module-specific things, nor
+ *  does it know anything about what information to reveal as part of the proc
+ *  entries.  The 2 functions that take care of displaying device and
+ *  driver specific information are passed as parameters to
+ *  easyproc_InitDriver().
+ *
+ *      void show_device_info(struct seq_file *seq, void *p);
+ *      void show_driver_info(struct seq_file *seq);
+ *
+ *  The second parameter to show_device_info is actually a pointer to the
+ *  device-specific info to show.  It is the context that was originally
+ *  passed to easyproc_InitDevice().
+ *
+ ******************************************************************************
+ */
+
+#include <linux/proc_fs.h>
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "easyproc.h"
+
+#define MYDRVNAME "easyproc"
+
+
+
+/*
+ *   /proc/<ProcId>                              ProcDir
+ *   /proc/<ProcId>/driver                       ProcDriverDir
+ *   /proc/<ProcId>/driver/diag                  ProcDriverDiagFile
+ *   /proc/<ProcId>/device                       ProcDeviceDir
+ *   /proc/<ProcId>/device/0                     procDevicexDir
+ *   /proc/<ProcId>/device/0/diag                procDevicexDiagFile
+ */
+
+
+static ssize_t proc_write_device(struct file *file, const char __user *buffer,
+                                size_t count, loff_t *ppos);
+static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
+                                size_t count, loff_t *ppos);
+
+static struct proc_dir_entry *
+       createProcDir(char *name, struct proc_dir_entry *parent)
+{
+       struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
+       if (p == NULL)
+               ERRDRV("failed to create /proc directory %s", name);
+       return p;
+}
+
+static int seq_show_driver(struct seq_file *seq, void *offset);
+static int proc_open_driver(struct inode *inode, struct file *file)
+{
+       return single_open(file, seq_show_driver, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_driver = {
+       .open = proc_open_driver,
+       .read = seq_read,
+       .write = proc_write_driver,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int seq_show_device(struct seq_file *seq, void *offset);
+static int seq_show_device_property(struct seq_file *seq, void *offset);
+static int proc_open_device(struct inode *inode, struct file *file)
+{
+       return single_open(file, seq_show_device, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_device = {
+       .open = proc_open_device,
+       .read = seq_read,
+       .write = proc_write_device,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+static int proc_open_device_property(struct inode *inode, struct file *file)
+{
+       return single_open(file, seq_show_device_property, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_device_property = {
+       .open = proc_open_device_property,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+
+
+void easyproc_InitDriver(struct easyproc_driver_info *pdriver,
+                        char *procId,
+                        void (*show_driver_info)(struct seq_file *),
+                        void (*show_device_info)(struct seq_file *, void *))
+{
+       memset(pdriver, 0, sizeof(struct easyproc_driver_info));
+       pdriver->ProcId = procId;
+       if (pdriver->ProcId == NULL)
+               ERRDRV("ProcId cannot be NULL (trouble ahead)!");
+       pdriver->Show_driver_info = show_driver_info;
+       pdriver->Show_device_info = show_device_info;
+       if (pdriver->ProcDir == NULL)
+               pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
+       if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
+               pdriver->ProcDriverDir = createProcDir("driver",
+                                                      pdriver->ProcDir);
+       if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
+               pdriver->ProcDeviceDir = createProcDir("device",
+                                                      pdriver->ProcDir);
+       if ((pdriver->ProcDriverDir != NULL) &&
+           (pdriver->ProcDriverDiagFile == NULL)) {
+               pdriver->ProcDriverDiagFile =
+                       proc_create_data("diag", 0,
+                                        pdriver->ProcDriverDir,
+                                        &proc_fops_driver, pdriver);
+               if (pdriver->ProcDriverDiagFile == NULL)
+                       ERRDRV("failed to register /proc/%s/driver/diag entry",
+                              pdriver->ProcId);
+       }
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDriver);
+
+
+
+void easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
+                          char *procId,
+                          void (*show_driver_info)(struct seq_file *),
+                          void (*show_device_info)(struct seq_file *, void *),
+                          void (*write_driver_info)(char *buf, size_t count,
+                                                    loff_t *ppos),
+                          void (*write_device_info)(char *buf, size_t count,
+                                                    loff_t *ppos, void *p))
+{
+       easyproc_InitDriver(pdriver, procId,
+                           show_driver_info, show_device_info);
+       pdriver->Write_driver_info = write_driver_info;
+       pdriver->Write_device_info = write_device_info;
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDriverEx);
+
+
+
+void easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
+{
+       if (pdriver->ProcDriverDiagFile != NULL) {
+               remove_proc_entry("diag", pdriver->ProcDriverDir);
+               pdriver->ProcDriverDiagFile = NULL;
+       }
+       if (pdriver->ProcDriverDir != NULL) {
+               remove_proc_entry("driver", pdriver->ProcDir);
+               pdriver->ProcDriverDir = NULL;
+       }
+       if (pdriver->ProcDeviceDir != NULL) {
+               remove_proc_entry("device", pdriver->ProcDir);
+               pdriver->ProcDeviceDir = NULL;
+       }
+       if (pdriver->ProcDir != NULL) {
+               remove_proc_entry(pdriver->ProcId, NULL);
+               pdriver->ProcDir = NULL;
+       }
+       pdriver->ProcId = NULL;
+       pdriver->Show_driver_info = NULL;
+       pdriver->Show_device_info = NULL;
+       pdriver->Write_driver_info = NULL;
+       pdriver->Write_device_info = NULL;
+}
+EXPORT_SYMBOL_GPL(easyproc_DeInitDriver);
+
+
+
+void easyproc_InitDevice(struct easyproc_driver_info *pdriver,
+                        struct easyproc_device_info *p, int devno,
+                        void *devdata)
+{
+       if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
+               char s[29];
+               sprintf(s, "%d", devno);
+               p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
+               p->devno = devno;
+       }
+       p->devdata = devdata;
+       p->pdriver = pdriver;
+       p->devno = devno;
+       if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
+               p->procDevicexDiagFile =
+                       proc_create_data("diag", 0, p->procDevicexDir,
+                                        &proc_fops_device, p);
+               if (p->procDevicexDiagFile == NULL)
+                       ERRDEVX(devno, "failed to register /proc/%s/device/%d/diag entry",
+                               pdriver->ProcId, devno
+                              );
+       }
+       memset(&(p->device_property_info[0]), 0,
+              sizeof(p->device_property_info));
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDevice);
+
+
+
+void easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
+                                  void (*show_property_info)(struct seq_file *, void *),
+                                  char *property_name)
+{
+       size_t i;
+       struct easyproc_device_property_info *px = NULL;
+
+       if (p->procDevicexDir == NULL) {
+               ERRDRV("state error");
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
+               if (p->device_property_info[i].procEntry == NULL) {
+                       px = &(p->device_property_info[i]);
+                       break;
+               }
+       }
+       if (!px) {
+               ERRDEVX(p->devno, "too many device properties");
+               return;
+       }
+       px->devdata = p->devdata;
+       px->pdriver = p->pdriver;
+       px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
+                                        &proc_fops_device_property, px);
+       if (strlen(property_name)+1 > sizeof(px->property_name)) {
+               ERRDEVX(p->devno, "device property name %s too long",
+                       property_name);
+               return;
+       }
+       strcpy(px->property_name, property_name);
+       if (px->procEntry == NULL) {
+               ERRDEVX(p->devno, "failed to register /proc/%s/device/%d/%s entry",
+                       p->pdriver->ProcId, p->devno, property_name
+                      );
+               return;
+       }
+       px->show_device_property_info = show_property_info;
+}
+EXPORT_SYMBOL_GPL(easyproc_CreateDeviceProperty);
+
+
+
+void easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
+                          struct easyproc_device_info *p, int devno)
+{
+       size_t i;
+       for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
+               if (p->device_property_info[i].procEntry != NULL) {
+                       struct easyproc_device_property_info *px =
+                               &(p->device_property_info[i]);
+                       remove_proc_entry(px->property_name, p->procDevicexDir);
+                       px->procEntry = NULL;
+               }
+       }
+       if (p->procDevicexDiagFile != NULL) {
+               remove_proc_entry("diag", p->procDevicexDir);
+               p->procDevicexDiagFile = NULL;
+       }
+       if (p->procDevicexDir != NULL) {
+               char s[29];
+               sprintf(s, "%d", devno);
+               remove_proc_entry(s, pdriver->ProcDeviceDir);
+               p->procDevicexDir = NULL;
+       }
+       p->devdata = NULL;
+       p->pdriver = NULL;
+}
+EXPORT_SYMBOL_GPL(easyproc_DeInitDevice);
+
+
+
+static int seq_show_driver(struct seq_file *seq, void *offset)
+{
+       struct easyproc_driver_info *p =
+               (struct easyproc_driver_info *)(seq->private);
+       if (!p)
+               return 0;
+       (*(p->Show_driver_info))(seq);
+       return 0;
+}
+
+
+
+static int seq_show_device(struct seq_file *seq, void *offset)
+{
+       struct easyproc_device_info *p =
+               (struct easyproc_device_info *)(seq->private);
+       if ((!p) || (!(p->pdriver)))
+               return 0;
+       (*(p->pdriver->Show_device_info))(seq, p->devdata);
+       return 0;
+}
+
+
+
+static int seq_show_device_property(struct seq_file *seq, void *offset)
+{
+       struct easyproc_device_property_info *p =
+               (struct easyproc_device_property_info *)(seq->private);
+       if ((!p) || (!(p->show_device_property_info)))
+               return 0;
+       (*(p->show_device_property_info))(seq, p->devdata);
+       return 0;
+}
+
+
+
+static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
+                                size_t count, loff_t *ppos)
+{
+       struct seq_file *seq = (struct seq_file *)file->private_data;
+       struct easyproc_driver_info *p = NULL;
+       char local_buf[256];
+       if (seq == NULL)
+               return 0;
+       p = (struct easyproc_driver_info *)(seq->private);
+       if ((!p) || (!(p->Write_driver_info)))
+               return 0;
+       if (count >= sizeof(local_buf))
+               return -ENOMEM;
+       if (copy_from_user(local_buf, buffer, count))
+               return -EFAULT;
+       local_buf[count] = '\0';  /* be friendly */
+       (*(p->Write_driver_info))(local_buf, count, ppos);
+       return count;
+}
+
+
+
+static ssize_t proc_write_device(struct file *file, const char __user *buffer,
+                                size_t count, loff_t *ppos)
+{
+       struct seq_file *seq = (struct seq_file *)file->private_data;
+       struct easyproc_device_info *p = NULL;
+       char local_buf[256];
+       if (seq == NULL)
+               return 0;
+       p = (struct easyproc_device_info *)(seq->private);
+       if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
+               return 0;
+       if (count >= sizeof(local_buf))
+               return -ENOMEM;
+       if (copy_from_user(local_buf, buffer, count))
+               return -EFAULT;
+       local_buf[count] = '\0';  /* be friendly */
+       (*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);
+       return count;
+}
diff --git a/drivers/staging/unisys/visorutil/easyproc.h b/drivers/staging/unisys/visorutil/easyproc.h
new file mode 100644 (file)
index 0000000..a1b4df7
--- /dev/null
@@ -0,0 +1,86 @@
+/* easyproc.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes the interfaces necessary for a simple /proc file
+ *  implementation for a driver.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __EASYPROC_H__
+#define __EASYPROC_H__
+
+#include "timskmod.h"
+
+
+struct easyproc_driver_info {
+       struct proc_dir_entry *ProcDir;
+       struct proc_dir_entry *ProcDriverDir;
+       struct proc_dir_entry *ProcDriverDiagFile;
+       struct proc_dir_entry *ProcDeviceDir;
+       char *ProcId;
+       void (*Show_device_info)(struct seq_file *seq, void *p);
+       void (*Show_driver_info)(struct seq_file *seq);
+       void (*Write_device_info)(char *buf, size_t count,
+                                 loff_t *ppos, void *p);
+       void (*Write_driver_info)(char *buf, size_t count, loff_t *ppos);
+};
+
+/* property is a file under /proc/<x>/device/<x>/<property_name> */
+struct easyproc_device_property_info {
+       char property_name[25];
+       struct proc_dir_entry *procEntry;
+       struct easyproc_driver_info *pdriver;
+       void *devdata;
+       void (*show_device_property_info)(struct seq_file *seq, void *p);
+};
+
+struct easyproc_device_info {
+       struct proc_dir_entry *procDevicexDir;
+       struct proc_dir_entry *procDevicexDiagFile;
+       struct easyproc_driver_info *pdriver;
+       void *devdata;
+       int devno;
+       /*  allow for a number of custom properties for each device: */
+       struct easyproc_device_property_info device_property_info[10];
+};
+
+void easyproc_InitDevice(struct easyproc_driver_info *pdriver,
+                        struct easyproc_device_info *p, int devno,
+                        void *devdata);
+void easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
+                          struct easyproc_device_info *p, int devno);
+void easyproc_InitDriver(struct easyproc_driver_info *pdriver,
+                        char *procId,
+                        void (*show_driver_info)(struct seq_file *),
+                        void (*show_device_info)(struct seq_file *, void *));
+void easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
+                          char *procId,
+                          void (*show_driver_info)(struct seq_file *),
+                          void (*show_device_info)(struct seq_file *, void *),
+                          void (*Write_driver_info)(char *buf, size_t count,
+                                                    loff_t *ppos),
+                          void (*Write_device_info)(char *buf, size_t count,
+                                                    loff_t *ppos, void *p));
+void easyproc_DeInitDriver(struct easyproc_driver_info *pdriver);
+void easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
+                                  void (*show_property_info)(struct seq_file *, void *),
+                                  char *property_name);
+
+#endif
diff --git a/drivers/staging/unisys/visorutil/memregion.h b/drivers/staging/unisys/visorutil/memregion.h
new file mode 100644 (file)
index 0000000..a1fce7b
--- /dev/null
@@ -0,0 +1,43 @@
+/* memregion.h
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __MEMREGION_H__
+#define __MEMREGION_H__
+
+#include "timskmod.h"
+
+/* MEMREGION is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct MEMREGION_Tag MEMREGION;
+
+MEMREGION *memregion_create(HOSTADDRESS physaddr, ulong nbytes);
+MEMREGION *memregion_create_overlapped(MEMREGION *parent,
+                                      ulong offset, ulong nbytes);
+int memregion_resize(MEMREGION *memregion, ulong newsize);
+int memregion_read(MEMREGION *memregion,
+                  ulong offset, void *dest, ulong nbytes);
+int memregion_write(MEMREGION *memregion,
+                   ulong offset, void *src, ulong nbytes);
+void memregion_destroy(MEMREGION *memregion);
+HOSTADDRESS memregion_get_physaddr(MEMREGION *memregion);
+ulong memregion_get_nbytes(MEMREGION *memregion);
+void memregion_dump(MEMREGION *memregion, char *s,
+                   ulong off, ulong len, struct seq_file *seq);
+void *memregion_get_pointer(MEMREGION *memregion);
+
+#endif
diff --git a/drivers/staging/unisys/visorutil/memregion_direct.c b/drivers/staging/unisys/visorutil/memregion_direct.c
new file mode 100644 (file)
index 0000000..fbb460f
--- /dev/null
@@ -0,0 +1,221 @@
+/* memregion_direct.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This is an implementation of memory regions that can be used to read/write
+ *  channel memory (in main memory of the host system) from code running in
+ *  a virtual partition.
+ */
+#include "uniklog.h"
+#include "timskmod.h"
+#include "memregion.h"
+
+#define MYDRVNAME "memregion"
+
+struct MEMREGION_Tag {
+       HOSTADDRESS physaddr;
+       ulong nbytes;
+       void *mapped;
+       BOOL requested;
+       BOOL overlapped;
+};
+
+static BOOL mapit(MEMREGION *memregion);
+static void unmapit(MEMREGION *memregion);
+
+MEMREGION *
+memregion_create(HOSTADDRESS physaddr, ulong nbytes)
+{
+       MEMREGION *rc = NULL;
+       MEMREGION *memregion = kmalloc(sizeof(MEMREGION),
+                                      GFP_KERNEL|__GFP_NORETRY);
+       if (memregion == NULL) {
+               ERRDRV("memregion_create allocation failed");
+               return NULL;
+       }
+       memset(memregion, 0, sizeof(MEMREGION));
+       memregion->physaddr = physaddr;
+       memregion->nbytes = nbytes;
+       memregion->overlapped = FALSE;
+       if (!mapit(memregion))
+               RETPTR(NULL);
+       RETPTR(memregion);
+
+Away:
+       if (rc == NULL) {
+               if (memregion != NULL) {
+                       memregion_destroy(memregion);
+                       memregion = NULL;
+               }
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(memregion_create);
+
+MEMREGION *
+memregion_create_overlapped(MEMREGION *parent, ulong offset, ulong nbytes)
+{
+       MEMREGION *memregion = NULL;
+
+       if (parent == NULL) {
+               ERRDRV("%s parent is NULL", __func__);
+               return NULL;
+       }
+       if (parent->mapped == NULL) {
+               ERRDRV("%s parent is not mapped!", __func__);
+               return NULL;
+       }
+       if ((offset >= parent->nbytes) ||
+           ((offset + nbytes) >= parent->nbytes)) {
+               ERRDRV("%s range (%lu,%lu) out of parent range",
+                      __func__, offset, nbytes);
+               return NULL;
+       }
+       memregion = kmalloc(sizeof(MEMREGION), GFP_KERNEL|__GFP_NORETRY);
+       if (memregion == NULL) {
+               ERRDRV("%s allocation failed", __func__);
+               return NULL;
+       }
+       memset(memregion, 0, sizeof(MEMREGION));
+       memregion->physaddr = parent->physaddr + offset;
+       memregion->nbytes = nbytes;
+       memregion->mapped = ((u8 *) (parent->mapped)) + offset;
+       memregion->requested = FALSE;
+       memregion->overlapped = TRUE;
+       return memregion;
+}
+EXPORT_SYMBOL_GPL(memregion_create_overlapped);
+
+
+static BOOL
+mapit(MEMREGION *memregion)
+{
+       ulong physaddr = (ulong) (memregion->physaddr);
+       ulong nbytes = memregion->nbytes;
+
+       memregion->requested = FALSE;
+       if (!request_mem_region(physaddr, nbytes, MYDRVNAME))
+               ERRDRV("cannot reserve channel memory @0x%lx for 0x%lx-- no big deal", physaddr, nbytes);
+       else
+               memregion->requested = TRUE;
+       memregion->mapped = ioremap_cache(physaddr, nbytes);
+       if (memregion->mapped == NULL) {
+               ERRDRV("cannot ioremap_cache channel memory @0x%lx for 0x%lx",
+                      physaddr, nbytes);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static void
+unmapit(MEMREGION *memregion)
+{
+       if (memregion->mapped != NULL) {
+               iounmap(memregion->mapped);
+               memregion->mapped = NULL;
+       }
+       if (memregion->requested) {
+               release_mem_region((ulong) (memregion->physaddr),
+                                  memregion->nbytes);
+               memregion->requested = FALSE;
+       }
+}
+
+HOSTADDRESS
+memregion_get_physaddr(MEMREGION *memregion)
+{
+       return memregion->physaddr;
+}
+EXPORT_SYMBOL_GPL(memregion_get_physaddr);
+
+ulong
+memregion_get_nbytes(MEMREGION *memregion)
+{
+       return memregion->nbytes;
+}
+EXPORT_SYMBOL_GPL(memregion_get_nbytes);
+
+void *
+memregion_get_pointer(MEMREGION *memregion)
+{
+       return memregion->mapped;
+}
+EXPORT_SYMBOL_GPL(memregion_get_pointer);
+
+int
+memregion_resize(MEMREGION *memregion, ulong newsize)
+{
+       if (newsize == memregion->nbytes)
+               return 0;
+       if (memregion->overlapped)
+               /* no error check here - we no longer know the
+                * parent's range!
+                */
+               memregion->nbytes = newsize;
+       else {
+               unmapit(memregion);
+               memregion->nbytes = newsize;
+               if (!mapit(memregion))
+                       return -1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(memregion_resize);
+
+
+static int
+memregion_readwrite(BOOL is_write,
+                   MEMREGION *memregion, ulong offset,
+                   void *local, ulong nbytes)
+{
+       if (offset + nbytes > memregion->nbytes) {
+               ERRDRV("memregion_readwrite offset out of range!!");
+               return -EFAULT;
+       }
+       if (is_write)
+               memcpy_toio(memregion->mapped + offset, local, nbytes);
+       else
+               memcpy_fromio(local, memregion->mapped + offset, nbytes);
+
+       return 0;
+}
+
+int
+memregion_read(MEMREGION *memregion, ulong offset, void *dest, ulong nbytes)
+{
+       return memregion_readwrite(FALSE, memregion, offset, dest, nbytes);
+}
+EXPORT_SYMBOL_GPL(memregion_read);
+
+int
+memregion_write(MEMREGION *memregion, ulong offset, void *src, ulong nbytes)
+{
+       return memregion_readwrite(TRUE, memregion, offset, src, nbytes);
+}
+EXPORT_SYMBOL_GPL(memregion_write);
+
+void
+memregion_destroy(MEMREGION *memregion)
+{
+       if (memregion == NULL)
+               return;
+       if (!memregion->overlapped)
+               unmapit(memregion);
+       kfree(memregion);
+}
+EXPORT_SYMBOL_GPL(memregion_destroy);
+
diff --git a/drivers/staging/unisys/visorutil/periodic_work.c b/drivers/staging/unisys/visorutil/periodic_work.c
new file mode 100644 (file)
index 0000000..1350b8e
--- /dev/null
@@ -0,0 +1,230 @@
+/* periodic_work.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Helper functions to schedule periodic work in Linux kernel mode.
+ */
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "periodic_work.h"
+
+#define MYDRVNAME "periodic_work"
+
+
+
+struct PERIODIC_WORK_Tag {
+       rwlock_t lock;
+       struct delayed_work work;
+       void (*workfunc)(void *);
+       void *workfuncarg;
+       BOOL is_scheduled;
+       BOOL want_to_stop;
+       ulong jiffy_interval;
+       struct workqueue_struct *workqueue;
+       const char *devnam;
+};
+
+
+
+static void periodic_work_func(struct work_struct *work)
+{
+       PERIODIC_WORK *periodic_work =
+               container_of(work, struct PERIODIC_WORK_Tag, work.work);
+       (*periodic_work->workfunc)(periodic_work->workfuncarg);
+}
+
+
+
+PERIODIC_WORK *periodic_work_create(ulong jiffy_interval,
+                                     struct workqueue_struct *workqueue,
+                                     void (*workfunc)(void *),
+                                     void *workfuncarg,
+                                     const char *devnam)
+{
+       PERIODIC_WORK *periodic_work = kmalloc(sizeof(PERIODIC_WORK),
+                                              GFP_KERNEL|__GFP_NORETRY);
+       if (periodic_work == NULL) {
+               ERRDRV("periodic_work allocation failed ");
+               return NULL;
+       }
+       memset(periodic_work, '\0', sizeof(PERIODIC_WORK));
+       rwlock_init(&periodic_work->lock);
+       periodic_work->jiffy_interval = jiffy_interval;
+       periodic_work->workqueue = workqueue;
+       periodic_work->workfunc = workfunc;
+       periodic_work->workfuncarg = workfuncarg;
+       periodic_work->devnam = devnam;
+       return periodic_work;
+}
+EXPORT_SYMBOL_GPL(periodic_work_create);
+
+
+
+void periodic_work_destroy(PERIODIC_WORK *periodic_work)
+{
+       if (periodic_work == NULL)
+               return;
+       kfree(periodic_work);
+}
+EXPORT_SYMBOL_GPL(periodic_work_destroy);
+
+
+
+/** Call this from your periodic work worker function to schedule the next
+ *  call.
+ *  If this function returns FALSE, there was a failure and the
+ *  periodic work is no longer scheduled
+ */
+BOOL periodic_work_nextperiod(PERIODIC_WORK *periodic_work)
+{
+       BOOL rc = FALSE;
+       write_lock(&periodic_work->lock);
+       if (periodic_work->want_to_stop) {
+               periodic_work->is_scheduled = FALSE;
+               periodic_work->want_to_stop = FALSE;
+               RETBOOL(TRUE);  /* yes, TRUE; see periodic_work_stop() */
+       } else if (queue_delayed_work(periodic_work->workqueue,
+                                     &periodic_work->work,
+                                     periodic_work->jiffy_interval) < 0) {
+               ERRDEV(periodic_work->devnam, "queue_delayed_work failed!");
+               periodic_work->is_scheduled = FALSE;
+               RETBOOL(FALSE);
+       }
+       RETBOOL(TRUE);
+Away:
+       write_unlock(&periodic_work->lock);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(periodic_work_nextperiod);
+
+
+
+/** This function returns TRUE iff new periodic work was actually started.
+ *  If this function returns FALSE, then no work was started
+ *  (either because it was already started, or because of a failure).
+ */
+BOOL periodic_work_start(PERIODIC_WORK *periodic_work)
+{
+       BOOL rc = FALSE;
+
+       write_lock(&periodic_work->lock);
+       if (periodic_work->is_scheduled)
+               RETBOOL(FALSE);
+       if (periodic_work->want_to_stop) {
+               ERRDEV(periodic_work->devnam,
+                      "dev_start_periodic_work failed!");
+               RETBOOL(FALSE);
+       }
+       INIT_DELAYED_WORK(&periodic_work->work, &periodic_work_func);
+       if (queue_delayed_work(periodic_work->workqueue,
+                              &periodic_work->work,
+                              periodic_work->jiffy_interval) < 0) {
+               ERRDEV(periodic_work->devnam,
+                      "%s queue_delayed_work failed!", __func__);
+               RETBOOL(FALSE);
+       }
+       periodic_work->is_scheduled = TRUE;
+       RETBOOL(TRUE);
+Away:
+       write_unlock(&periodic_work->lock);
+       return rc;
+
+}
+EXPORT_SYMBOL_GPL(periodic_work_start);
+
+
+
+
+/** This function returns TRUE iff your call actually stopped the periodic
+ *  work.
+ *
+ *  -- PAY ATTENTION... this is important --
+ *
+ *  NO NO #1
+ *
+ *     Do NOT call this function from some function that is running on the
+ *     same workqueue as the work you are trying to stop might be running
+ *     on!  If you violate this rule, periodic_work_stop() MIGHT work, but it
+ *     also MIGHT get hung up in an infinite loop saying
+ *     "waiting for delayed work...".  This will happen if the delayed work
+ *     you are trying to cancel has been put in the workqueue list, but can't
+ *     run yet because we are running that same workqueue thread right now.
+ *
+ *     Bottom line: If you need to call periodic_work_stop() from a workitem,
+ *     be sure the workitem is on a DIFFERENT workqueue than the workitem that
+ *     you are trying to cancel.
+ *
+ *     If I could figure out some way to check for this "no no" condition in
+ *     the code, I would.  It would have saved me the trouble of writing this
+ *     long comment.  And also, don't think this is some "theoretical" race
+ *     condition.  It is REAL, as I have spent the day chasing it.
+ *
+ *  NO NO #2
+ *
+ *     Take close note of the locks that you own when you call this function.
+ *     You must NOT own any locks that are needed by the periodic work
+ *     function that is currently installed.  If you DO, a deadlock may result,
+ *     because stopping the periodic work often involves waiting for the last
+ *     iteration of the periodic work function to complete.  Again, if you hit
+ *     this deadlock, you will get hung up in an infinite loop saying
+ *     "waiting for delayed work...".
+ */
+BOOL periodic_work_stop(PERIODIC_WORK *periodic_work)
+{
+       BOOL stopped_something = FALSE;
+
+       write_lock(&periodic_work->lock);
+       stopped_something = periodic_work->is_scheduled &&
+               (!periodic_work->want_to_stop);
+       while (periodic_work->is_scheduled) {
+               periodic_work->want_to_stop = TRUE;
+               if (cancel_delayed_work(&periodic_work->work)) {
+                       /* We get here if the delayed work was pending as
+                        * delayed work, but was NOT run.
+                        */
+                       ASSERT(periodic_work->is_scheduled);
+                       periodic_work->is_scheduled = FALSE;
+               } else {
+                       /* If we get here, either the delayed work:
+                        * - was run, OR,
+                        * - is running RIGHT NOW on another processor, OR,
+                        * - wasn't even scheduled (there is a miniscule
+                        *   timing window where this could be the case)
+                        * flush_workqueue() would make sure it is finished
+                        * executing, but that still isn't very useful, which
+                        * explains the loop...
+                        */
+               }
+               if (periodic_work->is_scheduled) {
+                       write_unlock(&periodic_work->lock);
+                       WARNDEV(periodic_work->devnam,
+                               "waiting for delayed work...");
+                       /* We rely on the delayed work function running here,
+                        * and eventually calling periodic_work_nextperiod(),
+                        * which will see that want_to_stop is set, and
+                        * subsequently clear is_scheduled.
+                        */
+                       SLEEPJIFFIES(10);
+                       write_lock(&periodic_work->lock);
+               } else
+                       periodic_work->want_to_stop = FALSE;
+       }
+       write_unlock(&periodic_work->lock);
+       return stopped_something;
+}
+EXPORT_SYMBOL_GPL(periodic_work_stop);
diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c
new file mode 100644 (file)
index 0000000..f59b37e
--- /dev/null
@@ -0,0 +1,334 @@
+/* procobjecttree.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "procobjecttree.h"
+
+#define MYDRVNAME "procobjecttree"
+
+
+
+/** This is context info that we stash in each /proc file entry, which we
+ *  need in order to call the callback function that supplies the /proc read
+ *  info for that file.
+ */
+typedef struct {
+       void (*show_property)(struct seq_file *, void *, int);
+       MYPROCOBJECT *procObject;
+       int propertyIndex;
+
+} PROCDIRENTRYCONTEXT;
+
+/** This describes the attributes of a tree rooted at
+ *  <procDirRoot>/<name[0]>/<name[1]>/...
+ *  Properties for each object of this type will be located under
+ *  <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>.
+ */
+struct MYPROCTYPE_Tag {
+       const char **name;  /**< node names for this type, ending with NULL */
+       int nNames;         /**< num of node names in <name> */
+
+       /** root dir for this type tree in /proc */
+       struct proc_dir_entry *procDirRoot;
+
+       struct proc_dir_entry **procDirs;  /**< for each node in <name> */
+
+       /** bottom dir where objects will be rooted; i.e., this is
+        *  <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the
+        *  last entry in the <procDirs> array. */
+       struct proc_dir_entry *procDir;
+
+       /** name for each property that objects of this type can have */
+       const char **propertyNames;
+
+       int nProperties;       /**< num of names in <propertyNames> */
+
+       /** Call this, passing MYPROCOBJECT.context and the property index
+        *  whenever someone reads the proc entry */
+       void (*show_property)(struct seq_file *, void *, int);
+};
+
+
+
+struct MYPROCOBJECT_Tag {
+       MYPROCTYPE *type;
+
+       /** This is the name of the dir node in /proc under which the
+        *  properties of this object will appear as files. */
+       char *name;
+
+       int namesize;   /**< number of bytes allocated for name */
+       void *context;  /**< passed to MYPROCTYPE.show_property */
+
+       /** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */
+       struct proc_dir_entry *procDir;
+
+       /** a proc dir entry for each of the properties of the object;
+        *  properties are identified in MYPROCTYPE.propertyNames, so each of
+        *  the <procDirProperties> describes a single file like
+        *  <type.procDirRoot>/<type.name[0]>/<type.name[1]>/...
+        *           /<name>/<propertyName>
+        */
+       struct proc_dir_entry **procDirProperties;
+
+       /** this is a holding area for the context information that is needed
+        *  to run the /proc callback function */
+       PROCDIRENTRYCONTEXT *procDirPropertyContexts;
+};
+
+
+
+static struct proc_dir_entry *
+createProcDir(const char *name, struct proc_dir_entry *parent)
+{
+       struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
+       if (p == NULL)
+               ERRDRV("failed to create /proc directory %s", name);
+       return p;
+}
+
+static struct proc_dir_entry *
+createProcFile(const char *name, struct proc_dir_entry *parent,
+              const struct file_operations *fops, void *data)
+{
+       struct proc_dir_entry *p = proc_create_data(name, 0, parent,
+                                                   fops, data);
+       if (p == NULL)
+               ERRDRV("failed to create /proc file %s", name);
+       return p;
+}
+
+static int seq_show(struct seq_file *seq, void *offset);
+static int proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, seq_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_fops = {
+       .open = proc_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+
+
+MYPROCTYPE *proc_CreateType(struct proc_dir_entry *procDirRoot,
+                           const char **name,
+                           const char **propertyNames,
+                           void (*show_property)(struct seq_file *,
+                                                 void *, int))
+{
+       int i = 0;
+       MYPROCTYPE *rc = NULL, *type = NULL;
+       struct proc_dir_entry *parent = NULL;
+
+       if (procDirRoot == NULL)
+               FAIL("procDirRoot cannot be NULL!", 0);
+       if (name == NULL || name[0] == NULL)
+               FAIL("name must contain at least 1 node name!", 0);
+       type = kmalloc(sizeof(MYPROCTYPE), GFP_KERNEL|__GFP_NORETRY);
+       if (type == NULL)
+               FAIL("out of memory", 0);
+       memset(type, 0, sizeof(MYPROCTYPE));
+       type->name = name;
+       type->propertyNames = propertyNames;
+       type->nProperties = 0;
+       type->nNames = 0;
+       type->show_property = show_property;
+       type->procDirRoot = procDirRoot;
+       if (type->propertyNames != 0)
+               while (type->propertyNames[type->nProperties] != NULL)
+                       type->nProperties++;
+       while (type->name[type->nNames] != NULL)
+               type->nNames++;
+       type->procDirs = kmalloc((type->nNames+1)*
+                                sizeof(struct proc_dir_entry *),
+                                GFP_KERNEL|__GFP_NORETRY);
+       if (type->procDirs == NULL)
+               FAIL("out of memory", 0);
+       memset(type->procDirs, 0, (type->nNames + 1) *
+              sizeof(struct proc_dir_entry *));
+       parent = procDirRoot;
+       for (i = 0; i < type->nNames; i++) {
+               type->procDirs[i] = createProcDir(type->name[i], parent);
+               if (type->procDirs[i] == NULL)
+                       RETPTR(NULL);
+               parent = type->procDirs[i];
+       }
+       type->procDir = type->procDirs[type->nNames-1];
+       RETPTR(type);
+Away:
+       if (rc == NULL) {
+               if (type != NULL) {
+                       proc_DestroyType(type);
+                       type = NULL;
+               }
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(proc_CreateType);
+
+
+
+void proc_DestroyType(MYPROCTYPE *type)
+{
+       if (type == NULL)
+               return;
+       if (type->procDirs != NULL) {
+               int i = type->nNames-1;
+               while (i >= 0) {
+                       if (type->procDirs[i] != NULL) {
+                               struct proc_dir_entry *parent = NULL;
+                               if (i == 0)
+                                       parent = type->procDirRoot;
+                               else
+                                       parent = type->procDirs[i-1];
+                               remove_proc_entry(type->name[i], parent);
+                       }
+                       i--;
+               }
+               kfree(type->procDirs);
+               type->procDirs = NULL;
+       }
+       kfree(type);
+}
+EXPORT_SYMBOL_GPL(proc_DestroyType);
+
+
+
+MYPROCOBJECT *proc_CreateObject(MYPROCTYPE *type,
+                               const char *name, void *context)
+{
+       MYPROCOBJECT *obj = NULL, *rc = NULL;
+       int i = 0;
+
+       if (type == NULL)
+               FAIL("type cannot be NULL", 0);
+       obj = kmalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY);
+       if (obj == NULL)
+               FAIL("out of memory", 0);
+       memset(obj, 0, sizeof(MYPROCOBJECT));
+       obj->type = type;
+       obj->context = context;
+       if (name == NULL) {
+               obj->name = NULL;
+               obj->procDir = type->procDir;
+       } else {
+               obj->namesize = strlen(name)+1;
+               obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY);
+               if (obj->name == NULL) {
+                       obj->namesize = 0;
+                       FAIL("out of memory", 0);
+               }
+               strcpy(obj->name, name);
+               obj->procDir = createProcDir(obj->name, type->procDir);
+               if (obj->procDir == NULL)
+                       RETPTR(NULL);
+       }
+       obj->procDirPropertyContexts =
+               kmalloc((type->nProperties+1)*sizeof(PROCDIRENTRYCONTEXT),
+                       GFP_KERNEL|__GFP_NORETRY);
+       if (obj->procDirPropertyContexts == NULL)
+               FAIL("out of memory", 0);
+       memset(obj->procDirPropertyContexts, 0,
+              (type->nProperties+1)*sizeof(PROCDIRENTRYCONTEXT));
+       obj->procDirProperties =
+               kmalloc((type->nProperties+1) * sizeof(struct proc_dir_entry *),
+                       GFP_KERNEL|__GFP_NORETRY);
+       if (obj->procDirProperties == NULL)
+               FAIL("out of memory", 0);
+       memset(obj->procDirProperties, 0,
+              (type->nProperties+1) * sizeof(struct proc_dir_entry *));
+       for (i = 0; i < type->nProperties; i++) {
+               obj->procDirPropertyContexts[i].procObject = obj;
+               obj->procDirPropertyContexts[i].propertyIndex = i;
+               obj->procDirPropertyContexts[i].show_property =
+                       type->show_property;
+               if (type->propertyNames[i][0] != '\0') {
+                       /* only create properties that have names */
+                       obj->procDirProperties[i] =
+                               createProcFile(type->propertyNames[i],
+                                              obj->procDir, &proc_fops,
+                                              &obj->procDirPropertyContexts[i]);
+                       if (obj->procDirProperties[i] == NULL)
+                               RETPTR(NULL);
+               }
+       }
+       RETPTR(obj);
+Away:
+       if (rc == NULL) {
+               if (obj != NULL) {
+                       proc_DestroyObject(obj);
+                       obj = NULL;
+               }
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(proc_CreateObject);
+
+
+
+void proc_DestroyObject(MYPROCOBJECT *obj)
+{
+       MYPROCTYPE *type = NULL;
+       if (obj == NULL)
+               return;
+       type = obj->type;
+       if (type == NULL)
+               return;
+       if (obj->procDirProperties != NULL) {
+               int i = 0;
+               for (i = 0; i < type->nProperties; i++) {
+                       if (obj->procDirProperties[i] != NULL) {
+                               remove_proc_entry(type->propertyNames[i],
+                                                 obj->procDir);
+                               obj->procDirProperties[i] = NULL;
+                       }
+               }
+               kfree(obj->procDirProperties);
+               obj->procDirProperties = NULL;
+       }
+       if (obj->procDirPropertyContexts != NULL) {
+               kfree(obj->procDirPropertyContexts);
+               obj->procDirPropertyContexts = NULL;
+       }
+       if (obj->procDir != NULL) {
+               if (obj->name != NULL)
+                       remove_proc_entry(obj->name, type->procDir);
+               obj->procDir = NULL;
+       }
+       if (obj->name != NULL) {
+               kfree(obj->name);
+               obj->name = NULL;
+       }
+       kfree(obj);
+}
+EXPORT_SYMBOL_GPL(proc_DestroyObject);
+
+
+
+static int seq_show(struct seq_file *seq, void *offset)
+{
+       PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private);
+       if (ctx == NULL) {
+               ERRDRV("I don't have a freakin' clue...");
+               return 0;
+       }
+       (*ctx->show_property)(seq, ctx->procObject->context,
+                             ctx->propertyIndex);
+       return 0;
+}
diff --git a/drivers/staging/unisys/visorutil/visorkmodutils.c b/drivers/staging/unisys/visorutil/visorkmodutils.c
new file mode 100644 (file)
index 0000000..13e7326
--- /dev/null
@@ -0,0 +1,721 @@
+/* timskmodutils.c
+ *
+ * Copyright Â© 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+#define MYDRVNAME "timskmodutils"
+
+BOOL Debug_Malloc_Enabled = FALSE;
+
+
+
+void myprintk(const char *myDrvName, const char *devname,
+              const char *template, ...)
+{
+       va_list ap;
+       char temp[999];
+       char *ptemp = temp;
+       char pfx[20];
+       char msg[sizeof(pfx) + strlen(myDrvName) + 50];
+
+       if (myDrvName == NULL)
+               return;
+       temp[sizeof(temp)-1] = '\0';
+       pfx[0]               = '\0';
+       msg[0]               = '\0';
+       va_start(ap, template);
+       vsprintf(temp, template, ap);
+       va_end(ap);
+       if (temp[0] == '<') {
+               size_t i = 0;
+               for (i = 0; i < sizeof(pfx) - 1; i++) {
+                       pfx[i] = temp[i];
+                       if (pfx[i] == '>' || pfx[i] == '\0') {
+                               if (pfx[i] == '>')
+                                       ptemp = temp+i+1;
+                               i++;
+                               break;
+                       }
+               }
+               pfx[i] = '\0';
+       }
+       if (devname == NULL)
+               sprintf(msg, "%s%s: ", pfx, myDrvName);
+       else
+               sprintf(msg, "%s%s[%s]: ", pfx, myDrvName, devname);
+       printk(KERN_INFO "%s", msg);
+
+       /* The <prefix> applies up until the \n, so we should not include
+        * it in these printks.  That's why we use <ptemp> to point to the
+        * first char after the ">" in the prefix.
+        */
+       printk(KERN_INFO "%s", ptemp);
+       printk("\n");
+
+}
+
+
+
+void myprintkx(const char *myDrvName, int devno, const char *template, ...)
+{
+       va_list ap;
+       char temp[999];
+       char *ptemp = temp;
+       char pfx[20];
+       char msg[sizeof(pfx) + strlen(myDrvName) + 50];
+
+       if (myDrvName == NULL)
+               return;
+       temp[sizeof(temp)-1] = '\0';
+       pfx[0]               = '\0';
+       msg[0]               = '\0';
+       va_start(ap, template);
+       vsprintf(temp, template, ap);
+       va_end(ap);
+       if (temp[0] == '<') {
+               size_t i = 0;
+               for (i = 0; i < sizeof(pfx) - 1; i++) {
+                       pfx[i] = temp[i];
+                       if (pfx[i] == '>' || pfx[i] == '\0') {
+                               if (pfx[i] == '>')
+                                       ptemp = temp+i+1;
+                               i++;
+                               break;
+                       }
+               }
+               pfx[i] = '\0';
+       }
+       if (devno < 0)
+               sprintf(msg, "%s%s: ", pfx, myDrvName);
+       else
+               sprintf(msg, "%s%s[%d]: ", pfx, myDrvName, devno);
+       printk(KERN_INFO "%s", msg);
+
+       /* The <prefix> applies up until the \n, so we should not include
+        * it in these printks.  That's why we use <ptemp> to point to the
+        * first char after the ">" in the prefix.
+        */
+       printk(KERN_INFO "%s", ptemp);
+       printk("\n");
+}
+
+
+
+int hexDumpWordsToBuffer(char *dest,
+                        int destSize,
+                        char *prefix,
+                        uint32_t *src,
+                        int srcWords,
+                        int wordsToDumpPerLine)
+{
+       int i = 0;
+       int pos = 0;
+       char hex[(wordsToDumpPerLine * 9) + 1];
+       char *line = NULL;
+       int linesize = 1000;
+       int linelen = 0;
+       int currentlen = 0;
+       char emptystring[] = "";
+       char *pfx = prefix;
+       int baseaddr = 0;
+       int rc = 0;
+       uint8_t b1, b2, b3, b4;
+
+       line = vmalloc(linesize);
+       if (line == NULL)
+               RETINT(currentlen);
+
+       if (pfx == NULL || (strlen(pfx) > 50))
+               pfx = emptystring;
+       memset(hex, ' ', wordsToDumpPerLine * 9);
+       hex[wordsToDumpPerLine * 9] = '\0';
+       if (destSize > 0)
+               dest[0] = '\0';
+
+       for (i = 0; i < srcWords; i++) {
+               pos = i % wordsToDumpPerLine;
+               if ((pos == 0) && (i > 0)) {
+                       hex[wordsToDumpPerLine * 9] = '\0';
+                       linelen = sprintf(line, "%s%-6.6x %s\n", pfx,
+                                         baseaddr, hex);
+                       if ((currentlen) + (linelen) >= destSize)
+                               RETINT(currentlen);
+                       strcat(dest, line);
+                       currentlen += linelen;
+                       memset(hex, ' ', wordsToDumpPerLine * 9);
+                       baseaddr = i * 4;
+               }
+               b1 = (uint8_t)((src[i] >> 24) & 0xff);
+               b2 = (uint8_t)((src[i] >> 16) & 0xff);
+               b3 = (uint8_t)((src[i] >>  8) & 0xff);
+               b4 = (uint8_t)((src[i]) & 0xff);
+               sprintf(hex + (pos * 9), "%-2.2x%-2.2x%-2.2x%-2.2x ",
+                       b1, b2, b3, b4);
+               *(hex + (pos * 9) + 9) = ' ';  /* get rid of null */
+       }
+       pos = i%wordsToDumpPerLine;
+       if (i > 0) {
+               hex[wordsToDumpPerLine * 9] = '\0';
+               linelen = sprintf(line, "%s%-6.6x %s\n", pfx, baseaddr, hex);
+               if ((currentlen) + (linelen) >= destSize)
+                       RETINT(currentlen);
+               strcat(dest, line);
+               currentlen += linelen;
+       }
+       RETINT(currentlen);
+
+Away:
+       if (line)
+               vfree(line);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(hexDumpWordsToBuffer);
+
+
+
+int myPrintkHexDump(char *myDrvName,
+                   char *devname,
+                   char *prefix,
+                   char *src,
+                   int srcLen,
+                   int bytesToDumpPerLine)
+{
+       int i = 0;
+       int pos = 0;
+       char printable[bytesToDumpPerLine + 1];
+       char hex[(bytesToDumpPerLine*3) + 1];
+       char *line = NULL;
+       int linesize = 1000;
+       int linelen = 0;
+       int currentlen = 0;
+       char emptystring[] = "";
+       char *pfx = prefix;
+       int baseaddr = 0;
+       int rc = 0;
+       int linecount = 0;
+
+       line = vmalloc(linesize);
+       if (line == NULL)
+               RETINT(currentlen);
+
+       if (pfx == NULL || (strlen(pfx) > 50))
+               pfx = emptystring;
+       memset(hex, ' ', bytesToDumpPerLine * 3);
+       hex[bytesToDumpPerLine * 3] = '\0';
+       memset(printable, ' ', bytesToDumpPerLine);
+       printable[bytesToDumpPerLine] = '\0';
+
+       for (i = 0; i < srcLen; i++) {
+               pos = i % bytesToDumpPerLine;
+               if ((pos == 0) && (i > 0)) {
+                       hex[bytesToDumpPerLine*3] = '\0';
+                       linelen = sprintf(line, "%s%-6.6x %s %s",
+                                         pfx, baseaddr, hex, printable);
+                       myprintk(myDrvName, devname, KERN_INFO "%s", line);
+                       currentlen += linelen;
+                       linecount++;
+                       if ((linecount % 50) == 0)
+                               SLEEPJIFFIES(10);
+                       memset(hex, ' ', bytesToDumpPerLine*3);
+                       memset(printable, ' ', bytesToDumpPerLine);
+                       baseaddr = i;
+               }
+               sprintf(hex + (pos * 3), "%-2.2x ", (uint8_t)(src[i]));
+               *(hex + (pos * 3) + 3) = ' ';  /* get rid of null */
+               if (((uint8_t)(src[i]) >= ' ') && (uint8_t)(src[i]) < 127)
+                       printable[pos] = src[i];
+               else
+                       printable[pos] = '.';
+       }
+       pos = i%bytesToDumpPerLine;
+       if (i > 0) {
+               hex[bytesToDumpPerLine*3] = '\0';
+               linelen = sprintf(line, "%s%-6.6x %s %s",
+                                 pfx, baseaddr, hex, printable);
+               myprintk(myDrvName, devname, KERN_INFO "%s", line);
+               currentlen += linelen;
+       }
+       RETINT(currentlen);
+
+Away:
+       if (line)
+               vfree(line);
+       return rc;
+}
+
+
+
+/** Given as input a number of seconds in #seconds, creates text describing
+    the time within #s.  Also breaks down the number of seconds into component
+    days, hours, minutes, and seconds, and stores to *#days, *#hours,
+    *#minutes, and *#secondsx.
+ *  @param seconds input number of seconds
+ *  @param days    points to a long value where the days component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param hours   points to a long value where the hours component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param minutes points to a long value where the minutes component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param secondsx points to a long value where the seconds component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param s       points to a character buffer where a text representation of
+ *                the #seconds value will be stored.  This buffer MUST be
+ *                large enough to hold the resulting string; to be safe it
+ *                should be at least 100 bytes long.
+ */
+void expandSeconds(time_t seconds, long *days, long *hours, long *minutes,
+                  long *secondsx, char *s)
+{
+       BOOL started = FALSE;
+       char buf[99];
+
+       *days = seconds / (60*60*24);
+       seconds -= ((*days)*(60*60*24));
+       *hours = seconds / (60*60);
+       seconds -= ((*hours)*(60*60));
+       *minutes = seconds/60;
+       seconds -= ((*minutes)*60);
+       *secondsx = (long)seconds;
+       if (s == NULL)
+               RETVOID;
+       s[0] = '\0';
+       if (*days > 0) {
+               sprintf(buf, "%lu day", *days);
+               strcat(s, buf);
+               if (*days != 1)
+                       strcat(s, "s");
+               started = TRUE;
+       }
+       if ((*hours > 0) || started) {
+               if (started)
+                       strcat(s, ", ");
+               sprintf(buf, "%lu hour", *hours);
+               strcat(s, buf);
+               if (*hours != 1)
+                       strcat(s, "s");
+               started = TRUE;
+       }
+       if ((*minutes > 0) || started) {
+               if (started)
+                       strcat(s, ", ");
+               sprintf(buf, "%lu minute", *minutes);
+               strcat(s, buf);
+               if (*minutes != 1)
+                       strcat(s, "s");
+               started = TRUE;
+       }
+       if (started)
+               strcat(s, ", ");
+       sprintf(buf, "%lu second", *secondsx);
+       strcat(s, buf);
+       if (*secondsx != 1)
+               strcat(s, "s");
+
+Away:
+       return;
+}
+
+
+
+/** Initialize a #MESSAGEQ for use (initially it will be empty, of course).
+ *  @param q               the #MESSAGEQ to initialize
+ *  @ingroup messageq
+ */
+void initMessageQ(MESSAGEQ *q)
+{
+       q->qHead = NULL;
+       q->qTail = NULL;
+       sema_init(&q->nQEntries, 0);   /* will block initially */
+       spin_lock_init(&q->queueLock);
+}
+
+
+
+/** Initialize #p with your data structure in #data,
+ *  so you can later place #p onto a #MESSAGEQ.
+ *  @param p               the queue entry that will house your data structure
+ *  @param data            a pointer to your data structure that you want
+ *                         to queue
+ *  @ingroup messageq
+ */
+void initMessageQEntry(MESSAGEQENTRY *p, void *data)
+{
+       p->data = data;
+       p->qNext = NULL;
+       p->qPrev = NULL;
+}
+
+
+
+MESSAGEQENTRY *dequeueMessageGuts(MESSAGEQ *q, BOOL canBlock)
+{
+       MESSAGEQENTRY *pEntry = NULL;
+       MESSAGEQENTRY *rc = NULL;
+       BOOL locked = FALSE;
+       ulong flags = 0;
+       int res = 0;
+
+       if (canBlock) {
+               /* wait for non-empty q */
+               res = down_interruptible(&q->nQEntries);
+               if (signal_pending(current)) {
+                       DEBUGDRV("got signal in dequeueMessage");
+                       RETPTR(NULL);
+               }
+       } else if (down_trylock(&q->nQEntries))
+               RETPTR(NULL);
+       spin_lock_irqsave(&q->queueLock, flags);
+       locked = TRUE;
+#ifdef PARANOID
+       if (q->qHead == NULL) {
+               HUHDRV("unexpected empty queue in getQueue");
+               RETPTR(NULL);
+       }
+#endif
+       pEntry = q->qHead;
+       if (pEntry == q->qTail) {
+               /* only 1 item in the queue */
+               q->qHead = NULL;
+               q->qTail = NULL;
+       } else {
+               q->qHead = pEntry->qNext;
+               q->qHead->qPrev = NULL;
+       }
+       RETPTR(pEntry);
+Away:
+       if (locked) {
+               spin_unlock_irqrestore(&q->queueLock, flags);
+               locked = FALSE;
+       }
+       return rc;
+}
+
+
+
+/** Remove the next message at the head of the FIFO queue, and return it.
+ *  Wait for the queue to become non-empty if it is empty when this
+ *  function is called.
+ *  @param q               the queue where the message is to be obtained from
+ *  @return                the queue entry obtained from the head of the
+ *                         FIFO queue, or NULL iff a signal was received
+ *                         while waiting for the queue to become non-empty
+ *  @ingroup messageq
+ */
+MESSAGEQENTRY *dequeueMessage(MESSAGEQ *q)
+{
+       return dequeueMessageGuts(q, TRUE);
+}
+
+
+
+/** Remove the next message at the head of the FIFO queue, and return it.
+ *  This function will never block (it returns NULL instead).
+ *  @param q               the queue where the message is to be obtained from
+ *  @return                the queue entry obtained from the head of the
+ *                         FIFO queue, or NULL iff the queue is empty.
+ *  @ingroup messageq
+ */
+MESSAGEQENTRY *dequeueMessageNoBlock(MESSAGEQ *q)
+{
+       return dequeueMessageGuts(q, FALSE);
+}
+
+
+
+/** Add an entry to a FIFO queue.
+ *  @param q               the queue where the entry is to be added
+ *  @param pEntry          the entry you want to add to the queue
+ *  @ingroup messageq
+ */
+void enqueueMessage(MESSAGEQ *q, MESSAGEQENTRY *pEntry)
+{
+       BOOL locked = FALSE;
+       ulong flags = 0;
+
+       spin_lock_irqsave(&q->queueLock, flags);
+       locked = TRUE;
+       if (q->qHead == NULL) {
+#ifdef PARANOID
+               if (q->qTail != NULL) {
+                       HUHDRV("qHead/qTail not consistent");
+                       RETVOID;
+               }
+#endif
+               q->qHead = pEntry;
+               q->qTail = pEntry;
+               pEntry->qNext = NULL;
+               pEntry->qPrev = NULL;
+       } else {
+#ifdef PARANOID
+               if (q->qTail == NULL) {
+                       HUHDRV("qTail should not be NULL here");
+                       RETVOID;
+               }
+#endif
+               q->qTail->qNext = pEntry;
+               pEntry->qPrev = q->qTail;
+               pEntry->qNext = NULL;
+               q->qTail = pEntry;
+       }
+       spin_unlock_irqrestore(&q->queueLock, flags);
+       locked = FALSE;
+       up(&q->nQEntries);
+       RETVOID;
+Away:
+       if (locked) {
+               spin_unlock_irqrestore(&q->queueLock, flags);
+               locked = FALSE;
+       }
+       return;
+}
+
+
+
+/** Return the number of entries in the queue.
+ *  @param q               the queue to be examined
+ *  @return                the number of entries on #q
+ *  @ingroup messageq
+ */
+size_t getQueueCount(MESSAGEQ *q)
+{
+       return (size_t)__sync_fetch_and_add(&(q->nQEntries.count), 0);
+}
+
+
+
+/** Return the number of processes waiting in a standard wait queue.
+ *  @param q               the pointer to the wait queue to be
+ *                         examined
+ *  @return                the number of waiters
+ *  @ingroup internal
+ */
+int waitQueueLen(wait_queue_head_t *q)
+{
+       struct list_head *x;
+       int count = 0;
+       list_for_each(x, &(q->task_list))
+               count++;
+       return count;
+}
+
+
+
+/** Display information about the processes on a standard wait queue.
+ *  @param q               the pointer to the wait queue to be
+ *                         examined
+ *  @ingroup internal
+ */
+void debugWaitQ(wait_queue_head_t *q)
+{
+       DEBUGDRV("task_list.next= %-8.8x",
+                ((struct __wait_queue_head *)(q))->task_list.next);
+       DEBUGDRV("task_list.prev= %-8.8x",
+                ((struct __wait_queue_head *)(q))->task_list.prev);
+}
+
+
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  @param dest               the print buffer where text characters will
+ *                           be written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                           to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                           hex-dumped
+ *  @param srcLen             the number of bytes at #src to be hex-dumped
+ *  @param bytesToDumpPerLine output will be formatted such that at most
+ *                           this many of the input data bytes will be
+ *                           represented on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int hexDumpToBuffer(char *dest, int destSize, char *prefix, char *src,
+                   int srcLen, int bytesToDumpPerLine)
+{
+       int i = 0;
+       int pos = 0;
+       char printable[bytesToDumpPerLine + 1];
+       char hex[(bytesToDumpPerLine * 3) + 1];
+       char *line = NULL;
+       int linesize = 1000;
+       int linelen = 0;
+       int currentlen = 0;
+       char emptystring[] = "";
+       char *pfx = prefix;
+       int baseaddr = 0;
+       int rc = 0;
+
+       line = vmalloc(linesize);
+       if (line == NULL)
+               RETINT(currentlen);
+
+       if (pfx == NULL || (strlen(pfx) > 50))
+               pfx = emptystring;
+       memset(hex, ' ', bytesToDumpPerLine * 3);
+       hex[bytesToDumpPerLine * 3] = '\0';
+       memset(printable, ' ', bytesToDumpPerLine);
+       printable[bytesToDumpPerLine] = '\0';
+       if (destSize > 0)
+               dest[0] = '\0';
+
+       for (i = 0; i < srcLen; i++) {
+               pos = i % bytesToDumpPerLine;
+               if ((pos == 0) && (i > 0)) {
+                       hex[bytesToDumpPerLine*3] = '\0';
+                       linelen = sprintf(line, "%s%-6.6x %s %s\n", pfx,
+                                         baseaddr, hex, printable);
+                       if ((currentlen) + (linelen) >= destSize)
+                               RETINT(currentlen);
+                       strcat(dest, line);
+                       currentlen += linelen;
+                       memset(hex, ' ', bytesToDumpPerLine * 3);
+                       memset(printable, ' ', bytesToDumpPerLine);
+                       baseaddr = i;
+               }
+               sprintf(hex + (pos * 3), "%-2.2x ", (uint8_t)(src[i]));
+               *(hex + (pos * 3) + 3) = ' ';  /* get rid of null */
+               if (((uint8_t)(src[i]) >= ' ') && (uint8_t)(src[i]) < 127)
+                       printable[pos] = src[i];
+               else
+                       printable[pos] = '.';
+       }
+       pos = i%bytesToDumpPerLine;
+       if (i > 0) {
+               hex[bytesToDumpPerLine * 3] = '\0';
+               linelen = sprintf(line, "%s%-6.6x %s %s\n",
+                                 pfx, baseaddr, hex, printable);
+               if ((currentlen) + (linelen) >= destSize)
+                       RETINT(currentlen);
+               strcat(dest, line);
+               currentlen += linelen;
+       }
+       RETINT(currentlen);
+
+Away:
+       if (line)
+               vfree(line);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(hexDumpToBuffer);
+
+
+/** Callers to interfaces that set __GFP_NORETRY flag below
+ *  must check for a NULL (error) result as we are telling the
+ *  kernel interface that it is okay to fail.
+ */
+
+void *kmalloc_kernel(size_t siz)
+{
+       return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY);
+}
+
+void *kmalloc_kernel_dma(size_t siz)
+{
+       return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY|GFP_DMA);
+}
+
+void kfree_kernel(const void *p, size_t siz)
+{
+       kfree(p);
+}
+
+void *vmalloc_kernel(size_t siz)
+{
+       return vmalloc((unsigned long)(siz));
+}
+
+void vfree_kernel(const void *p, size_t siz)
+{
+       vfree((void *)(p));
+}
+
+void *pgalloc_kernel(size_t siz)
+{
+       return (void *)__get_free_pages(GFP_KERNEL|__GFP_NORETRY,
+                                      get_order(siz));
+}
+
+void pgfree_kernel(const void *p, size_t siz)
+{
+       free_pages((ulong)(p), get_order(siz));
+}
+
+
+
+/*  Use these handy-dandy seq_file_xxx functions if you want to call some
+ *  functions that write stuff into a seq_file, but you actually just want
+ *  to dump that output into a buffer.  Use them as follows:
+ *  - call seq_file_new_buffer to create the seq_file (you supply the buf)
+ *  - call whatever functions you want that take a seq_file as an argument
+ *    (the buf you supplied will get the output data)
+ *  - call seq_file_done_buffer to dispose of your seq_file
+ */
+struct seq_file *seq_file_new_buffer(void *buf, size_t buf_size)
+{
+       struct seq_file *rc = NULL;
+       struct seq_file *m = kmalloc_kernel(sizeof(struct seq_file));
+
+       if (m == NULL)
+               RETPTR(NULL);
+       memset(m, 0, sizeof(struct seq_file));
+       m->buf = buf;
+       m->size = buf_size;
+       RETPTR(m);
+Away:
+       if (rc == NULL) {
+               seq_file_done_buffer(m);
+               m = NULL;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(seq_file_new_buffer);
+
+
+
+void seq_file_done_buffer(struct seq_file *m)
+{
+       if (!m)
+               return;
+       kfree(m);
+}
+EXPORT_SYMBOL_GPL(seq_file_done_buffer);
+
+
+
+void seq_hexdump(struct seq_file *seq, u8 *pfx, void *buf, ulong nbytes)
+{
+       int fmtbufsize = 100 * COVQ(nbytes, 16);
+       char *fmtbuf = NULL;
+       int i = 0;
+       if (buf == NULL) {
+               seq_printf(seq, "%s<NULL>\n", pfx);
+               return;
+       }
+       fmtbuf = kmalloc_kernel(fmtbufsize);
+       if (fmtbuf == NULL)
+               return;
+       hexDumpToBuffer(fmtbuf, fmtbufsize, pfx, (char *)(buf), nbytes, 16);
+       for (i = 0; fmtbuf[i] != '\0'; i++)
+               seq_printf(seq, "%c", fmtbuf[i]);
+       kfree(fmtbuf);
+}
index b0bfd3430d4772264572c8b6d9359e798825d228..60a3e3fe4dcb29961eec9bdab1ba1ae6bb9aeffe 100644 (file)
@@ -87,13 +87,16 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
        int sockfd = 0;
        struct socket *socket;
        ssize_t err = -EINVAL;
+       int rv;
 
        if (!sdev) {
                dev_err(dev, "sdev is null\n");
                return -ENODEV;
        }
 
-       sscanf(buf, "%d", &sockfd);
+       rv = sscanf(buf, "%d", &sockfd);
+       if (rv != 1)
+               return -EINVAL;
 
        if (sockfd != -1) {
                dev_info(dev, "stub up\n");
diff --git a/drivers/staging/usbip/uapi/usbip.h b/drivers/staging/usbip/uapi/usbip.h
new file mode 100644 (file)
index 0000000..fa5db30
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *     usbip.h
+ *
+ *     USBIP uapi defines and function prototypes etc.
+*/
+
+#ifndef _UAPI_LINUX_USBIP_H
+#define _UAPI_LINUX_USBIP_H
+
+/* usbip device status - exported in usbip device sysfs status */
+enum usbip_device_status {
+       /* sdev is available. */
+       SDEV_ST_AVAILABLE = 0x01,
+       /* sdev is now used. */
+       SDEV_ST_USED,
+       /* sdev is unusable because of a fatal error. */
+       SDEV_ST_ERROR,
+
+       /* vdev does not connect a remote device. */
+       VDEV_ST_NULL,
+       /* vdev is used, but the USB address is not assigned yet */
+       VDEV_ST_NOTASSIGNED,
+       VDEV_ST_USED,
+       VDEV_ST_ERROR
+};
+#endif /* _UAPI_LINUX_USBIP_H */
index 7e6c5436d972f6201a19cbc691e3a4cbfac6f528..732fb636a1e5b26c19b816448f7faa08391f5a35 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/usb.h>
 #include <linux/wait.h>
+#include "uapi/usbip.h"
 
 #define USBIP_VERSION "1.0.0"
 
@@ -235,22 +236,6 @@ enum usbip_side {
        USBIP_STUB,
 };
 
-enum usbip_status {
-       /* sdev is available. */
-       SDEV_ST_AVAILABLE = 0x01,
-       /* sdev is now used. */
-       SDEV_ST_USED,
-       /* sdev is unusable because of a fatal error. */
-       SDEV_ST_ERROR,
-
-       /* vdev does not connect a remote device. */
-       VDEV_ST_NULL,
-       /* vdev is used, but the USB address is not assigned yet */
-       VDEV_ST_NOTASSIGNED,
-       VDEV_ST_USED,
-       VDEV_ST_ERROR
-};
-
 /* event handler */
 #define USBIP_EH_SHUTDOWN      (1 << 0)
 #define USBIP_EH_BYE           (1 << 1)
@@ -271,7 +256,7 @@ enum usbip_status {
 /* a common structure for stub_device and vhci_device */
 struct usbip_device {
        enum usbip_side side;
-       enum usbip_status status;
+       enum usbip_device_status status;
 
        /* lock for status */
        spinlock_t lock;
index 2cb81b3b35f755494c9a137b76b656ecf8acbb72..5af59d429114d98db687be39dc9ba2120f6a2137 100644 (file)
@@ -15,6 +15,7 @@
 #include <syslog.h>
 #include <unistd.h>
 #include <linux/usb/ch9.h>
+#include "../../uapi/usbip.h"
 
 #ifndef USBIDS_FILE
 #define USBIDS_FILE "/usr/share/hwdata/usb.ids"
@@ -77,23 +78,6 @@ extern int usbip_use_debug ;
                abort();                                \
        } while (0)
 
-/* FIXME: how to sync with drivers/usbip_common.h ? */
-enum usbip_device_status {
-       /* sdev is available. */
-       SDEV_ST_AVAILABLE = 0x01,
-       /* sdev is now used. */
-       SDEV_ST_USED,
-       /* sdev is unusable because of a fatal error. */
-       SDEV_ST_ERROR,
-
-       /* vdev does not connect a remote device. */
-       VDEV_ST_NULL,
-       /* vdev is used, but the USB address is not assigned yet */
-       VDEV_ST_NOTASSIGNED,
-       VDEV_ST_USED,
-       VDEV_ST_ERROR
-};
-
 struct usbip_usb_interface {
        uint8_t bInterfaceClass;
        uint8_t bInterfaceSubClass;
index 86a867582de6a4beaf8e5a9f061de42a1199363b..35b2f5b0e350f0d2bd17175a0266bff6bbdca31d 100644 (file)
@@ -101,6 +101,7 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
 static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
 {
        struct usbip_exported_device *edev = NULL;
+       struct usbip_exported_device *edev_old;
        size_t size;
        int i;
 
@@ -126,8 +127,10 @@ static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
        size = sizeof(*edev) + edev->udev.bNumInterfaces *
                sizeof(struct usbip_usb_interface);
 
+       edev_old = edev;
        edev = realloc(edev, size);
        if (!edev) {
+               edev = edev_old;
                dbg("realloc failed");
                goto err;
        }
index f4bfefec5fcc729f1c5af487e03bad4d6c321bce..d80d37c64cb373c9910d235a5debc81cdc68ec29 100644 (file)
@@ -545,7 +545,7 @@ int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
                return -1;
        }
 
-       snprintf(buff, sizeof(buff), "%u %u %u %u",
+       snprintf(buff, sizeof(buff), "%u %d %u %u",
                        port, sockfd, devid, speed);
        dbg("writing: %s", buff);
 
index e5f0be3b4ae48db47d666e89b7fbd2e816e2fb60..e2abe3ddd2448b896817b3d205dbf48b14866157 100644 (file)
@@ -158,10 +158,10 @@ typedef enum __device_msg_level {
 /*
  * Enum of context types for SendPacket
  */
-typedef enum _CONTEXT_TYPE {
-    CONTEXT_DATA_PACKET = 1,
-    CONTEXT_MGMT_PACKET
-} CONTEXT_TYPE;
+enum {
+       CONTEXT_DATA_PACKET = 1,
+       CONTEXT_MGMT_PACKET
+};
 
 /* RCB (Receive Control Block) */
 struct vnt_rcb {
@@ -180,9 +180,7 @@ struct vnt_usb_send_context {
        struct sk_buff *pPacket;
        struct urb *pUrb;
        unsigned int uBufLen;
-       CONTEXT_TYPE Type;
-       struct ethhdr sEthHeader;
-       void *Next;
+       u8 type;
        bool bBoolInUse;
        unsigned char Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS];
 };
@@ -206,12 +204,10 @@ typedef struct _DEFAULT_CONFIG {
 /*
  * Structure to keep track of USB interrupt packets
  */
-typedef struct {
-    unsigned int            uDataLen;
-    u8 *           pDataBuf;
-  /* struct urb *pUrb; */
-    bool            bInUse;
-} INT_BUFFER, *PINT_BUFFER;
+struct vnt_interrupt_buffer {
+       u8 *data_buf;
+       bool in_use;
+};
 
 /*++ NDIS related */
 
@@ -280,16 +276,6 @@ typedef struct tagSPMKIDCandidateEvent {
     PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST];
 } SPMKIDCandidateEvent, *PSPMKIDCandidateEvent;
 
-/*++ 802.11h related */
-#define MAX_QUIET_COUNT     8
-
-typedef struct tagSQuietControl {
-    bool        bEnable;
-    u32       dwStartTime;
-    u8        byPeriod;
-    u16        wDuration;
-} SQuietControl, *PSQuietControl;
-
 /* The receive duplicate detection cache entry */
 typedef struct tagSCacheEntry{
     u16        wFmSequence;
@@ -369,8 +355,6 @@ struct vnt_private {
 
        OPTIONS sOpts;
 
-       struct tasklet_struct CmdWorkItem;
-       struct tasklet_struct EventWorkItem;
        struct work_struct read_work_item;
        struct work_struct rx_mng_work_item;
 
@@ -420,28 +404,11 @@ struct vnt_private {
        struct vnt_tx_pkt_info pkt_info[16];
 
        /* Variables to track resources for the Interrupt In Pipe */
-       INT_BUFFER intBuf;
-       int bEventAvailable;
+       struct vnt_interrupt_buffer int_buf;
 
        /* default config from file by user setting */
        DEFAULT_CONFIG config_file;
 
-       /* Statistic for USB */
-       unsigned long ulBulkInPosted;
-       unsigned long ulBulkInError;
-       unsigned long ulBulkInContCRCError;
-       unsigned long ulBulkInBytesRead;
-
-       unsigned long ulBulkOutPosted;
-       unsigned long ulBulkOutError;
-       unsigned long ulBulkOutContCRCError;
-       unsigned long ulBulkOutBytesWrite;
-
-       unsigned long ulIntInPosted;
-       unsigned long ulIntInError;
-       unsigned long ulIntInContCRCError;
-       unsigned long ulIntInBytesRead;
-
        /* Version control */
        u16 wFirmwareVersion;
        u8 byLocalID;
@@ -462,11 +429,6 @@ struct vnt_private {
        int bExistSWNetAddr;
 
        /* Maintain statistical debug info. */
-       unsigned long packetsReceived;
-       unsigned long packetsReceivedDropped;
-       unsigned long packetsReceivedOverflow;
-       unsigned long packetsSent;
-       unsigned long packetsSentDropped;
        unsigned long SendContextsInUse;
        unsigned long RcvBuffersInUse;
 
@@ -791,5 +753,6 @@ struct vnt_private {
                                  (fMP_DISCONNECTED | fMP_RESET_IN_PROGRESS | fMP_HALT_IN_PROGRESS | fMP_INIT_IN_PROGRESS | fMP_SURPRISE_REMOVED)) == 0)
 
 int device_alloc_frag_buf(struct vnt_private *, PSDeFragControlBlock pDeF);
+void vnt_configure_filter(struct vnt_private *);
 
 #endif
index 03351e741bd3a17fd1e1737a383bd3d80ffb9176..4ccaa7e29a1c610c3e7681cf41d5ff6c84bd49f0 100644 (file)
@@ -1227,14 +1227,13 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
     if (is_multicast_ether_addr((u8 *)(skb->data+cbHeaderOffset))) {
        if (pMgmt->sNodeDBTable[0].bPSEnable) {
 
-           skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz);
+           skbcpy = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz);
 
         // if any node in PS mode, buffer packet until DTIM.
            if (skbcpy == NULL) {
                DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n");
            }
            else {
-               skbcpy->dev = pDevice->dev;
                skbcpy->len = FrameSize;
                memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize);
                skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy);
@@ -1295,63 +1294,66 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
 
 void RXvWorkItem(struct work_struct *work)
 {
-       struct vnt_private *pDevice =
+       struct vnt_private *priv =
                container_of(work, struct vnt_private, read_work_item);
-       int ntStatus;
-       struct vnt_rcb *pRCB = NULL;
+       int status;
+       struct vnt_rcb *rcb = NULL;
 
-       if (pDevice->Flags & fMP_DISCONNECTED)
+       if (priv->Flags & fMP_DISCONNECTED)
                return;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
-    spin_lock_irq(&pDevice->lock);
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
 
-    while ((pDevice->Flags & fMP_POST_READS) &&
-            MP_IS_READY(pDevice) &&
-            (pDevice->NumRecvFreeList != 0) ) {
-        pRCB = pDevice->FirstRecvFreeList;
-        pDevice->NumRecvFreeList--;
-        DequeueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList);
-        ntStatus = PIPEnsBulkInUsbRead(pDevice, pRCB);
-    }
-    pDevice->bIsRxWorkItemQueued = false;
-    spin_unlock_irq(&pDevice->lock);
+       spin_lock_irq(&priv->lock);
+
+       while ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) &&
+                       (priv->NumRecvFreeList != 0)) {
+               rcb = priv->FirstRecvFreeList;
+
+               priv->NumRecvFreeList--;
+
+               DequeueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList);
+
+               status = PIPEnsBulkInUsbRead(priv, rcb);
+       }
 
+       priv->bIsRxWorkItemQueued = false;
+
+       spin_unlock_irq(&priv->lock);
 }
 
-void RXvFreeRCB(struct vnt_rcb *pRCB, int bReAllocSkb)
+void RXvFreeRCB(struct vnt_rcb *rcb, int re_alloc_skb)
 {
-       struct vnt_private *pDevice = pRCB->pDevice;
+       struct vnt_private *priv = rcb->pDevice;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
 
-       if (bReAllocSkb == false) {
-               kfree_skb(pRCB->skb);
-               bReAllocSkb = true;
+       if (re_alloc_skb == false) {
+               kfree_skb(rcb->skb);
+               re_alloc_skb = true;
        }
 
-    if (bReAllocSkb == true) {
-        pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        // todo error handling
-        if (pRCB->skb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to re-alloc rx skb\n");
-        }else {
-            pRCB->skb->dev = pDevice->dev;
-        }
-    }
-    //
-    // Insert the RCB back in the Recv free list
-    //
-    EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
-    pDevice->NumRecvFreeList++;
+       if (re_alloc_skb == true) {
+               rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz);
+               /* TODO error handling */
+               if (!rcb->skb) {
+                       DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+                               " Failed to re-alloc rx skb\n");
+               }
+       }
 
-    if ((pDevice->Flags & fMP_POST_READS) && MP_IS_READY(pDevice) &&
-        (pDevice->bIsRxWorkItemQueued == false) ) {
+       /* Insert the RCB back in the Recv free list */
+       EnqueueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList, rcb);
+       priv->NumRecvFreeList++;
 
-        pDevice->bIsRxWorkItemQueued = true;
-       schedule_work(&pDevice->read_work_item);
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList);
+       if ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) &&
+                       (priv->bIsRxWorkItemQueued == false)) {
+               priv->bIsRxWorkItemQueued = true;
+               schedule_work(&priv->read_work_item);
+       }
+
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",
+                       priv->NumRecvFreeList, priv->NumRecvMngList);
 }
 
 void RXvMngWorkItem(struct work_struct *work)
index 34c45280a9c17bcb6cec5808f8661689663fca2b..cca56b2f243dd83c0bc78dd2b82d8a7f19537119 100644 (file)
@@ -84,7 +84,7 @@ void INTnsProcessData(struct vnt_private *priv)
 
        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n");
 
-       int_data = (struct vnt_interrupt_data *)priv->intBuf.pDataBuf;
+       int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
 
        if (int_data->tsr0 & TSR_VALID) {
                if (int_data->tsr0 & (TSR_TMO | TSR_RETRYTMO))
@@ -178,8 +178,8 @@ void INTnsProcessData(struct vnt_private *priv)
                        bScheduleCommand((void *) priv,
                                        WLAN_CMD_RADIO,
                                        NULL);
-       priv->intBuf.uDataLen = 0;
-       priv->intBuf.bInUse = false;
+
+       priv->int_buf.in_use = false;
 
        stats->tx_errors = priv->wstats.discard.retries;
        stats->tx_dropped = priv->wstats.discard.retries;
index bea1ad93336ab76f65d23eac8bc2eba476930295..7dd885fe2010c3e1e1909a7b43ec13e5be53acf2 100644 (file)
@@ -749,44 +749,47 @@ err_nomem:
        return rc;
 }
 
-static void device_free_tx_bufs(struct vnt_private *pDevice)
+static void device_free_tx_bufs(struct vnt_private *priv)
 {
-       struct vnt_usb_send_context *pTxContext;
-    int ii;
+       struct vnt_usb_send_context *tx_context;
+       int ii;
 
-    for (ii = 0; ii < pDevice->cbTD; ii++) {
+       for (ii = 0; ii < priv->cbTD; ii++) {
+               tx_context = priv->apTD[ii];
+               /* deallocate URBs */
+               if (tx_context->pUrb) {
+                       usb_kill_urb(tx_context->pUrb);
+                       usb_free_urb(tx_context->pUrb);
+               }
 
-        pTxContext = pDevice->apTD[ii];
-       /* deallocate URBs */
-        if (pTxContext->pUrb) {
-            usb_kill_urb(pTxContext->pUrb);
-            usb_free_urb(pTxContext->pUrb);
-        }
-        kfree(pTxContext);
-    }
-    return;
+               kfree(tx_context);
+       }
+
+       return;
 }
 
-static void device_free_rx_bufs(struct vnt_private *pDevice)
+static void device_free_rx_bufs(struct vnt_private *priv)
 {
-       struct vnt_rcb *pRCB;
+       struct vnt_rcb *rcb;
        int ii;
 
-    for (ii = 0; ii < pDevice->cbRD; ii++) {
+       for (ii = 0; ii < priv->cbRD; ii++) {
+               rcb = priv->apRCB[ii];
 
-        pRCB = pDevice->apRCB[ii];
-       /* deallocate URBs */
-        if (pRCB->pUrb) {
-            usb_kill_urb(pRCB->pUrb);
-            usb_free_urb(pRCB->pUrb);
-        }
-       /* deallocate skb */
-        if (pRCB->skb)
-            dev_kfree_skb(pRCB->skb);
-    }
-    kfree(pDevice->pRCBMem);
+               /* deallocate URBs */
+               if (rcb->pUrb) {
+                       usb_kill_urb(rcb->pUrb);
+                       usb_free_urb(rcb->pUrb);
+               }
 
-    return;
+               /* deallocate skb */
+               if (rcb->skb)
+                       dev_kfree_skb(rcb->skb);
+       }
+
+       kfree(priv->pRCBMem);
+
+       return;
 }
 
 static void usb_device_reset(struct vnt_private *pDevice)
@@ -798,95 +801,109 @@ static void usb_device_reset(struct vnt_private *pDevice)
        return ;
 }
 
-static void device_free_int_bufs(struct vnt_private *pDevice)
+static void device_free_int_bufs(struct vnt_private *priv)
 {
-    kfree(pDevice->intBuf.pDataBuf);
-    return;
+       kfree(priv->int_buf.data_buf);
+
+       return;
 }
 
-static bool device_alloc_bufs(struct vnt_private *pDevice)
+static bool device_alloc_bufs(struct vnt_private *priv)
 {
-       struct vnt_usb_send_context *pTxContext;
-       struct vnt_rcb *pRCB;
+       struct vnt_usb_send_context *tx_context;
+       struct vnt_rcb *rcb;
        int ii;
 
-    for (ii = 0; ii < pDevice->cbTD; ii++) {
+       for (ii = 0; ii < priv->cbTD; ii++) {
+               tx_context = kmalloc(sizeof(struct vnt_usb_send_context),
+                                                               GFP_KERNEL);
+               if (tx_context == NULL) {
+                       DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+                               "%s : allocate tx usb context failed\n",
+                                       priv->dev->name);
+                       goto free_tx;
+               }
 
-       pTxContext = kmalloc(sizeof(struct vnt_usb_send_context), GFP_KERNEL);
-        if (pTxContext == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate tx usb context failed\n", pDevice->dev->name);
-            goto free_tx;
-        }
-        pDevice->apTD[ii] = pTxContext;
-       pTxContext->pDevice = (void *) pDevice;
-       /* allocate URBs */
-        pTxContext->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
-        if (pTxContext->pUrb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "alloc tx urb failed\n");
-            goto free_tx;
-        }
-        pTxContext->bBoolInUse = false;
-    }
+               priv->apTD[ii] = tx_context;
+               tx_context->pDevice = priv;
 
-    /* allocate RCB mem */
-       pDevice->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * pDevice->cbRD),
+               /* allocate URBs */
+               tx_context->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+               if (tx_context->pUrb == NULL) {
+                       DBG_PRT(MSG_LEVEL_ERR,
+                               KERN_ERR "alloc tx urb failed\n");
+                       goto free_tx;
+               }
+
+               tx_context->bBoolInUse = false;
+       }
+
+       /* allocate RCB mem */
+       priv->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * priv->cbRD),
                                                                GFP_KERNEL);
-    if (pDevice->pRCBMem == NULL) {
-        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : alloc rx usb context failed\n", pDevice->dev->name);
-        goto free_tx;
-    }
+       if (priv->pRCBMem == NULL) {
+               DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+                       "%s : alloc rx usb context failed\n",
+                               priv->dev->name);
+               goto free_tx;
+       }
+
+       priv->FirstRecvFreeList = NULL;
+       priv->LastRecvFreeList = NULL;
+       priv->FirstRecvMngList = NULL;
+       priv->LastRecvMngList = NULL;
+       priv->NumRecvFreeList = 0;
 
-    pDevice->FirstRecvFreeList = NULL;
-    pDevice->LastRecvFreeList = NULL;
-    pDevice->FirstRecvMngList = NULL;
-    pDevice->LastRecvMngList = NULL;
-    pDevice->NumRecvFreeList = 0;
+       rcb = (struct vnt_rcb *)priv->pRCBMem;
 
-       pRCB = (struct vnt_rcb *)pDevice->pRCBMem;
+       for (ii = 0; ii < priv->cbRD; ii++) {
+               priv->apRCB[ii] = rcb;
+               rcb->pDevice = priv;
 
-    for (ii = 0; ii < pDevice->cbRD; ii++) {
+               /* allocate URBs */
+               rcb->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+               if (rcb->pUrb == NULL) {
+                       DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+                               " Failed to alloc rx urb\n");
+                       goto free_rx_tx;
+               }
 
-        pDevice->apRCB[ii] = pRCB;
-       pRCB->pDevice = (void *) pDevice;
-       /* allocate URBs */
-        pRCB->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+               rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz);
+               if (rcb->skb == NULL) {
+                       DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+                                               " Failed to alloc rx skb\n");
+                       goto free_rx_tx;
+               }
 
-        if (pRCB->pUrb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx urb\n");
-            goto free_rx_tx;
-        }
-        pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        if (pRCB->skb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx skb\n");
-            goto free_rx_tx;
-        }
-        pRCB->skb->dev = pDevice->dev;
-        pRCB->bBoolInUse = false;
-        EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
-        pDevice->NumRecvFreeList++;
-        pRCB++;
-    }
+               rcb->bBoolInUse = false;
+
+               EnqueueRCB(priv->FirstRecvFreeList,
+                                               priv->LastRecvFreeList, rcb);
 
-       pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
-       if (pDevice->pInterruptURB == NULL) {
-           DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n");
-           goto free_rx_tx;
+               priv->NumRecvFreeList++;
+               rcb++;
        }
 
-    pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
-       if (pDevice->intBuf.pDataBuf == NULL) {
-           DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n");
-           usb_free_urb(pDevice->pInterruptURB);
-           goto free_rx_tx;
+       priv->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
+       if (priv->pInterruptURB == NULL) {
+               DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc int urb\n");
+               goto free_rx_tx;
        }
 
-    return true;
+       priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
+       if (priv->int_buf.data_buf == NULL) {
+               DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc int buf\n");
+               usb_free_urb(priv->pInterruptURB);
+               goto free_rx_tx;
+       }
+
+       return true;
 
 free_rx_tx:
-    device_free_rx_bufs(pDevice);
+       device_free_rx_bufs(priv);
 
 free_tx:
-    device_free_tx_bufs(pDevice);
+       device_free_tx_bufs(priv);
 
        return false;
 }
@@ -931,13 +948,11 @@ static void device_free_frag_bufs(struct vnt_private *pDevice)
 int device_alloc_frag_buf(struct vnt_private *pDevice,
                PSDeFragControlBlock pDeF)
 {
+       pDeF->skb = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz);
+       if (!pDeF->skb)
+               return false;
 
-    pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-    if (pDeF->skb == NULL)
-        return false;
-    pDeF->skb->dev = pDevice->dev;
-
-    return true;
+       return true;
 }
 
 static int  device_open(struct net_device *dev)
@@ -974,8 +989,6 @@ static int  device_open(struct net_device *dev)
                goto free_all;
        }
 
-    device_set_multi(pDevice->dev);
-
     /* init for key management */
     KeyvInitTable(pDevice,&pDevice->sKey);
        memcpy(pDevice->vnt_mgmt.abyMACAddr,
@@ -992,15 +1005,12 @@ static int  device_open(struct net_device *dev)
 
     vMgrObjectInit(pDevice);
 
-    tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice);
-
        schedule_delayed_work(&pDevice->second_callback_work, HZ);
 
        pDevice->int_interval = 100;  /* max 100 microframes */
     pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 
     pDevice->bIsRxWorkItemQueued = true;
-    pDevice->bEventAvailable = false;
 
    pDevice->bWPADEVUp = false;
      pDevice->bwextstep0 = false;
@@ -1096,8 +1106,6 @@ static int device_close(struct net_device *dev)
        cancel_work_sync(&pDevice->rx_mng_work_item);
        cancel_work_sync(&pDevice->read_work_item);
 
-    tasklet_kill(&pDevice->EventWorkItem);
-
    pDevice->bRoaming = false;
    pDevice->bIsRoaming = false;
    pDevice->bEnableRoaming = false;
@@ -1349,14 +1357,26 @@ static int Read_config_file(struct vnt_private *pDevice)
 static void device_set_multi(struct net_device *dev)
 {
        struct vnt_private *priv = netdev_priv(dev);
+       unsigned long flags;
+
+       if (priv->flags & DEVICE_FLAGS_OPENED) {
+               spin_lock_irqsave(&priv->lock, flags);
+
+               bScheduleCommand(priv, WLAN_CMD_CONFIGURE_FILTER, NULL);
+
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+}
+
+void vnt_configure_filter(struct vnt_private *priv)
+{
+       struct net_device *dev = priv->dev;
        struct vnt_manager *mgmt = &priv->vnt_mgmt;
        struct netdev_hw_addr *ha;
        u64 mc_filter = 0;
        u8 tmp = 0;
        int rc;
 
-       spin_lock_irq(&priv->lock);
-
        rc = CONTROLnsRequestIn(priv, MESSAGE_TYPE_READ,
                MAC_REG_RCR, MESSAGE_REQUEST_MACREG, 1, &tmp);
        if (rc == 0)
@@ -1403,8 +1423,6 @@ static void device_set_multi(struct net_device *dev)
 
        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
                                "priv->byRxMode out= %x\n", priv->byRxMode);
-
-       spin_unlock_irq(&priv->lock);
 }
 
 static struct net_device_stats *device_get_stats(struct net_device *dev)
index 92146e50315624f785d7dde47f2cd39e641e5953..7083af32e43c35ef7075ed7fd8e55c7366ca7dac 100644 (file)
@@ -1610,7 +1610,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
@@ -1702,7 +1702,7 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
     pTX_Buffer->byType = 0x01;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     PIPEnsSendBulkOut(pDevice,pContext);
@@ -2050,7 +2050,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = skb;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
@@ -2440,11 +2440,11 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
     pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = skb;
-    pContext->Type = CONTEXT_DATA_PACKET;
+    pContext->type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
     s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
-                       &pContext->sEthHeader.h_dest[0],
+                       &pDevice->sTxEthHeader.h_dest[0],
                        (u16)(BytesToWrite-uHeaderLen),
                        pTX_Buffer->fifo_head.wFIFOCtl);
 
@@ -2594,11 +2594,11 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
     pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_DATA_PACKET;
+    pContext->type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
     s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
-               &pContext->sEthHeader.h_dest[0],
+               &pDevice->sTxEthHeader.h_dest[0],
                (u16)(BytesToWrite - uHeaderLen),
                pTX_Buffer->fifo_head.wFIFOCtl);
 
index 119f656032418955c647fd569d2b59910fb1bbe5..a4a4bf24aad6f3b98dfb73d88b2219c1940a0107 100644 (file)
@@ -295,40 +295,38 @@ static void s_nsControlInUsbIoCompleteRead(struct urb *urb)
  *
  */
 
-int PIPEnsInterruptRead(struct vnt_private *pDevice)
+int PIPEnsInterruptRead(struct vnt_private *priv)
 {
-       int ntStatus = STATUS_FAILURE;
+       int status = STATUS_FAILURE;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                       "---->s_nsStartInterruptUsbRead()\n");
 
-    if(pDevice->intBuf.bInUse == true){
-        return (STATUS_FAILURE);
-    }
-    pDevice->intBuf.bInUse = true;
-//    pDevice->bEventAvailable = false;
-    pDevice->ulIntInPosted++;
-
-    //
-    // Now that we have created the urb, we will send a
-    // request to the USB device object.
-    //
-    pDevice->pInterruptURB->interval = pDevice->int_interval;
-
-usb_fill_bulk_urb(pDevice->pInterruptURB,
-               pDevice->usb,
-               usb_rcvbulkpipe(pDevice->usb, 1),
-               (void *) pDevice->intBuf.pDataBuf,
+       if (priv->int_buf.in_use == true)
+               return STATUS_FAILURE;
+
+       priv->int_buf.in_use = true;
+
+       usb_fill_int_urb(priv->pInterruptURB,
+               priv->usb,
+               usb_rcvbulkpipe(priv->usb, 1),
+               priv->int_buf.data_buf,
                MAX_INTERRUPT_SIZE,
                s_nsInterruptUsbIoCompleteRead,
-               pDevice);
+               priv,
+               priv->int_interval);
 
-       ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
-       if (ntStatus != 0) {
-           DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
-    }
+       status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
+       if (status) {
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                       "Submit int URB failed %d\n", status);
+               priv->int_buf.in_use = false;
+       }
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
-    return ntStatus;
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+               "<----s_nsStartInterruptUsbRead Return(%x)\n", status);
+
+       return status;
 }
 
 /*
@@ -348,7 +346,7 @@ usb_fill_bulk_urb(pDevice->pInterruptURB,
 
 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
 {
-       struct vnt_private *priv = (struct vnt_private *)urb->context;
+       struct vnt_private *priv = urb->context;
        int status;
 
        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
@@ -361,7 +359,7 @@ static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               priv->intBuf.bInUse = false;
+               priv->int_buf.in_use = false;
                return;
        default:
                break;
@@ -373,15 +371,11 @@ static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
                "s_nsInterruptUsbIoCompleteRead Status %d\n", status);
 
        if (status != STATUS_SUCCESS) {
-               priv->ulBulkInError++;
-               priv->intBuf.bInUse = false;
+               priv->int_buf.in_use = false;
 
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
                        "IntUSBIoCompleteControl STATUS = %d\n", status);
        } else {
-               priv->ulIntInBytesRead += (unsigned long)urb->actual_length;
-               priv->ulIntInContCRCError = 0;
-               priv->bEventAvailable = true;
                INTnsProcessData(priv);
        }
 
@@ -390,7 +384,7 @@ static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
                        "Submit int URB failed %d\n", status);
        } else {
-               priv->intBuf.bInUse = true;
+               priv->int_buf.in_use = true;
        }
 
        return;
@@ -410,45 +404,41 @@ static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
  *
  */
 
-int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, struct vnt_rcb *pRCB)
+int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
 {
-       int ntStatus = 0;
-       struct urb *pUrb;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
+       int status = 0;
+       struct urb *urb;
 
-    if (pDevice->Flags & fMP_DISCONNECTED)
-        return STATUS_FAILURE;
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
 
-    pDevice->ulBulkInPosted++;
+       if (priv->Flags & fMP_DISCONNECTED)
+               return STATUS_FAILURE;
 
-       pUrb = pRCB->pUrb;
-    //
-    // Now that we have created the urb, we will send a
-    // request to the USB device object.
-    //
-    if (pRCB->skb == NULL) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
-        return ntStatus;
-    }
+       urb = rcb->pUrb;
+       if (rcb->skb == NULL) {
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rcb->skb is null\n");
+               return status;
+       }
 
-       usb_fill_bulk_urb(pUrb,
-               pDevice->usb,
-               usb_rcvbulkpipe(pDevice->usb, 2),
-               (void *) (pRCB->skb->data),
+       usb_fill_bulk_urb(urb,
+               priv->usb,
+               usb_rcvbulkpipe(priv->usb, 2),
+               (void *) (rcb->skb->data),
                MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
                s_nsBulkInUsbIoCompleteRead,
-               pRCB);
+               rcb);
 
-       ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
-       if (ntStatus != 0) {
-               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status != 0) {
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                               "Submit Rx URB failed %d\n", status);
                return STATUS_FAILURE ;
        }
-    pRCB->Ref = 1;
-    pRCB->bBoolInUse= true;
 
-    return ntStatus;
+       rcb->Ref = 1;
+       rcb->bBoolInUse = true;
+
+       return status;
 }
 
 /*
@@ -468,51 +458,47 @@ int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, struct vnt_rcb *pRCB)
 
 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
 {
-       struct vnt_rcb *pRCB = (struct vnt_rcb *)urb->context;
-       struct vnt_private *pDevice = pRCB->pDevice;
-       unsigned long   bytesRead;
-       int bIndicateReceive = false;
-       int bReAllocSkb = false;
-       int status;
+       struct vnt_rcb *rcb = urb->context;
+       struct vnt_private *priv = rcb->pDevice;
+       int re_alloc_skb = false;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
-    status = urb->status;
-    bytesRead = urb->actual_length;
-
-    if (status) {
-        pDevice->ulBulkInError++;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
-//todo...xxxxxx
-//        if (status == USBD_STATUS_CRC) {
-//            pDevice->ulBulkInContCRCError++;
-//        }
-//        if (status == STATUS_DEVICE_NOT_CONNECTED )
-//        {
-//            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
-//        }
-    } else {
-       if (bytesRead)
-               bIndicateReceive = true;
-        pDevice->ulBulkInContCRCError = 0;
-        pDevice->ulBulkInBytesRead += bytesRead;
-    }
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
 
-    if (bIndicateReceive) {
-        spin_lock(&pDevice->lock);
-        if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == true)
-            bReAllocSkb = true;
-        spin_unlock(&pDevice->lock);
-    }
-    pRCB->Ref--;
-    if (pRCB->Ref == 0)
-    {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
-        spin_lock(&pDevice->lock);
-        RXvFreeRCB(pRCB, bReAllocSkb);
-        spin_unlock(&pDevice->lock);
-    }
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       case -ETIMEDOUT:
+       default:
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                               "BULK In failed %d\n", urb->status);
+               break;
+       }
+
+       if (urb->actual_length) {
+               spin_lock(&priv->lock);
+
+               if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
+                       re_alloc_skb = true;
+
+               spin_unlock(&priv->lock);
+       }
 
-    return;
+       rcb->Ref--;
+       if (rcb->Ref == 0) {
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d\n",
+                                                       priv->NumRecvFreeList);
+               spin_lock(&priv->lock);
+
+               RXvFreeRCB(rcb, re_alloc_skb);
+
+               spin_unlock(&priv->lock);
+       }
+
+       return;
 }
 
 /*
@@ -529,53 +515,40 @@ static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
  *
  */
 
-int PIPEnsSendBulkOut(struct vnt_private *pDevice,
-                               struct vnt_usb_send_context *pContext)
+int PIPEnsSendBulkOut(struct vnt_private *priv,
+                               struct vnt_usb_send_context *context)
 {
        int status;
-       struct urb          *pUrb;
+       struct urb *urb;
 
-    pDevice->bPWBitOn = false;
+       priv->bPWBitOn = false;
 
-/*
-    if (pDevice->pPendingBulkOutContext != NULL) {
-        pDevice->NumContextsQueued++;
-        EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
-        status = STATUS_PENDING;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
-        return status;
-    }
-*/
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
-
-    if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) {
-
-        pUrb = pContext->pUrb;
-        pDevice->ulBulkOutPosted++;
-//        pDevice->pPendingBulkOutContext = pContext;
-        usb_fill_bulk_urb(
-                   pUrb,
-                       pDevice->usb,
-                   usb_sndbulkpipe(pDevice->usb, 3),
-                   (void *) &(pContext->Data[0]),
-                       pContext->uBufLen,
-                       s_nsBulkOutIoCompleteWrite,
-                       pContext);
-
-       status = usb_submit_urb(pUrb, GFP_ATOMIC);
-       if (status != 0)
-       {
-               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
-               pContext->bBoolInUse = false;
-               return STATUS_FAILURE;
-       }
-        return STATUS_PENDING;
-    }
-    else {
-        pContext->bBoolInUse = false;
-        return STATUS_RESOURCES;
-    }
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
+
+       if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
+               context->bBoolInUse = false;
+               return STATUS_RESOURCES;
+       }
+
+       urb = context->pUrb;
+
+       usb_fill_bulk_urb(urb,
+                       priv->usb,
+                       usb_sndbulkpipe(priv->usb, 3),
+                       context->Data,
+                       context->uBufLen,
+                       s_nsBulkOutIoCompleteWrite,
+                       context);
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status != 0) {
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                               "Submit Tx URB failed %d\n", status);
+               context->bBoolInUse = false;
+               return STATUS_FAILURE;
+       }
+
+       return STATUS_PENDING;
 }
 
 /*
@@ -608,68 +581,49 @@ int PIPEnsSendBulkOut(struct vnt_private *pDevice,
 
 static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
 {
-       struct vnt_private *pDevice;
-       int status;
-       CONTEXT_TYPE ContextType;
-       unsigned long ulBufLen;
-       struct vnt_usb_send_context *pContext;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
-    //
-    // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
-    //
-       pContext = (struct vnt_usb_send_context *)urb->context;
-
-    pDevice = pContext->pDevice;
-    ContextType = pContext->Type;
-    ulBufLen = pContext->uBufLen;
-
-    if (!netif_device_present(pDevice->dev))
-           return;
-
-   //
-    // Perform various IRP, URB, and buffer 'sanity checks'
-    //
+       struct vnt_usb_send_context *context = urb->context;
+       struct vnt_private *priv = context->pDevice;
+       u8 context_type = context->type;
 
-    status = urb->status;
+       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
 
-    if(status == STATUS_SUCCESS) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
-        pDevice->ulBulkOutBytesWrite += ulBufLen;
-        pDevice->ulBulkOutContCRCError = 0;
-    } else {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
-        pDevice->ulBulkOutError++;
-    }
+       switch (urb->status) {
+       case 0:
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                       "Write %d bytes\n", context->uBufLen);
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               context->bBoolInUse = false;
+               return;
+       case -ETIMEDOUT:
+       default:
+               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                               "BULK Out failed %d\n", urb->status);
+               break;
+       }
 
-//    pDevice->ulCheckForHangCount = 0;
-//    pDevice->pPendingBulkOutContext = NULL;
+       if (!netif_device_present(priv->dev))
+               return;
 
-    if ( CONTEXT_DATA_PACKET == ContextType ) {
-        // Indicate to the protocol the status of the sent packet and return
-        // ownership of the packet.
-           if (pContext->pPacket != NULL) {
-               dev_kfree_skb_irq(pContext->pPacket);
-               pContext->pPacket = NULL;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
-           }
+       if (CONTEXT_DATA_PACKET == context_type) {
+               if (context->pPacket != NULL) {
+                       dev_kfree_skb_irq(context->pPacket);
+                       context->pPacket = NULL;
+                       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+                               "tx  %d bytes\n", context->uBufLen);
+               }
 
-        pDevice->dev->trans_start = jiffies;
+               priv->dev->trans_start = jiffies;
+       }
 
-        if (status == STATUS_SUCCESS) {
-            pDevice->packetsSent++;
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
-            pDevice->packetsSentDropped++;
-        }
+       if (priv->bLinkPass == true) {
+               if (netif_queue_stopped(priv->dev))
+                       netif_wake_queue(priv->dev);
+       }
 
-    }
-    if (pDevice->bLinkPass == true) {
-        if (netif_queue_stopped(pDevice->dev))
-            netif_wake_queue(pDevice->dev);
-    }
-    pContext->bBoolInUse = false;
+       context->bBoolInUse = false;
 
-    return;
+       return;
 }
index 6b9522914634fa3a7db5b69e89483db648ea8823..3cf3f24247a3f847d59be8dc702dbf831fe098e5 100644 (file)
@@ -293,17 +293,11 @@ void vRunCommand(struct work_struct *work)
        case WLAN_CMD_SCAN_START:
 
                pDevice->byReAssocCount = 0;
-               if (pDevice->bRadioOff == true) {
-                       s_bCommandComplete(pDevice);
-                       spin_unlock_irq(&pDevice->lock);
-                       return;
-               }
+               if (pDevice->bRadioOff == true)
+                       break;
 
-               if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-                       s_bCommandComplete(pDevice);
-                       spin_unlock_irq(&pDevice->lock);
-                       return;
-               }
+               if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
+                       break;
 
                pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
 
@@ -311,16 +305,12 @@ void vRunCommand(struct work_struct *work)
                        pMgmt->uScanChannel = pDevice->byMinChannel;
                if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
                        pDevice->eCommandState = WLAN_CMD_SCAN_END;
-                       s_bCommandComplete(pDevice);
-                       spin_unlock_irq(&pDevice->lock);
-                       return;
+                       break;
                } else {
                        if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) {
                                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d\n", pMgmt->uScanChannel);
                                pMgmt->uScanChannel++;
-                               s_bCommandComplete(pDevice);
-                               spin_unlock_irq(&pDevice->lock);
-                               return;
+                               break;
                        }
                        if (pMgmt->uScanChannel == pDevice->byMinChannel) {
                                // pMgmt->eScanType = WMAC_SCAN_ACTIVE;          //mike mark
@@ -420,16 +410,13 @@ void vRunCommand(struct work_struct *work)
                memset(&wrqu, 0, sizeof(wrqu));
                wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
 
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_DISASSOCIATE_START:
                pDevice->byReAssocCount = 0;
                if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
                    (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
-                       s_bCommandComplete(pDevice);
-                       spin_unlock_irq(&pDevice->lock);
-                       return;
+                       break;
                } else {
                        pDevice->bwextstep0 = false;
                        pDevice->bwextstep1 = false;
@@ -458,17 +445,14 @@ void vRunCommand(struct work_struct *work)
                netif_stop_queue(pDevice->dev);
                if (pDevice->bNeedRadioOFF == true)
                        CARDbRadioPowerOff(pDevice);
-               s_bCommandComplete(pDevice);
+
                break;
 
        case WLAN_CMD_SSID_START:
 
                pDevice->byReAssocCount = 0;
-               if (pDevice->bRadioOff == true) {
-                       s_bCommandComplete(pDevice);
-                       spin_unlock_irq(&pDevice->lock);
-                       return;
-               }
+               if (pDevice->bRadioOff == true)
+                       break;
 
                memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID,
                       ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN);
@@ -489,11 +473,9 @@ void vRunCommand(struct work_struct *work)
                if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
                    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
                        if (pItemSSID->len == pItemSSIDCurr->len) {
-                               if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
-                                       s_bCommandComplete(pDevice);
-                                       spin_unlock_irq(&pDevice->lock);
-                                       return;
-                               }
+                               if (!memcmp(pItemSSID->abySSID,
+                                       pItemSSIDCurr->abySSID, pItemSSID->len))
+                                       break;
                        }
                        netif_stop_queue(pDevice->dev);
                        pDevice->bLinkPass = false;
@@ -582,7 +564,6 @@ void vRunCommand(struct work_struct *work)
                                }
                        }
                }
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_AUTHENTICATE_WAIT:
@@ -612,7 +593,6 @@ void vRunCommand(struct work_struct *work)
                }
                pDevice->byLinkWaitCount = 0;
 
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_ASSOCIATE_WAIT:
@@ -647,7 +627,6 @@ void vRunCommand(struct work_struct *work)
                        return;
                }
 
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_AP_MODE_START:
@@ -683,7 +662,6 @@ void vRunCommand(struct work_struct *work)
                        ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER);
                        schedule_delayed_work(&pDevice->second_callback_work, HZ);
                }
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_TX_PSPACKET_START:
@@ -738,8 +716,6 @@ void vRunCommand(struct work_struct *work)
                                pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
                        }
                }
-
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_RADIO_START:
@@ -760,11 +736,8 @@ void vRunCommand(struct work_struct *work)
                                        1,
                                        &byTmp);
 
-                       if (ntStatus != STATUS_SUCCESS) {
-                               s_bCommandComplete(pDevice);
-                               spin_unlock_irq(&pDevice->lock);
-                               return;
-                       }
+                       if (ntStatus != STATUS_SUCCESS)
+                               break;
                        if ((byTmp & GPIO3_DATA) == 0) {
                                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n");
                                // Old commands are useless.
@@ -833,7 +806,6 @@ void vRunCommand(struct work_struct *work)
                        }
                }
 
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_CHANGE_BBSENSITIVITY_START:
@@ -843,24 +815,20 @@ void vRunCommand(struct work_struct *work)
                BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change sensitivity pDevice->byBBVGACurrent = %x\n", pDevice->byBBVGACurrent);
                pDevice->bStopDataPkt = false;
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_TBTT_WAKEUP_START:
                PSbIsNextTBTTWakeUp(pDevice);
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_BECON_SEND_START:
                bMgrPrepareBeaconToSend(pDevice, pMgmt);
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_SETPOWER_START:
 
                RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel);
 
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_CHANGE_ANTENNA_START:
@@ -878,12 +846,10 @@ void vRunCommand(struct work_struct *work)
                        else
                                BBvSetAntennaMode(pDevice, ANT_RXA);
                }
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_REMOVE_ALLKEY_START:
                KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID);
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_MAC_DISPOWERSAVING_START:
@@ -898,7 +864,6 @@ void vRunCommand(struct work_struct *work)
                                        NULL
                                        );
                }
-               s_bCommandComplete(pDevice);
                break;
 
        case WLAN_CMD_11H_CHSW_START:
@@ -906,14 +871,17 @@ void vRunCommand(struct work_struct *work)
                pDevice->bChannelSwitch = false;
                pMgmt->uCurrChannel = pDevice->byNewChannel;
                pDevice->bStopDataPkt = false;
-               s_bCommandComplete(pDevice);
                break;
 
+       case WLAN_CMD_CONFIGURE_FILTER_START:
+               vnt_configure_filter(pDevice);
+               break;
        default:
-               s_bCommandComplete(pDevice);
                break;
        } //switch
 
+       s_bCommandComplete(pDevice);
+
        spin_unlock_irq(&pDevice->lock);
        return;
 }
@@ -1009,6 +977,11 @@ static int s_bCommandComplete(struct vnt_private *pDevice)
                        pDevice->eCommandState = WLAN_CMD_11H_CHSW_START;
                        break;
 
+               case WLAN_CMD_CONFIGURE_FILTER:
+                       pDevice->eCommandState =
+                                               WLAN_CMD_CONFIGURE_FILTER_START;
+                       break;
+
                default:
                        break;
                }
index caf2684ce9151f34961d5d203e4e7949c5d5b9da..736572101badce8191ec58b9f744f95cce8a282f 100644 (file)
@@ -51,7 +51,8 @@ typedef enum tagCMD_CODE {
     WLAN_CMD_REMOVE_ALLKEY,
     WLAN_CMD_MAC_DISPOWERSAVING,
     WLAN_CMD_11H_CHSW,
-    WLAN_CMD_RUN_AP
+    WLAN_CMD_RUN_AP,
+    WLAN_CMD_CONFIGURE_FILTER
 } CMD_CODE, *PCMD_CODE;
 
 #define CMD_Q_SIZE              32
@@ -96,6 +97,7 @@ typedef enum tagCMD_STATE {
     WLAN_CMD_REMOVE_ALLKEY_START,
     WLAN_CMD_MAC_DISPOWERSAVING_START,
     WLAN_CMD_11H_CHSW_START,
+    WLAN_CMD_CONFIGURE_FILTER_START,
     WLAN_CMD_IDLE
 } CMD_STATE, *PCMD_STATE;
 
index b3ff603e6225dec31b2c24cef8832e06365ffcf4..466804687fc04cdc9156419537899f4dda8fcaee 100644 (file)
@@ -1754,8 +1754,7 @@ static int xgifb_probe(struct pci_dev *pdev,
                dev_err(&pdev->dev, "Unable request memory size %x\n",
                       xgifb_info->video_size);
                dev_err(&pdev->dev,
-                       "Fatal error: Unable to reserve frame buffer memory. "
-                       "Is there another framebuffer driver active?\n");
+                       "Fatal error: Unable to reserve frame buffer memory. Is there another framebuffer driver active?\n");
                ret = -ENODEV;
                goto error_disable;
        }
@@ -2087,23 +2086,19 @@ static struct pci_driver xgifb_driver = {
 
 module_param(mode, charp, 0);
 MODULE_PARM_DESC(mode,
-       "Selects the desired default display mode in the format XxYxDepth "
-       "(eg. 1024x768x16).");
+       "Selects the desired default display mode in the format XxYxDepth (eg. 1024x768x16).");
 
 module_param(forcecrt2type, charp, 0);
 MODULE_PARM_DESC(forcecrt2type,
-       "Force the second display output type. Possible values are NONE, "
-       "LCD, TV, VGA, SVIDEO or COMPOSITE.");
+       "Force the second display output type. Possible values are NONE, LCD, TV, VGA, SVIDEO or COMPOSITE.");
 
 module_param(vesa, int, 0);
 MODULE_PARM_DESC(vesa,
-       "Selects the desired default display mode by VESA mode number "
-       "(eg. 0x117).");
+       "Selects the desired default display mode by VESA mode number (eg. 0x117).");
 
 module_param(filter, int, 0);
 MODULE_PARM_DESC(filter,
-       "Selects TV flicker filter type (only for systems with a SiS301 video bridge). "
-       "Possible values 0-7. Default: [no filter]).");
+       "Selects TV flicker filter type (only for systems with a SiS301 video bridge). Possible values 0-7. Default: [no filter]).");
 
 static int __init xgifb_init(void)
 {
index a4489444ffbc640d940869ca7de305b2ae6c4b58..42f18fc1067b63cd8c539959ae43e2548c53c34b 100644 (file)
@@ -1074,7 +1074,7 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
        struct scatterlist *psg;
        void *paddr, *addr;
        unsigned int i, len, left;
-       unsigned int offset = 0;
+       unsigned int offset = sg_off;
 
        left = sectors * dev->prot_length;
 
@@ -1084,11 +1084,10 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
                if (offset >= sg->length) {
                        sg = sg_next(sg);
                        offset = 0;
-                       sg_off = sg->offset;
                }
 
                paddr = kmap_atomic(sg_page(psg)) + psg->offset;
-               addr = kmap_atomic(sg_page(sg)) + sg_off;
+               addr = kmap_atomic(sg_page(sg)) + sg->offset + offset;
 
                if (read)
                        memcpy(paddr, addr, len);
@@ -1163,7 +1162,7 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
 {
        struct se_device *dev = cmd->se_dev;
        struct se_dif_v1_tuple *sdt;
-       struct scatterlist *dsg;
+       struct scatterlist *dsg, *psg = sg;
        sector_t sector = start;
        void *daddr, *paddr;
        int i, j, offset = sg_off;
@@ -1171,14 +1170,14 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
 
        for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) {
                daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
-               paddr = kmap_atomic(sg_page(sg)) + sg->offset;
+               paddr = kmap_atomic(sg_page(psg)) + sg->offset;
 
                for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) {
 
-                       if (offset >= sg->length) {
+                       if (offset >= psg->length) {
                                kunmap_atomic(paddr);
-                               sg = sg_next(sg);
-                               paddr = kmap_atomic(sg_page(sg)) + sg->offset;
+                               psg = sg_next(psg);
+                               paddr = kmap_atomic(sg_page(psg)) + psg->offset;
                                offset = 0;
                        }
 
index 24b4f65d8777bd357efbb85f7324ac4d803da101..2956250b7225c99d77a7475b27d1bf881231539f 100644 (file)
@@ -1601,6 +1601,9 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_CHECK_CONDITION_ABORT_CMD:
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
        case TCM_CHECK_CONDITION_NOT_READY:
+       case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
+       case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
+       case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
                break;
        case TCM_OUT_OF_RESOURCES:
                sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
index bd2715a9d8e5ac959ec1681fd920e953859856a3..c74a00ad7add80254ddf98dbaf88ed0725a540e0 100644 (file)
@@ -1267,17 +1267,16 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
  *     @p: output buffer of at least 7 bytes
  *
  *     Generate a name from a driver reference and write it to the output
- *     buffer. Return the number of bytes written.
+ *     buffer.
  *
  *     Locking: None
  */
-static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
+static void tty_line_name(struct tty_driver *driver, int index, char *p)
 {
        if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
-               return sprintf(p, "%s", driver->name);
+               strcpy(p, driver->name);
        else
-               return sprintf(p, "%s%d", driver->name,
-                              index + driver->name_base);
+               sprintf(p, "%s%d", driver->name, index + driver->name_base);
 }
 
 /**
@@ -3546,19 +3545,9 @@ static ssize_t show_cons_active(struct device *dev,
                if (i >= ARRAY_SIZE(cs))
                        break;
        }
-       while (i--) {
-               struct tty_driver *driver;
-               const char *name = cs[i]->name;
-               int index = cs[i]->index;
-
-               driver = cs[i]->device(cs[i], &index);
-               if (driver) {
-                       count += tty_line_name(driver, index, buf + count);
-                       count += sprintf(buf + count, "%c", i ? ' ':'\n');
-               } else
-                       count += sprintf(buf + count, "%s%d%c",
-                                        name, index, i ? ' ':'\n');
-       }
+       while (i--)
+               count += sprintf(buf + count, "%s%d%c",
+                                cs[i]->name, cs[i]->index, i ? ' ':'\n');
        console_unlock();
 
        return count;
index 80de2f88ed2c7852fdd38bec785e6d5681cbe310..4ab2cb62dfce4c1b3dfe140ef83f20d4633b9ff0 100644 (file)
@@ -105,7 +105,7 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir)
 
        do {
                /* flush any pending transfer */
-               hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n));
+               hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n));
                while (hw_read(ci, OP_ENDPTFLUSH, BIT(n)))
                        cpu_relax();
        } while (hw_read(ci, OP_ENDPTSTAT, BIT(n)));
@@ -205,7 +205,7 @@ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl)
        if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
                return -EAGAIN;
 
-       hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n));
+       hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n));
 
        while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
                cpu_relax();
index 888fbb43b338ecebcaf7cf8cb267fb2de35cc240..e969eb809a853dbb38093a0f5d3d39f57f931bb7 100644 (file)
@@ -360,24 +360,30 @@ static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
        bcm_writel(val, udc->iudma_regs + off);
 }
 
-static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off)
+static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan)
 {
-       return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off);
+       return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+                                       int chan)
 {
-       bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off);
+       bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off)
+static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan)
 {
-       return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off);
+       return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+                                       int chan)
 {
-       bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off);
+       bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
 static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled)
@@ -638,7 +644,7 @@ static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma,
        } while (!last_bd);
 
        usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK,
-                       ENETDMAC_CHANCFG_REG(iudma->ch_idx));
+                       ENETDMAC_CHANCFG_REG, iudma->ch_idx);
 }
 
 /**
@@ -694,9 +700,9 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
                bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num));
 
        /* stop DMA, then wait for the hardware to wrap up */
-       usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx));
+       usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx);
 
-       while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) &
+       while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) &
                                   ENETDMAC_CHANCFG_EN_MASK) {
                udelay(1);
 
@@ -713,10 +719,10 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
                        dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n",
                                 ch_idx);
                        usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK,
-                                       ENETDMAC_CHANCFG_REG(ch_idx));
+                                       ENETDMAC_CHANCFG_REG, ch_idx);
                }
        }
-       usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx));
+       usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx);
 
        /* don't leave "live" HW-owned entries for the next guy to step on */
        for (d = iudma->bd_ring; d <= iudma->end_bd; d++)
@@ -728,11 +734,11 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
 
        /* set up IRQs, UBUS burst size, and BD base for this channel */
        usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-                       ENETDMAC_IRMASK_REG(ch_idx));
-       usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx));
+                       ENETDMAC_IRMASK_REG, ch_idx);
+       usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx);
 
-       usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx));
-       usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx));
+       usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx);
+       usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx);
 }
 
 /**
@@ -2035,7 +2041,7 @@ static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id)
        spin_lock(&udc->lock);
 
        usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-                       ENETDMAC_IR_REG(iudma->ch_idx));
+                       ENETDMAC_IR_REG, iudma->ch_idx);
        bep = iudma->bep;
        rc = iudma_read(udc, iudma);
 
@@ -2175,18 +2181,18 @@ static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p)
                seq_printf(s, " [ep%d]:\n",
                           max_t(int, iudma_defaults[ch_idx].ep_num, 0));
                seq_printf(s, "  cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n",
-                          usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)),
-                          usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)),
-                          usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)),
-                          usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx)));
+                          usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx));
 
-               sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx));
-               sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx));
+               sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx);
+               sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx);
                seq_printf(s, "  base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n",
-                          usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)),
+                          usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx),
                           sram2 >> 16, sram2 & 0xffff,
                           sram3 >> 16, sram3 & 0xffff,
-                          usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx)));
+                          usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx));
                seq_printf(s, "  desc: %d/%d used", iudma->n_bds_used,
                           iudma->n_bds);
 
index 306a2b52125c8e7ee2eba91bcf1156e689ae133e..2b43343940766251ee5f274b807b882273f09008 100644 (file)
@@ -585,7 +585,6 @@ static ssize_t ffs_epfile_io(struct file *file,
                             char __user *buf, size_t len, int read)
 {
        struct ffs_epfile *epfile = file->private_data;
-       struct usb_gadget *gadget = epfile->ffs->gadget;
        struct ffs_ep *ep;
        char *data = NULL;
        ssize_t ret, data_len;
@@ -621,6 +620,12 @@ static ssize_t ffs_epfile_io(struct file *file,
 
        /* Allocate & copy */
        if (!halt) {
+               /*
+                * if we _do_ wait above, the epfile->ffs->gadget might be NULL
+                * before the waiting completes, so do not assign to 'gadget' earlier
+                */
+               struct usb_gadget *gadget = epfile->ffs->gadget;
+
                /*
                 * Controller may require buffer size to be aligned to
                 * maxpacketsize of an out endpoint.
index bf7a56b6d48ac2c3ebb3acf8920c70d79900d307..69b76efd11e9bea3f11d9d2effe293c04045f01c 100644 (file)
@@ -1157,7 +1157,7 @@ static int __init printer_bind_config(struct usb_configuration *c)
 
        usb_gadget_set_selfpowered(gadget);
 
-       if (gadget->is_otg) {
+       if (gadget_is_otg(gadget)) {
                otg_descriptor.bmAttributes |= USB_OTG_HNP;
                printer_cfg_driver.descriptors = otg_desc;
                printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
index f04b2c3154dea73b0fa2c1d93322bdbf1c5930bc..dd9678f85c586a591b2a6514ba71034895d1769d 100644 (file)
@@ -1629,7 +1629,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
                ep->ep.desc = NULL;
                ep->halted = 0;
                INIT_LIST_HEAD(&ep->queue);
-               usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket);
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
        }
 }
 
index 471142725ffe1cd42f92b2ad0883fa925c715a2a..81cda09b47e3127772e51cbc5c57eab7761c4a52 100644 (file)
@@ -685,8 +685,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        u32                     status, masked_status, pcd_status = 0, cmd;
        int                     bh;
+       unsigned long           flags;
 
-       spin_lock (&ehci->lock);
+       /*
+        * For threadirqs option we use spin_lock_irqsave() variant to prevent
+        * deadlock with ehci hrtimer callback, because hrtimer callbacks run
+        * in interrupt context even when threadirqs is specified. We can go
+        * back to spin_lock() variant when hrtimer callbacks become threaded.
+        */
+       spin_lock_irqsave(&ehci->lock, flags);
 
        status = ehci_readl(ehci, &ehci->regs->status);
 
@@ -704,7 +711,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 
        /* Shared IRQ? */
        if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
-               spin_unlock(&ehci->lock);
+               spin_unlock_irqrestore(&ehci->lock, flags);
                return IRQ_NONE;
        }
 
@@ -815,7 +822,7 @@ dead:
 
        if (bh)
                ehci_work (ehci);
-       spin_unlock (&ehci->lock);
+       spin_unlock_irqrestore(&ehci->lock, flags);
        if (pcd_status)
                usb_hcd_poll_rh_status(hcd);
        return IRQ_HANDLED;
index 47b858fc50b2ee484c035cef8fe8b27c669009b5..7ae0c4d517417d46dbc2dd8f51993728fa839c3a 100644 (file)
@@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        int                     port;
        int                     mask;
        int                     changed;
+       bool                    fs_idle_delay;
 
        ehci_dbg(ehci, "suspend root hub\n");
 
@@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        ehci->bus_suspended = 0;
        ehci->owned_ports = 0;
        changed = 0;
+       fs_idle_delay = false;
        port = HCS_N_PORTS(ehci->hcs_params);
        while (port--) {
                u32 __iomem     *reg = &ehci->regs->port_status [port];
@@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
                }
 
                if (t1 != t2) {
+                       /*
+                        * On some controllers, Wake-On-Disconnect will
+                        * generate false wakeup signals until the bus
+                        * switches over to full-speed idle.  For their
+                        * sake, add a delay if we need one.
+                        */
+                       if ((t2 & PORT_WKDISC_E) &&
+                                       ehci_port_speed(ehci, t2) ==
+                                               USB_PORT_STAT_HIGH_SPEED)
+                               fs_idle_delay = true;
                        ehci_writel(ehci, t2, reg);
                        changed = 1;
                }
        }
+       spin_unlock_irq(&ehci->lock);
+
+       if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
+               /*
+                * Wait for HCD to enter low-power mode or for the bus
+                * to switch to full-speed idle.
+                */
+               usleep_range(5000, 5500);
+       }
 
        if (changed && ehci->has_tdi_phy_lpm) {
-               spin_unlock_irq(&ehci->lock);
-               msleep(5);      /* 5 ms for HCD to enter low-power mode */
                spin_lock_irq(&ehci->lock);
-
                port = HCS_N_PORTS(ehci->hcs_params);
                while (port--) {
                        u32 __iomem     *hostpc_reg = &ehci->regs->hostpc[port];
@@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
                                        port, (t3 & HOSTPC_PHCD) ?
                                        "succeeded" : "failed");
                }
+               spin_unlock_irq(&ehci->lock);
        }
-       spin_unlock_irq(&ehci->lock);
 
        /* Apparently some devices need a >= 1-uframe delay here */
        if (ehci->bus_suspended)
index fc192ad9cc6a60eb4a7f00d124eb0a0d1bca73fe..239ad0b1ceb6d15ddff5fa3741ca97796e70e067 100644 (file)
@@ -477,8 +477,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                musb->port1_status |=
                                                (USB_PORT_STAT_C_SUSPEND << 16)
                                                | MUSB_PORT_STAT_RESUME;
+                               musb->rh_timer = jiffies
+                                                + msecs_to_jiffies(20);
                                schedule_delayed_work(
-                                       &musb->finish_resume_work, 20);
+                                       &musb->finish_resume_work,
+                                       msecs_to_jiffies(20));
 
                                musb->xceiv->state = OTG_STATE_A_HOST;
                                musb->is_active = 1;
@@ -2157,11 +2160,19 @@ static void musb_restore_context(struct musb *musb)
        void __iomem *musb_base = musb->mregs;
        void __iomem *ep_target_regs;
        void __iomem *epio;
+       u8 power;
 
        musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
        musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
        musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
-       musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+
+       /* Don't affect SUSPENDM/RESUME bits in POWER reg */
+       power = musb_readb(musb_base, MUSB_POWER);
+       power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME;
+       musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME);
+       power |= musb->context.power;
+       musb_writeb(musb_base, MUSB_POWER, power);
+
        musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
        musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
        musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
index ed455724017b5767f6ad849961946d7ad7af3228..abb38c3833ef46a1f8041c8a5f95fa96138b1796 100644 (file)
@@ -1183,6 +1183,9 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
                                csr = MUSB_CSR0_H_STATUSPKT
                                        | MUSB_CSR0_TXPKTRDY;
 
+                       /* disable ping token in status phase */
+                       csr |= MUSB_CSR0_H_DIS_PING;
+
                        /* flag status stage */
                        musb->ep0_stage = MUSB_EP0_STATUS;
 
index eb634433ef095b631cd7e70df77453334cf48ddc..e2d2d8c9891bc1f7a4cf5f8a16048d58a3d4c630 100644 (file)
@@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
 
                /* later, GetPortStatus will stop RESUME signaling */
                musb->port1_status |= MUSB_PORT_STAT_RESUME;
-               schedule_delayed_work(&musb->finish_resume_work, 20);
+               schedule_delayed_work(&musb->finish_resume_work,
+                                     msecs_to_jiffies(20));
        }
 }
 
@@ -158,7 +159,6 @@ void musb_port_reset(struct musb *musb, bool do_reset)
         */
        power = musb_readb(mbase, MUSB_POWER);
        if (do_reset) {
-
                /*
                 * If RESUME is set, we must make sure it stays minimum 20 ms.
                 * Then we must clear RESUME and wait a bit to let musb start
@@ -167,11 +167,22 @@ void musb_port_reset(struct musb *musb, bool do_reset)
                 * detected".
                 */
                if (power &  MUSB_POWER_RESUME) {
-                       while (time_before(jiffies, musb->rh_timer))
-                               msleep(1);
+                       long remain = (unsigned long) musb->rh_timer - jiffies;
+
+                       if (musb->rh_timer > 0 && remain > 0) {
+                               /* take into account the minimum delay after resume */
+                               schedule_delayed_work(
+                                       &musb->deassert_reset_work, remain);
+                               return;
+                       }
+
                        musb_writeb(mbase, MUSB_POWER,
-                               power & ~MUSB_POWER_RESUME);
-                       msleep(1);
+                                   power & ~MUSB_POWER_RESUME);
+
+                       /* Give the core 1 ms to clear MUSB_POWER_RESUME */
+                       schedule_delayed_work(&musb->deassert_reset_work,
+                                             msecs_to_jiffies(1));
+                       return;
                }
 
                power &= 0xf0;
@@ -180,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset)
 
                musb->port1_status |= USB_PORT_STAT_RESET;
                musb->port1_status &= ~USB_PORT_STAT_ENABLE;
-               schedule_delayed_work(&musb->deassert_reset_work, 50);
+               schedule_delayed_work(&musb->deassert_reset_work,
+                                     msecs_to_jiffies(50));
        } else {
                dev_dbg(musb->controller, "root port reset stopped\n");
                musb_writeb(mbase, MUSB_POWER,
index 2a408cdaf7b2c7102098faac6d29727505f41c91..8aa59a2c5eb2485c823244012cc738ce5df7d127 100644 (file)
@@ -659,7 +659,6 @@ static int omap2430_runtime_suspend(struct device *dev)
                                OTG_INTERFSEL);
 
                omap2430_low_level_exit(musb);
-               phy_power_off(musb->phy);
        }
 
        return 0;
@@ -674,7 +673,6 @@ static int omap2430_runtime_resume(struct device *dev)
                omap2430_low_level_init(musb);
                musb_writel(musb->mregs, OTG_INTERFSEL,
                                musb->context.otg_interfsel);
-               phy_power_on(musb->phy);
        }
 
        return 0;
index 8546c8dccd51b003fc9aba3038184cd2d0eedbea..d204f745ed05e652ef168940dece89e2e16a8269 100644 (file)
@@ -159,32 +159,6 @@ put_3p3:
        return rc;
 }
 
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL  500000
-static int msm_hsusb_config_vddcx(int high)
-{
-       int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
-       int min_vol;
-       int ret;
-
-       if (high)
-               min_vol = USB_PHY_VDD_DIG_VOL_MIN;
-       else
-               min_vol = USB_PHY_SUSP_DIG_VOL;
-
-       ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
-       if (ret) {
-               pr_err("%s: unable to set the voltage for regulator "
-                       "HSUSB_VDDCX\n", __func__);
-               return ret;
-       }
-
-       pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
-
-       return ret;
-}
-#endif
-
 static int msm_hsusb_ldo_set_mode(int on)
 {
        int ret = 0;
@@ -440,7 +414,32 @@ static int msm_otg_reset(struct usb_phy *phy)
 #define PHY_SUSPEND_TIMEOUT_USEC       (500 * 1000)
 #define PHY_RESUME_TIMEOUT_USEC        (100 * 1000)
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
+
+#define USB_PHY_SUSP_DIG_VOL  500000
+static int msm_hsusb_config_vddcx(int high)
+{
+       int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+       int min_vol;
+       int ret;
+
+       if (high)
+               min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+       else
+               min_vol = USB_PHY_SUSP_DIG_VOL;
+
+       ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+       if (ret) {
+               pr_err("%s: unable to set the voltage for regulator "
+                       "HSUSB_VDDCX\n", __func__);
+               return ret;
+       }
+
+       pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+       return ret;
+}
+
 static int msm_otg_suspend(struct msm_otg *motg)
 {
        struct usb_phy *phy = &motg->phy;
@@ -1733,22 +1732,18 @@ static int msm_otg_pm_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
 static const struct dev_pm_ops msm_otg_dev_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
        SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
                                msm_otg_runtime_idle)
 };
-#endif
 
 static struct platform_driver msm_otg_driver = {
        .remove = msm_otg_remove,
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm = &msm_otg_dev_pm_ops,
-#endif
        },
 };
 
index ee1f00f03c434ec67a5fee98f229ca3fd8e6c187..44ab1298680557f840d243056d7fc4812d7adc0d 100644 (file)
@@ -907,6 +907,8 @@ static const struct usb_device_id id_table_combined[] = {
        /* Crucible Devices */
        { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
+       /* Cressi Devices */
+       { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
        { }                                     /* Terminating entry */
 };
 
index 1e2d369df86e57ae29f188040fcf9b2d85aaa49c..e599fbfcde5f8fd5055f29f464fdaea13c130cb5 100644 (file)
  * Manufacturer: Smart GSM Team
  */
 #define FTDI_Z3X_PID           0x0011
+
+/*
+ * Product: Cressi PC Interface
+ * Manufacturer: Cressi
+ */
+#define FTDI_CRESSI_PID                0x87d0
index 216d20affba82741e0430989e19da8a54a492037..68fc9fe65936e712ba08e9f6825de4773b4cc9a9 100644 (file)
@@ -1526,7 +1526,8 @@ static const struct usb_device_id option_ids[] = {
        /* Cinterion */
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
-       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
index 9a68409580d5b76d8d3972e42a33314dc22f16f8..a0fa5de210cf57ac6842625ceb21499ac07a7969 100644 (file)
@@ -70,7 +70,12 @@ enum {
 };
 
 struct vhost_net_ubuf_ref {
-       struct kref kref;
+       /* refcount follows semantics similar to kref:
+        *  0: object is released
+        *  1: no outstanding ubufs
+        * >1: outstanding ubufs
+        */
+       atomic_t refcount;
        wait_queue_head_t wait;
        struct vhost_virtqueue *vq;
 };
@@ -116,14 +121,6 @@ static void vhost_net_enable_zcopy(int vq)
        vhost_net_zcopy_mask |= 0x1 << vq;
 }
 
-static void vhost_net_zerocopy_done_signal(struct kref *kref)
-{
-       struct vhost_net_ubuf_ref *ubufs;
-
-       ubufs = container_of(kref, struct vhost_net_ubuf_ref, kref);
-       wake_up(&ubufs->wait);
-}
-
 static struct vhost_net_ubuf_ref *
 vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy)
 {
@@ -134,21 +131,24 @@ vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy)
        ubufs = kmalloc(sizeof(*ubufs), GFP_KERNEL);
        if (!ubufs)
                return ERR_PTR(-ENOMEM);
-       kref_init(&ubufs->kref);
+       atomic_set(&ubufs->refcount, 1);
        init_waitqueue_head(&ubufs->wait);
        ubufs->vq = vq;
        return ubufs;
 }
 
-static void vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
+static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
 {
-       kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
+       int r = atomic_sub_return(1, &ubufs->refcount);
+       if (unlikely(!r))
+               wake_up(&ubufs->wait);
+       return r;
 }
 
 static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
 {
-       kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
-       wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+       vhost_net_ubuf_put(ubufs);
+       wait_event(ubufs->wait, !atomic_read(&ubufs->refcount));
 }
 
 static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs)
@@ -306,23 +306,26 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
 {
        struct vhost_net_ubuf_ref *ubufs = ubuf->ctx;
        struct vhost_virtqueue *vq = ubufs->vq;
-       int cnt = atomic_read(&ubufs->kref.refcount);
+       int cnt;
+
+       rcu_read_lock_bh();
 
        /* set len to mark this desc buffers done DMA */
        vq->heads[ubuf->desc].len = success ?
                VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
-       vhost_net_ubuf_put(ubufs);
+       cnt = vhost_net_ubuf_put(ubufs);
 
        /*
         * Trigger polling thread if guest stopped submitting new buffers:
-        * in this case, the refcount after decrement will eventually reach 1
-        * so here it is 2.
+        * in this case, the refcount after decrement will eventually reach 1.
         * We also trigger polling periodically after each 16 packets
         * (the value 16 here is more or less arbitrary, it's tuned to trigger
         * less than 10% of times).
         */
-       if (cnt <= 2 || !(cnt % 16))
+       if (cnt <= 1 || !(cnt % 16))
                vhost_poll_queue(&vq->poll);
+
+       rcu_read_unlock_bh();
 }
 
 /* Expects to be always run from workqueue - which acts as
@@ -420,7 +423,7 @@ static void handle_tx(struct vhost_net *net)
                        msg.msg_control = ubuf;
                        msg.msg_controllen = sizeof(ubuf);
                        ubufs = nvq->ubufs;
-                       kref_get(&ubufs->kref);
+                       atomic_inc(&ubufs->refcount);
                        nvq->upend_idx = (nvq->upend_idx + 1) % UIO_MAXIOV;
                } else {
                        msg.msg_control = NULL;
@@ -780,7 +783,7 @@ static void vhost_net_flush(struct vhost_net *n)
                vhost_net_ubuf_put_and_wait(n->vqs[VHOST_NET_VQ_TX].ubufs);
                mutex_lock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex);
                n->tx_flush = false;
-               kref_init(&n->vqs[VHOST_NET_VQ_TX].ubufs->kref);
+               atomic_set(&n->vqs[VHOST_NET_VQ_TX].ubufs->refcount, 1);
                mutex_unlock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex);
        }
 }
@@ -800,6 +803,8 @@ static int vhost_net_release(struct inode *inode, struct file *f)
                fput(tx_sock->file);
        if (rx_sock)
                fput(rx_sock->file);
+       /* Make sure no callbacks are outstanding */
+       synchronize_rcu_bh();
        /* We do an extra flush before freeing memory,
         * since jobs can re-queue themselves. */
        vhost_net_flush(n);
index 0a025b8e2a12efd2f58434b8084a45ad2454b604..e48d4a672580cd5eefaf741946435073a4e58e8c 100644 (file)
@@ -1001,6 +1001,12 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                        break;
                }
 
+               /* virtio-scsi spec requires byte 0 of the lun to be 1 */
+               if (unlikely(v_req.lun[0] != 1)) {
+                       vhost_scsi_send_bad_target(vs, vq, head, out);
+                       continue;
+               }
+
                /* Extract the tpgt */
                target = v_req.lun[1];
                tpg = ACCESS_ONCE(vs_tpg[target]);
index aaf2995d37f4b595d010efa500e89bb1ae5aef5b..68b45fc9ba6a5de684f18128ca337c09e7b3657e 100644 (file)
@@ -402,7 +402,7 @@ static int __init wdt_init(void)
 
        if (!found) {
                pr_err("No W83697HF/HG could be found\n");
-               ret = -EIO;
+               ret = -ENODEV;
                goto out;
        }
 
index 4c2d452c4bfc0abad11cf3e3b0577d62ed3ef240..21887d63dad589a53e3da21fccb00c45a5c28ab6 100644 (file)
@@ -54,11 +54,6 @@ static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode,
        return acl;
 }
 
-void ceph_forget_all_cached_acls(struct inode *inode)
-{
-       forget_all_cached_acls(inode);
-}
-
 struct posix_acl *ceph_get_acl(struct inode *inode, int type)
 {
        int size;
@@ -160,11 +155,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
                        goto out_dput;
        }
 
-       if (value)
-               ret = __ceph_setxattr(dentry, name, value, size, 0);
-       else
-               ret = __ceph_removexattr(dentry, name);
-
+       ret = __ceph_setxattr(dentry, name, value, size, 0);
        if (ret) {
                if (new_mode != old_mode) {
                        newattrs.ia_mode = old_mode;
index 6da4df84ba300824a8a6afdea9f2a20121600765..45eda6d7a40c2030db42fc06fa2d741f180c254f 100644 (file)
@@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p)
        return p & 0xffffffff;
 }
 
+static int fpos_cmp(loff_t l, loff_t r)
+{
+       int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r));
+       if (v)
+               return v;
+       return (int)(fpos_off(l) - fpos_off(r));
+}
+
 /*
  * When possible, we try to satisfy a readdir by peeking at the
  * dcache.  We make this work by carefully ordering dentries on
@@ -156,7 +164,7 @@ more:
                if (!d_unhashed(dentry) && dentry->d_inode &&
                    ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
                    ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
-                   ctx->pos <= di->offset)
+                   fpos_cmp(ctx->pos, di->offset) <= 0)
                        break;
                dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
                     dentry->d_name.len, dentry->d_name.name, di->offset,
@@ -695,9 +703,8 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
        ceph_mdsc_put_request(req);
 
        if (!err)
-               err = ceph_init_acl(dentry, dentry->d_inode, dir);
-
-       if (err)
+               ceph_init_acl(dentry, dentry->d_inode, dir);
+       else
                d_drop(dentry);
        return err;
 }
@@ -735,7 +742,9 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
        if (!err && !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
        ceph_mdsc_put_request(req);
-       if (err)
+       if (!err)
+               ceph_init_acl(dentry, dentry->d_inode, dir);
+       else
                d_drop(dentry);
        return err;
 }
@@ -776,7 +785,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
                err = ceph_handle_notrace_create(dir, dentry);
        ceph_mdsc_put_request(req);
 out:
-       if (err < 0)
+       if (!err)
+               ceph_init_acl(dentry, dentry->d_inode, dir);
+       else
                d_drop(dentry);
        return err;
 }
index dfd2ce3419f812f71769406023d0ff33cea3a35b..09c7afe32e496c7dfe20d527106c7a184248c3ca 100644 (file)
@@ -286,6 +286,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
        } else {
                dout("atomic_open finish_open on dn %p\n", dn);
                if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
+                       ceph_init_acl(dentry, dentry->d_inode, dir);
                        *opened |= FILE_CREATED;
                }
                err = finish_open(file, dentry, ceph_open, opened);
index 2df963f1cf5a3b84615772e793cd45eeddec801f..10a4ccbf38dab2c6f26407e7383815986f337bc0 100644 (file)
@@ -144,7 +144,11 @@ enum {
        Opt_ino32,
        Opt_noino32,
        Opt_fscache,
-       Opt_nofscache
+       Opt_nofscache,
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       Opt_acl,
+#endif
+       Opt_noacl
 };
 
 static match_table_t fsopt_tokens = {
@@ -172,6 +176,10 @@ static match_table_t fsopt_tokens = {
        {Opt_noino32, "noino32"},
        {Opt_fscache, "fsc"},
        {Opt_nofscache, "nofsc"},
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       {Opt_acl, "acl"},
+#endif
+       {Opt_noacl, "noacl"},
        {-1, NULL}
 };
 
@@ -271,6 +279,14 @@ static int parse_fsopt_token(char *c, void *private)
        case Opt_nofscache:
                fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
                break;
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       case Opt_acl:
+               fsopt->sb_flags |= MS_POSIXACL;
+               break;
+#endif
+       case Opt_noacl:
+               fsopt->sb_flags &= ~MS_POSIXACL;
+               break;
        default:
                BUG_ON(token);
        }
@@ -438,6 +454,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
        else
                seq_puts(m, ",nofsc");
 
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       if (fsopt->sb_flags & MS_POSIXACL)
+               seq_puts(m, ",acl");
+       else
+               seq_puts(m, ",noacl");
+#endif
+
        if (fsopt->wsize)
                seq_printf(m, ",wsize=%d", fsopt->wsize);
        if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
@@ -819,9 +842,6 @@ static int ceph_set_super(struct super_block *s, void *data)
 
        s->s_flags = fsc->mount_options->sb_flags;
        s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
-#ifdef CONFIG_CEPH_FS_POSIX_ACL
-       s->s_flags |= MS_POSIXACL;
-#endif
 
        s->s_xattr = ceph_xattr_handlers;
        s->s_fs_info = fsc;
@@ -911,6 +931,10 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
        struct ceph_options *opt = NULL;
 
        dout("ceph_mount\n");
+
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       flags |= MS_POSIXACL;
+#endif
        err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
        if (err < 0) {
                res = ERR_PTR(err);
index 19793b56d0a7d3a90330c36a218312728b42e45e..d8801a95b6857d514fc27e440af8d476513cae3e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
+#include <linux/posix_acl.h>
 
 #include <linux/ceph/libceph.h>
 
@@ -743,7 +744,11 @@ extern const struct xattr_handler *ceph_xattr_handlers[];
 struct posix_acl *ceph_get_acl(struct inode *, int);
 int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int ceph_init_acl(struct dentry *, struct inode *, struct inode *);
-void ceph_forget_all_cached_acls(struct inode *inode);
+
+static inline void ceph_forget_all_cached_acls(struct inode *inode)
+{
+       forget_all_cached_acls(inode);
+}
 
 #else
 
index 898b6565ad3e2c114baca0282fafea6a5643071a..a55ec37378c6730efa476d3d6a923e37ba10ec72 100644 (file)
@@ -12,6 +12,9 @@
 #define XATTR_CEPH_PREFIX "ceph."
 #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
 
+static int __remove_xattr(struct ceph_inode_info *ci,
+                         struct ceph_inode_xattr *xattr);
+
 /*
  * List of handlers for synthetic system.* attributes. Other
  * attributes are handled directly.
@@ -319,8 +322,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
 static int __set_xattr(struct ceph_inode_info *ci,
                           const char *name, int name_len,
                           const char *val, int val_len,
-                          int dirty,
-                          int should_free_name, int should_free_val,
+                          int flags, int update_xattr,
                           struct ceph_inode_xattr **newxattr)
 {
        struct rb_node **p;
@@ -349,12 +351,31 @@ static int __set_xattr(struct ceph_inode_info *ci,
                xattr = NULL;
        }
 
+       if (update_xattr) {
+               int err = 0;
+               if (xattr && (flags & XATTR_CREATE))
+                       err = -EEXIST;
+               else if (!xattr && (flags & XATTR_REPLACE))
+                       err = -ENODATA;
+               if (err) {
+                       kfree(name);
+                       kfree(val);
+                       return err;
+               }
+               if (update_xattr < 0) {
+                       if (xattr)
+                               __remove_xattr(ci, xattr);
+                       kfree(name);
+                       return 0;
+               }
+       }
+
        if (!xattr) {
                new = 1;
                xattr = *newxattr;
                xattr->name = name;
                xattr->name_len = name_len;
-               xattr->should_free_name = should_free_name;
+               xattr->should_free_name = update_xattr;
 
                ci->i_xattrs.count++;
                dout("__set_xattr count=%d\n", ci->i_xattrs.count);
@@ -364,7 +385,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
                if (xattr->should_free_val)
                        kfree((void *)xattr->val);
 
-               if (should_free_name) {
+               if (update_xattr) {
                        kfree((void *)name);
                        name = xattr->name;
                }
@@ -379,8 +400,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
                xattr->val = "";
 
        xattr->val_len = val_len;
-       xattr->dirty = dirty;
-       xattr->should_free_val = (val && should_free_val);
+       xattr->dirty = update_xattr;
+       xattr->should_free_val = (val && update_xattr);
 
        if (new) {
                rb_link_node(&xattr->node, parent, p);
@@ -442,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci,
                          struct ceph_inode_xattr *xattr)
 {
        if (!xattr)
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        rb_erase(&xattr->node, &ci->i_xattrs.index);
 
@@ -588,7 +609,7 @@ start:
                        p += len;
 
                        err = __set_xattr(ci, name, namelen, val, len,
-                                         0, 0, 0, &xattrs[numattr]);
+                                         0, 0, &xattrs[numattr]);
 
                        if (err < 0)
                                goto bad;
@@ -850,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
 
        dout("setxattr value=%.*s\n", (int)size, value);
 
+       if (!value)
+               flags |= CEPH_XATTR_REMOVE;
+
        /* do request */
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
                                       USE_AUTH_MDS);
@@ -892,7 +916,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
        struct ceph_inode_info *ci = ceph_inode(inode);
        int issued;
        int err;
-       int dirty;
+       int dirty = 0;
        int name_len = strlen(name);
        int val_len = size;
        char *newname = NULL;
@@ -953,12 +977,14 @@ retry:
                goto retry;
        }
 
-       err = __set_xattr(ci, newname, name_len, newval,
-                         val_len, 1, 1, 1, &xattr);
+       err = __set_xattr(ci, newname, name_len, newval, val_len,
+                         flags, value ? 1 : -1, &xattr);
 
-       dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
-       ci->i_xattrs.dirty = true;
-       inode->i_ctime = CURRENT_TIME;
+       if (!err) {
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+               ci->i_xattrs.dirty = true;
+               inode->i_ctime = CURRENT_TIME;
+       }
 
        spin_unlock(&ci->i_ceph_lock);
        if (dirty)
index c819b0bd491aab9bf587987b7b4017cdb5c69f64..7ff866dbb89eb7b31033ce1e99f7b56f664fbdf6 100644 (file)
@@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
        return rc;
 }
 
-static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
-               __u16 fid, u32 *pacllen)
+struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
+               const struct cifs_fid *cifsfid, u32 *pacllen)
 {
        struct cifs_ntsd *pntsd = NULL;
        unsigned int xid;
@@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
                return ERR_CAST(tlink);
 
        xid = get_xid();
-       rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
+       rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
+                               pacllen);
        free_xid(xid);
 
        cifs_put_tlink(tlink);
@@ -946,7 +947,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
        if (!open_file)
                return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 
-       pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
+       pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
        cifsFileInfo_put(open_file);
        return pntsd;
 }
@@ -1006,19 +1007,31 @@ out:
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
 int
 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
-                 struct inode *inode, const char *path, const __u16 *pfid)
+                 struct inode *inode, const char *path,
+                 const struct cifs_fid *pfid)
 {
        struct cifs_ntsd *pntsd = NULL;
        u32 acllen = 0;
        int rc = 0;
+       struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+       struct cifs_tcon *tcon;
 
        cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
-       if (pfid)
-               pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
-       else
-               pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
+       if (IS_ERR(tlink))
+               return PTR_ERR(tlink);
+       tcon = tlink_tcon(tlink);
 
+       if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
+               pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
+                                                         &acllen);
+       else if (tcon->ses->server->ops->get_acl)
+               pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
+                                                       &acllen);
+       else {
+               cifs_put_tlink(tlink);
+               return -EOPNOTSUPP;
+       }
        /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
@@ -1030,6 +1043,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
                        cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
        }
 
+       cifs_put_tlink(tlink);
+
        return rc;
 }
 
index 86dc28c7aa5c7b9a0f4652e3d5a09957d8c6883e..cf32f03933694cb56fd518a5e25388f35d834162 100644 (file)
@@ -398,6 +398,8 @@ struct smb_version_operations {
                        const struct nls_table *, int);
        struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
                        const char *, u32 *);
+       struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
+                       const struct cifs_fid *, u32 *);
        int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
                        int);
 };
index d00e09dfc452a3b1c8aed81d4bc7e02a7a231424..acc4ee8ed0759a7e786709ea61d5077970b3ef3e 100644 (file)
@@ -151,7 +151,7 @@ extern struct inode *cifs_iget(struct super_block *sb,
 
 extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
                               FILE_ALL_INFO *data, struct super_block *sb,
-                              int xid, const __u16 *fid);
+                              int xid, const struct cifs_fid *fid);
 extern int cifs_get_inode_info_unix(struct inode **pinode,
                        const unsigned char *search_path,
                        struct super_block *sb, unsigned int xid);
@@ -162,11 +162,13 @@ extern int cifs_rename_pending_delete(const char *full_path,
                                      const unsigned int xid);
 extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
                              struct cifs_fattr *fattr, struct inode *inode,
-                             const char *path, const __u16 *pfid);
+                             const char *path, const struct cifs_fid *pfid);
 extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
                                        kuid_t, kgid_t);
 extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
                                        const char *, u32 *);
+extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
+                                               const struct cifs_fid *, u32 *);
 extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
                                const char *, int);
 
index d3a6796caa5a3fce527584ae6437b2a446663da4..3db0c5fd9a1109629764cf5f2b759dd9ddd8cd8a 100644 (file)
@@ -378,7 +378,7 @@ cifs_create_get_file_info:
                                              xid);
        else {
                rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
-                                        xid, &fid->netfid);
+                                        xid, fid);
                if (newinode) {
                        if (server->ops->set_lease_key)
                                server->ops->set_lease_key(newinode, fid);
index 755584684f6c51d0f9dc8444541017eca2d0b294..53c15074bb3622b9a251bef0eafeed866a24ce0b 100644 (file)
@@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
                                              xid);
        else
                rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
-                                        xid, &fid->netfid);
+                                        xid, fid);
 
 out:
        kfree(buf);
@@ -2389,7 +2389,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
                 unsigned long nr_segs, loff_t *poffset)
 {
        unsigned long nr_pages, i;
-       size_t copied, len, cur_len;
+       size_t bytes, copied, len, cur_len;
        ssize_t total_written = 0;
        loff_t offset;
        struct iov_iter it;
@@ -2444,14 +2444,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 
                save_len = cur_len;
                for (i = 0; i < nr_pages; i++) {
-                       copied = min_t(const size_t, cur_len, PAGE_SIZE);
+                       bytes = min_t(const size_t, cur_len, PAGE_SIZE);
                        copied = iov_iter_copy_from_user(wdata->pages[i], &it,
-                                                        0, copied);
+                                                        0, bytes);
                        cur_len -= copied;
                        iov_iter_advance(&it, copied);
+                       /*
+                        * If we didn't copy as much as we expected, then that
+                        * may mean we trod into an unmapped area. Stop copying
+                        * at that point. On the next pass through the big
+                        * loop, we'll likely end up getting a zero-length
+                        * write and bailing out of it.
+                        */
+                       if (copied < bytes)
+                               break;
                }
                cur_len = save_len - cur_len;
 
+               /*
+                * If we have no data to send, then that probably means that
+                * the copy above failed altogether. That's most likely because
+                * the address in the iovec was bogus. Set the rc to -EFAULT,
+                * free anything we allocated and bail out.
+                */
+               if (!cur_len) {
+                       for (i = 0; i < nr_pages; i++)
+                               put_page(wdata->pages[i]);
+                       kfree(wdata);
+                       rc = -EFAULT;
+                       break;
+               }
+
+               /*
+                * i + 1 now represents the number of pages we actually used in
+                * the copy phase above. Bring nr_pages down to that, and free
+                * any pages that we didn't use.
+                */
+               for ( ; nr_pages > i + 1; nr_pages--)
+                       put_page(wdata->pages[nr_pages - 1]);
+
                wdata->sync_mode = WB_SYNC_ALL;
                wdata->nr_pages = nr_pages;
                wdata->offset = (__u64)offset;
index be58b8fcdb3c321ffbab033a4a91abc76c774df3..aadc2b68678b7d70c0381d10c847c86624589c4c 100644 (file)
@@ -677,7 +677,7 @@ cgfi_exit:
 int
 cifs_get_inode_info(struct inode **inode, const char *full_path,
                    FILE_ALL_INFO *data, struct super_block *sb, int xid,
-                   const __u16 *fid)
+                   const struct cifs_fid *fid)
 {
        bool validinum = false;
        __u16 srchflgs;
index bfd66d84831eb827b93d8baa4f4b0c183dcdb084..526fb89f92305b9e85d1f62f65a6e48c04555e83 100644 (file)
@@ -1073,6 +1073,7 @@ struct smb_version_operations smb1_operations = {
 #endif /* CIFS_XATTR */
 #ifdef CONFIG_CIFS_ACL
        .get_acl = get_cifs_acl,
+       .get_acl_by_fid = get_cifs_acl_by_fid,
        .set_acl = set_cifs_acl,
 #endif /* CIFS_ACL */
 };
index c38350851b0883cd6074b04f5aa36398b2528e3c..bc0bb9c34f72aaef62383760a06fa55c72d5b70b 100644 (file)
@@ -57,4 +57,7 @@
 #define SMB2_CMACAES_SIZE (16)
 #define SMB3_SIGNKEY_SIZE (16)
 
+/* Maximum buffer size value we can send with 1 credit */
+#define SMB2_MAX_BUFFER_SIZE 65536
+
 #endif /* _SMB2_GLOB_H */
index 757da3e54d3dce601b71b97883f3430556040107..192f51a12cf1c63fb6eee3359b2350747343a76c 100644 (file)
@@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
        /* start with specified wsize, or default */
        wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
        wsize = min_t(unsigned int, wsize, server->max_write);
-       /*
-        * limit write size to 2 ** 16, because we don't support multicredit
-        * requests now.
-        */
-       wsize = min_t(unsigned int, wsize, 2 << 15);
+       /* set it to the maximum buffer size value we can send with 1 credit */
+       wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
 
        return wsize;
 }
@@ -200,11 +197,8 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
        /* start with specified rsize, or default */
        rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
        rsize = min_t(unsigned int, rsize, server->max_read);
-       /*
-        * limit write size to 2 ** 16, because we don't support multicredit
-        * requests now.
-        */
-       rsize = min_t(unsigned int, rsize, 2 << 15);
+       /* set it to the maximum buffer size value we can send with 1 credit */
+       rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
 
        return rsize;
 }
index a3f7a9c3cc69d81ef4ce58b8f509dda288fa6602..860344701067f49169e20a8a41df55145fa5f023 100644 (file)
@@ -413,7 +413,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 
        /* SMB2 only has an extended negflavor */
        server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
-       server->maxBuf = le32_to_cpu(rsp->MaxTransactSize);
+       /* set it to the maximum buffer size value we can send with 1 credit */
+       server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
+                              SMB2_MAX_BUFFER_SIZE);
        server->max_read = le32_to_cpu(rsp->MaxReadSize);
        server->max_write = le32_to_cpu(rsp->MaxWriteSize);
        /* BB Do we need to validate the SecurityMode? */
index ece55565b9cd35575c454d44656c63321d89e0f9..d3a534fdc5ff6c766131e5d843591149736cc4d8 100644 (file)
@@ -771,6 +771,8 @@ do {                                                                               \
        if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime))                      \
                (einode)->xtime.tv_sec =                                       \
                        (signed)le32_to_cpu((raw_inode)->xtime);               \
+       else                                                                   \
+               (einode)->xtime.tv_sec = 0;                                    \
        if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))            \
                ext4_decode_extra_time(&(einode)->xtime,                       \
                                       raw_inode->xtime ## _extra);            \
index 10cff4736b116185f9d0a2cea73dca9423c6fb92..74bc2d549c58bd57d60ebcb0a143a3fdf4e95997 100644 (file)
@@ -3906,6 +3906,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
                } else
                        err = ret;
                map->m_flags |= EXT4_MAP_MAPPED;
+               map->m_pblk = newblock;
                if (allocated > map->m_len)
                        allocated = map->m_len;
                map->m_len = allocated;
index 6bea80614d77c19c6ca7b1ac9160d64f1115b36e..a2a837f0040743d9e76608904c5b2cb429aaadd2 100644 (file)
@@ -140,7 +140,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
        handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
        if (IS_ERR(handle)) {
                err = -EINVAL;
-               goto swap_boot_out;
+               goto journal_err_out;
        }
 
        /* Protect extent tree against block allocations via delalloc */
@@ -198,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
 
        ext4_double_up_write_data_sem(inode, inode_bl);
 
+journal_err_out:
        ext4_inode_resume_unlocked_dio(inode);
        ext4_inode_resume_unlocked_dio(inode_bl);
 
index c5adbb318a90c8c612c97dab1a47c0143b19ef77..f3b84cd9de566ff7b1ffb5d16e75483e9b9d06f2 100644 (file)
@@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb,
        ext4_group_t group;
        ext4_group_t last_group;
        unsigned overhead;
+       __u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0;
 
        BUG_ON(flex_gd->count == 0 || group_data == NULL);
 
@@ -266,7 +267,7 @@ next_group:
        src_group++;
        for (; src_group <= last_group; src_group++) {
                overhead = ext4_group_overhead_blocks(sb, src_group);
-               if (overhead != 0)
+               if (overhead == 0)
                        last_blk += group_data[src_group - group].blocks_count;
                else
                        break;
@@ -280,8 +281,7 @@ next_group:
                group = ext4_get_group_number(sb, start_blk - 1);
                group -= group_data[0].group;
                group_data[group].free_blocks_count--;
-               if (flexbg_size > 1)
-                       flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+               flex_gd->bg_flags[group] &= uninit_mask;
        }
 
        /* Allocate inode bitmaps */
@@ -292,22 +292,30 @@ next_group:
                group = ext4_get_group_number(sb, start_blk - 1);
                group -= group_data[0].group;
                group_data[group].free_blocks_count--;
-               if (flexbg_size > 1)
-                       flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+               flex_gd->bg_flags[group] &= uninit_mask;
        }
 
        /* Allocate inode tables */
        for (; it_index < flex_gd->count; it_index++) {
-               if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk)
+               unsigned int itb = EXT4_SB(sb)->s_itb_per_group;
+               ext4_fsblk_t next_group_start;
+
+               if (start_blk + itb > last_blk)
                        goto next_group;
                group_data[it_index].inode_table = start_blk;
-               group = ext4_get_group_number(sb, start_blk - 1);
+               group = ext4_get_group_number(sb, start_blk);
+               next_group_start = ext4_group_first_block_no(sb, group + 1);
                group -= group_data[0].group;
-               group_data[group].free_blocks_count -=
-                                       EXT4_SB(sb)->s_itb_per_group;
-               if (flexbg_size > 1)
-                       flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
 
+               if (start_blk + itb > next_group_start) {
+                       flex_gd->bg_flags[group + 1] &= uninit_mask;
+                       overhead = start_blk + itb - next_group_start;
+                       group_data[group + 1].free_blocks_count -= overhead;
+                       itb -= overhead;
+               }
+
+               group_data[group].free_blocks_count -= itb;
+               flex_gd->bg_flags[group] &= uninit_mask;
                start_blk += EXT4_SB(sb)->s_itb_per_group;
        }
 
@@ -401,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
                start = ext4_group_first_block_no(sb, group);
                group -= flex_gd->groups[0].group;
 
-               count2 = sb->s_blocksize * 8 - (block - start);
+               count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start);
                if (count2 > count)
                        count2 = count;
 
@@ -620,7 +628,7 @@ handle_ib:
                        if (err)
                                goto out;
                        count = group_table_count[j];
-                       start = group_data[i].block_bitmap;
+                       start = (&group_data[i].block_bitmap)[j];
                        block = start;
                }
 
index 1f7784de05b6c6afad4d7437202ceb6efeec3399..710fed2377d415a32b0658faabde9960ff639b84 100644 (file)
@@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        for (i = 0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
-       i = le32_to_cpu(es->s_flags);
-       if (i & EXT2_FLAGS_UNSIGNED_HASH)
-               sbi->s_hash_unsigned = 3;
-       else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
+       if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+               i = le32_to_cpu(es->s_flags);
+               if (i & EXT2_FLAGS_UNSIGNED_HASH)
+                       sbi->s_hash_unsigned = 3;
+               else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
 #ifdef __CHAR_UNSIGNED__
-               es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
-               sbi->s_hash_unsigned = 3;
+                       if (!(sb->s_flags & MS_RDONLY))
+                               es->s_flags |=
+                                       cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
+                       sbi->s_hash_unsigned = 3;
 #else
-               es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
+                       if (!(sb->s_flags & MS_RDONLY))
+                               es->s_flags |=
+                                       cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
 #endif
+               }
        }
 
        /* Handle clustersize */
index e0259a163f98e69000c28bdb78fcf2b77c2bed2d..d754e3cf99a85af0c433e71846db6ee051751ebd 100644 (file)
 struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
-       /*
-        * Write only inodes dirtied before this time. Don't forget to set
-        * older_than_this_is_set when you set this.
-        */
-       unsigned long older_than_this;
+       unsigned long *older_than_this;
        enum writeback_sync_modes sync_mode;
        unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
        unsigned int for_sync:1;        /* sync(2) WB_SYNC_ALL writeback */
-       unsigned int older_than_this_is_set:1;
        enum wb_reason reason;          /* why was writeback initiated? */
 
        struct list_head list;          /* pending work list */
@@ -252,10 +247,10 @@ static int move_expired_inodes(struct list_head *delaying_queue,
        int do_sb_sort = 0;
        int moved = 0;
 
-       WARN_ON_ONCE(!work->older_than_this_is_set);
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
-               if (inode_dirtied_after(inode, work->older_than_this))
+               if (work->older_than_this &&
+                   inode_dirtied_after(inode, *work->older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
@@ -742,8 +737,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
                .sync_mode      = WB_SYNC_NONE,
                .range_cyclic   = 1,
                .reason         = reason,
-               .older_than_this = jiffies,
-               .older_than_this_is_set = 1,
        };
 
        spin_lock(&wb->list_lock);
@@ -802,13 +795,12 @@ static long wb_writeback(struct bdi_writeback *wb,
 {
        unsigned long wb_start = jiffies;
        long nr_pages = work->nr_pages;
+       unsigned long oldest_jif;
        struct inode *inode;
        long progress;
 
-       if (!work->older_than_this_is_set) {
-               work->older_than_this = jiffies;
-               work->older_than_this_is_set = 1;
-       }
+       oldest_jif = jiffies;
+       work->older_than_this = &oldest_jif;
 
        spin_lock(&wb->list_lock);
        for (;;) {
@@ -842,10 +834,10 @@ static long wb_writeback(struct bdi_writeback *wb,
                 * safe.
                 */
                if (work->for_kupdate) {
-                       work->older_than_this = jiffies -
+                       oldest_jif = jiffies -
                                msecs_to_jiffies(dirty_expire_interval * 10);
                } else if (work->for_background)
-                       work->older_than_this = jiffies;
+                       oldest_jif = jiffies;
 
                trace_writeback_start(wb->bdi, work);
                if (list_empty(&wb->b_io))
@@ -1357,21 +1349,18 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb);
 
 /**
  * sync_inodes_sb      -       sync sb inode pages
- * @sb:                        the superblock
- * @older_than_this:   timestamp
+ * @sb: the superblock
  *
  * This function writes and waits on any dirty inode belonging to this
- * superblock that has been dirtied before given timestamp.
+ * super_block.
  */
-void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
+void sync_inodes_sb(struct super_block *sb)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
                .sb             = sb,
                .sync_mode      = WB_SYNC_ALL,
                .nr_pages       = LONG_MAX,
-               .older_than_this = older_than_this,
-               .older_than_this_is_set = 1,
                .range_cyclic   = 0,
                .done           = &done,
                .reason         = WB_REASON_SYNC,
index e1959efad64fa0f4101541683e8c422d27a37aa7..b5ebc2d7d80d30d39b21243561e1f7d26c300329 100644 (file)
@@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj)
        struct fscache_object *xobj;
        struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;
 
+       ASSERT(RB_EMPTY_NODE(&obj->objlist_link));
+
        write_lock(&fscache_object_list_lock);
 
        while (*p) {
@@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj)
  */
 void fscache_objlist_remove(struct fscache_object *obj)
 {
+       if (RB_EMPTY_NODE(&obj->objlist_link))
+               return;
+
        write_lock(&fscache_object_list_lock);
 
        BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
index 53d35c5042404738c213233220500feaf7686ae8..d3b4539f16515451cdd691fd853927d00fa3f8a8 100644 (file)
@@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object,
        object->cache = cache;
        object->cookie = cookie;
        object->parent = NULL;
+#ifdef CONFIG_FSCACHE_OBJECT_LIST
+       RB_CLEAR_NODE(&object->objlist_link);
+#endif
 
        object->oob_event_mask = 0;
        for (t = object->oob_table; t->events; t++)
index 8360674c85bcb98af88d6aaff3ee4c46fe6f31bf..60bb365f54a52efb8ff859ff746ac1af201bb7d2 100644 (file)
@@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type,
         * similarly constrained call sites
         */
        ret = start_this_handle(journal, handle, GFP_NOFS);
-       if (ret < 0)
+       if (ret < 0) {
                jbd2_journal_free_reserved(handle);
+               return ret;
+       }
        handle->h_type = type;
        handle->h_line_no = line_no;
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(jbd2_journal_start_reserved);
 
index e973b85d6afd9f136bcae002cbe70432000e5a15..5a8ea16eedbcd1d634feedce069637a717c49c19 100644 (file)
@@ -86,6 +86,8 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
                rc = posix_acl_equiv_mode(acl, &inode->i_mode);
                if (rc < 0)
                        return rc;
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
                if (rc == 0)
                        acl = NULL;
                break;
index 0d6ce895a9eec0ce3b3329d1353b594d353aeacb..0f4152defe7b6f96afa752acdbc075a512bc8c5d 100644 (file)
@@ -94,6 +94,7 @@ const void *kernfs_super_ns(struct super_block *sb)
  * @fs_type: file_system_type of the fs being mounted
  * @flags: mount flags specified for the mount
  * @root: kernfs_root of the hierarchy being mounted
+ * @new_sb_created: tell the caller if we allocated a new superblock
  * @ns: optional namespace tag of the mount
  *
  * This is to be called from each kernfs user's file_system_type->mount()
@@ -104,7 +105,8 @@ const void *kernfs_super_ns(struct super_block *sb)
  * The return value can be passed to the vfs layer verbatim.
  */
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-                              struct kernfs_root *root, const void *ns)
+                              struct kernfs_root *root, bool *new_sb_created,
+                              const void *ns)
 {
        struct super_block *sb;
        struct kernfs_super_info *info;
@@ -122,6 +124,10 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
                kfree(info);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
+
+       if (new_sb_created)
+               *new_sb_created = !sb->s_root;
+
        if (!sb->s_root) {
                error = kernfs_fill_super(sb);
                if (error) {
index 28a0a3cbd3b7818ee255f3a3c57b738d098e48c3..360114ae8b829bf705eaf4feda49b8fe484de2c0 100644 (file)
@@ -164,17 +164,16 @@ static void nfs_zap_caches_locked(struct inode *inode)
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
                nfs_fscache_invalidate(inode);
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR
-                                       | NFS_INO_INVALID_LABEL
                                        | NFS_INO_INVALID_DATA
                                        | NFS_INO_INVALID_ACCESS
                                        | NFS_INO_INVALID_ACL
                                        | NFS_INO_REVAL_PAGECACHE;
        } else
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR
-                                       | NFS_INO_INVALID_LABEL
                                        | NFS_INO_INVALID_ACCESS
                                        | NFS_INO_INVALID_ACL
                                        | NFS_INO_REVAL_PAGECACHE;
+       nfs_zap_label_cache_locked(nfsi);
 }
 
 void nfs_zap_caches(struct inode *inode)
@@ -266,6 +265,13 @@ nfs_init_locked(struct inode *inode, void *opaque)
 }
 
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+static void nfs_clear_label_invalid(struct inode *inode)
+{
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL;
+       spin_unlock(&inode->i_lock);
+}
+
 void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        struct nfs4_label *label)
 {
@@ -283,6 +289,7 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        __func__,
                                        (char *)label->label,
                                        label->len, error);
+               nfs_clear_label_invalid(inode);
        }
 }
 
@@ -1648,7 +1655,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                inode->i_blocks = fattr->du.nfs2.blocks;
 
        /* Update attrtimeo value if we're out of the unstable period */
-       if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) {
+       if (invalid & NFS_INO_INVALID_ATTR) {
                nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
                nfsi->attrtimeo_timestamp = now;
@@ -1661,7 +1668,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                }
        }
        invalid &= ~NFS_INO_INVALID_ATTR;
-       invalid &= ~NFS_INO_INVALID_LABEL;
        /* Don't invalidate the data if we were to blame */
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
                                || S_ISLNK(inode->i_mode)))
index 8b5cc04a86115e05f0a2e98e9b02a0b307b1b910..b46cf5a6732952460c68f6faeeb5479f355868d7 100644 (file)
@@ -176,7 +176,8 @@ extern struct nfs_server *nfs4_create_server(
 extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
                                                      struct nfs_fh *);
 extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
-                                       struct sockaddr *sap, size_t salen);
+                                       struct sockaddr *sap, size_t salen,
+                                       struct net *net);
 extern void nfs_free_server(struct nfs_server *server);
 extern struct nfs_server *nfs_clone_server(struct nfs_server *,
                                           struct nfs_fh *,
@@ -279,9 +280,18 @@ static inline void nfs4_label_free(struct nfs4_label *label)
        }
        return;
 }
+
+static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
+{
+       if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL))
+               nfsi->cache_validity |= NFS_INO_INVALID_LABEL;
+}
 #else
 static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
 static inline void nfs4_label_free(void *label) {}
+static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
+{
+}
 #endif /* CONFIG_NFS_V4_SECURITY_LABEL */
 
 /* proc.c */
index aa9bc973f36a31eacbca297c71f2cd9bb5fb81e9..a462ef0fb5d6dcda8bab6f211e8122d7d972b070 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/nfs_mount.h>
 #include <linux/freezer.h>
+#include <linux/xattr.h>
 
 #include "iostat.h"
 #include "internal.h"
index 860ad26a55905be060c1bcd1db5e9dde11746eec..0e46d3d1b6cc6c06854517c66ab4aa5f783cfb9e 100644 (file)
@@ -1135,6 +1135,7 @@ static int nfs_probe_destination(struct nfs_server *server)
  * @hostname: new end-point's hostname
  * @sap: new end-point's socket address
  * @salen: size of "sap"
+ * @net: net namespace
  *
  * The nfs_server must be quiescent before this function is invoked.
  * Either its session is drained (NFSv4.1+), or its transport is
@@ -1143,13 +1144,13 @@ static int nfs_probe_destination(struct nfs_server *server)
  * Returns zero on success, or a negative errno value.
  */
 int nfs4_update_server(struct nfs_server *server, const char *hostname,
-                      struct sockaddr *sap, size_t salen)
+                      struct sockaddr *sap, size_t salen, struct net *net)
 {
        struct nfs_client *clp = server->nfs_client;
        struct rpc_clnt *clnt = server->client;
        struct xprt_create xargs = {
                .ident          = clp->cl_proto,
-               .net            = &init_net,
+               .net            = net,
                .dstaddr        = sap,
                .addrlen        = salen,
                .servername     = hostname,
@@ -1189,7 +1190,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
        error = nfs4_set_client(server, hostname, sap, salen, buf,
                                clp->cl_rpcclient->cl_auth->au_flavor,
                                clp->cl_proto, clnt->cl_timeout,
-                               clp->cl_minorversion, clp->cl_net);
+                               clp->cl_minorversion, net);
        nfs_put_client(clp);
        if (error != 0) {
                nfs_server_insert_lists(server);
index 4e7f05d3e9db77d1fe96533424362c4171201014..3d5dbf80d46a8c844bf7fd96c6db6935bb76d48b 100644 (file)
@@ -121,9 +121,8 @@ static int nfs4_validate_fspath(struct dentry *dentry,
 }
 
 static size_t nfs_parse_server_name(char *string, size_t len,
-               struct sockaddr *sa, size_t salen, struct nfs_server *server)
+               struct sockaddr *sa, size_t salen, struct net *net)
 {
-       struct net *net = rpc_net_ns(server->client);
        ssize_t ret;
 
        ret = rpc_pton(net, string, len, sa, salen);
@@ -223,6 +222,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
                                     const struct nfs4_fs_location *location)
 {
        const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+       struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client);
        struct vfsmount *mnt = ERR_PTR(-ENOENT);
        char *mnt_path;
        unsigned int maxbuflen;
@@ -248,8 +248,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
                        continue;
 
                mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
-                               mountdata->addr, addr_bufsize,
-                               NFS_SB(mountdata->sb));
+                               mountdata->addr, addr_bufsize, net);
                if (mountdata->addrlen == 0)
                        continue;
 
@@ -419,6 +418,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
                const struct nfs4_fs_location *location)
 {
        const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+       struct net *net = rpc_net_ns(server->client);
        struct sockaddr *sap;
        unsigned int s;
        size_t salen;
@@ -440,7 +440,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
                        continue;
 
                salen = nfs_parse_server_name(buf->data, buf->len,
-                                               sap, addr_bufsize, server);
+                                               sap, addr_bufsize, net);
                if (salen == 0)
                        continue;
                rpc_set_port(sap, NFS_PORT);
@@ -450,7 +450,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
                if (hostname == NULL)
                        break;
 
-               error = nfs4_update_server(server, hostname, sap, salen);
+               error = nfs4_update_server(server, hostname, sap, salen, net);
                kfree(hostname);
                if (error == 0)
                        break;
index e5be72518bd7ebe813522b1c24f7fa16b539421e..e1a47217c05e14b7195fae25d5fc725f6983cd03 100644 (file)
@@ -1015,8 +1015,11 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
        if (ret == -EIO)
                /* A lost lock - don't even consider delegations */
                goto out;
-       if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
+       /* returns true if delegation stateid found and copied */
+       if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) {
+               ret = 0;
                goto out;
+       }
        if (ret != -ENOENT)
                /* nfs4_copy_delegation_stateid() didn't over-write
                 * dst, so it still has the lock stateid which we now
index 0b9ff4395e6ac320f6108f7c3cabb2d57d5a426f..abc8cbcfe90e0fca9f67471740c0b41c9055b7c6 100644 (file)
@@ -86,7 +86,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
                                struct fsnotify_mark *inode_mark,
                                struct fsnotify_mark *vfsmount_mark,
                                u32 mask, void *data, int data_type,
-                               const unsigned char *file_name)
+                               const unsigned char *file_name, u32 cookie)
 {
        struct dnotify_mark *dn_mark;
        struct dnotify_struct *dn;
index 0e792f5e3147c3cfcf38a980716075ea509b0e46..dc638f786d5c762373288942dc04cc5c5cee0750 100644 (file)
@@ -147,7 +147,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
                                 struct fsnotify_mark *inode_mark,
                                 struct fsnotify_mark *fanotify_mark,
                                 u32 mask, void *data, int data_type,
-                                const unsigned char *file_name)
+                                const unsigned char *file_name, u32 cookie)
 {
        int ret = 0;
        struct fanotify_event_info *event;
@@ -192,10 +192,12 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 
        ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
        if (ret) {
-               BUG_ON(mask & FAN_ALL_PERM_EVENTS);
+               /* Permission events shouldn't be merged */
+               BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS);
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               ret = 0;
+
+               return 0;
        }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
index b6175fa11bf856809d1ee6a43ee9b861980e9160..287a22c041496a206d94daa299be55a20b4786a2 100644 (file)
@@ -698,6 +698,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        struct fsnotify_group *group;
        int f_flags, fd;
        struct user_struct *user;
+       struct fanotify_event_info *oevent;
 
        pr_debug("%s: flags=%d event_f_flags=%d\n",
                __func__, flags, event_f_flags);
@@ -730,8 +731,20 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        group->fanotify_data.user = user;
        atomic_inc(&user->fanotify_listeners);
 
+       oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
+       if (unlikely(!oevent)) {
+               fd = -ENOMEM;
+               goto out_destroy_group;
+       }
+       group->overflow_event = &oevent->fse;
+       fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+       oevent->tgid = get_pid(task_tgid(current));
+       oevent->path.mnt = NULL;
+       oevent->path.dentry = NULL;
+
        group->fanotify_data.f_flags = event_f_flags;
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       oevent->response = 0;
        mutex_init(&group->fanotify_data.access_mutex);
        init_waitqueue_head(&group->fanotify_data.access_waitq);
        INIT_LIST_HEAD(&group->fanotify_data.access_list);
index 1d4e1ea2f37ca4995db3f16db9bd00bbf862ca93..9d3e9c50066aaf5856350cf3bc85576a79bab900 100644 (file)
@@ -179,7 +179,7 @@ static int send_to_group(struct inode *to_tell,
 
        return group->ops->handle_event(group, to_tell, inode_mark,
                                        vfsmount_mark, mask, data, data_is,
-                                       file_name);
+                                       file_name, cookie);
 }
 
 /*
index ee674fe2cec7f3f7b99ad09363b6a425ff4d6dbd..ad199598045655105e7ba4db0ed639357bf3fc6f 100644 (file)
@@ -55,6 +55,13 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
        /* clear the notification queue of all events */
        fsnotify_flush_notify(group);
 
+       /*
+        * Destroy overflow event (we cannot use fsnotify_destroy_event() as
+        * that deliberately ignores overflow events.
+        */
+       if (group->overflow_event)
+               group->ops->free_event(group->overflow_event);
+
        fsnotify_put_group(group);
 }
 
@@ -99,7 +106,6 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
        INIT_LIST_HEAD(&group->marks_list);
 
        group->ops = ops;
-       fsnotify_init_event(&group->overflow_event, NULL, FS_Q_OVERFLOW);
 
        return group;
 }
index 485eef3f4407a0371d903c08a75c9f262dfde82e..ed855ef6f0775e447489e7dd43e00ff3891c850e 100644 (file)
@@ -27,6 +27,6 @@ extern int inotify_handle_event(struct fsnotify_group *group,
                                struct fsnotify_mark *inode_mark,
                                struct fsnotify_mark *vfsmount_mark,
                                u32 mask, void *data, int data_type,
-                               const unsigned char *file_name);
+                               const unsigned char *file_name, u32 cookie);
 
 extern const struct fsnotify_ops inotify_fsnotify_ops;
index d5ee56348bb803fd0ddff46d4f3da7d0fa7016d1..43ab1e1a07a20acaca5a4741487ac5121e00bbd4 100644 (file)
@@ -67,7 +67,7 @@ int inotify_handle_event(struct fsnotify_group *group,
                         struct fsnotify_mark *inode_mark,
                         struct fsnotify_mark *vfsmount_mark,
                         u32 mask, void *data, int data_type,
-                        const unsigned char *file_name)
+                        const unsigned char *file_name, u32 cookie)
 {
        struct inotify_inode_mark *i_mark;
        struct inotify_event_info *event;
@@ -103,6 +103,7 @@ int inotify_handle_event(struct fsnotify_group *group,
        fsn_event = &event->fse;
        fsnotify_init_event(fsn_event, inode, mask);
        event->wd = i_mark->wd;
+       event->sync_cookie = cookie;
        event->name_len = len;
        if (len)
                strcpy(event->name, file_name);
index 497395c8274bc62cd0fab6c2cf89ce4950fafffc..78a2ca3966c3857a8f4a5bf5369b63ad10ef3380 100644 (file)
@@ -495,7 +495,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 
        /* Queue ignore event for the watch */
        inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
-                            NULL, FSNOTIFY_EVENT_NONE, NULL);
+                            NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
 
        i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
        /* remove this mark from the idr */
@@ -633,11 +633,23 @@ static int inotify_update_watch(struct fsnotify_group *group, struct inode *inod
 static struct fsnotify_group *inotify_new_group(unsigned int max_events)
 {
        struct fsnotify_group *group;
+       struct inotify_event_info *oevent;
 
        group = fsnotify_alloc_group(&inotify_fsnotify_ops);
        if (IS_ERR(group))
                return group;
 
+       oevent = kmalloc(sizeof(struct inotify_event_info), GFP_KERNEL);
+       if (unlikely(!oevent)) {
+               fsnotify_destroy_group(group);
+               return ERR_PTR(-ENOMEM);
+       }
+       group->overflow_event = &oevent->fse;
+       fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+       oevent->wd = -1;
+       oevent->sync_cookie = 0;
+       oevent->name_len = 0;
+
        group->max_events = max_events;
 
        spin_lock_init(&group->inotify_data.idr_lock);
index 18b3c4427dcac0f2c9125581cc171be3f1eb3a9f..1e58402171a56cd9d078ab62307951689a5630df 100644 (file)
@@ -80,7 +80,8 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
 /*
  * Add an event to the group notification queue.  The group can later pull this
  * event off the queue to deal with.  The function returns 0 if the event was
- * added to the queue, 1 if the event was merged with some other queued event.
+ * added to the queue, 1 if the event was merged with some other queued event,
+ * 2 if the queue of events has overflown.
  */
 int fsnotify_add_notify_event(struct fsnotify_group *group,
                              struct fsnotify_event *event,
@@ -95,10 +96,14 @@ int fsnotify_add_notify_event(struct fsnotify_group *group,
        mutex_lock(&group->notification_mutex);
 
        if (group->q_len >= group->max_events) {
+               ret = 2;
                /* Queue overflow event only if it isn't already queued */
-               if (list_empty(&group->overflow_event.list))
-                       event = &group->overflow_event;
-               ret = 1;
+               if (!list_empty(&group->overflow_event->list)) {
+                       mutex_unlock(&group->notification_mutex);
+                       return ret;
+               }
+               event = group->overflow_event;
+               goto queue;
        }
 
        if (!list_empty(list) && merge) {
@@ -109,6 +114,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group,
                }
        }
 
+queue:
        group->q_len++;
        list_add_tail(&event->list, list);
        mutex_unlock(&group->notification_mutex);
@@ -132,7 +138,11 @@ struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group
 
        event = list_first_entry(&group->notification_list,
                                 struct fsnotify_event, list);
-       list_del(&event->list);
+       /*
+        * We need to init list head for the case of overflow event so that
+        * check in fsnotify_add_notify_events() works
+        */
+       list_del_init(&event->list);
        group->q_len--;
 
        return event;
index 831d49a4111f8405716d96ff6a451fc9ebd59e91..cfc8dcc160437c0daacd234f43d29faeb9b2fd33 100644 (file)
@@ -581,9 +581,17 @@ int dquot_scan_active(struct super_block *sb,
                dqstats_inc(DQST_LOOKUPS);
                dqput(old_dquot);
                old_dquot = dquot;
-               ret = fn(dquot, priv);
-               if (ret < 0)
-                       goto out;
+               /*
+                * ->release_dquot() can be racing with us. Our reference
+                * protects us from new calls to it so just wait for any
+                * outstanding call and recheck the DQ_ACTIVE_B after that.
+                */
+               wait_on_dquot(dquot);
+               if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
+                       ret = fn(dquot, priv);
+                       if (ret < 0)
+                               goto out;
+               }
                spin_lock(&dq_list_lock);
                /* We are safe to continue now because our dquot could not
                 * be moved out of the inuse list while we hold the reference */
index 2b7882b508db4ce66486455d22f812e83809e77f..9a3c68cf6026ae0405ef91c07f3ec9ef02854f1a 100644 (file)
@@ -324,23 +324,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                        switch (flag) {
                        case M_INSERT:  /* insert item into L[0] */
 
-                               if (item_pos == tb->lnum[0] - 1
-                                   && tb->lbytes != -1) {
+                               if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
                                        /* part of new item falls into L[0] */
                                        int new_item_len;
                                        int version;
 
-                                       ret_val =
-                                           leaf_shift_left(tb, tb->lnum[0] - 1,
-                                                           -1);
+                                       ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, -1);
 
                                        /* Calculate item length to insert to S[0] */
-                                       new_item_len =
-                                           ih_item_len(ih) - tb->lbytes;
+                                       new_item_len = ih_item_len(ih) - tb->lbytes;
                                        /* Calculate and check item length to insert to L[0] */
-                                       put_ih_item_len(ih,
-                                                       ih_item_len(ih) -
-                                                       new_item_len);
+                                       put_ih_item_len(ih, ih_item_len(ih) - new_item_len);
 
                                        RFALSE(ih_item_len(ih) <= 0,
                                               "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d",
@@ -349,30 +343,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        /* Insert new item into L[0] */
                                        buffer_info_init_left(tb, &bi);
                                        leaf_insert_into_buf(&bi,
-                                                            n + item_pos -
-                                                            ret_val, ih, body,
-                                                            zeros_num >
-                                                            ih_item_len(ih) ?
-                                                            ih_item_len(ih) :
-                                                            zeros_num);
+                                                       n + item_pos - ret_val, ih, body,
+                                                       zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num);
 
                                        version = ih_version(ih);
 
                                        /* Calculate key component, item length and body to insert into S[0] */
-                                       set_le_ih_k_offset(ih,
-                                                          le_ih_k_offset(ih) +
-                                                          (tb->
-                                                           lbytes <<
-                                                           (is_indirect_le_ih
-                                                            (ih) ? tb->tb_sb->
-                                                            s_blocksize_bits -
-                                                            UNFM_P_SHIFT :
-                                                            0)));
+                                       set_le_ih_k_offset(ih, le_ih_k_offset(ih) +
+                                                       (tb-> lbytes << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0)));
 
                                        put_ih_item_len(ih, new_item_len);
                                        if (tb->lbytes > zeros_num) {
-                                               body +=
-                                                   (tb->lbytes - zeros_num);
+                                               body += (tb->lbytes - zeros_num);
                                                zeros_num = 0;
                                        } else
                                                zeros_num -= tb->lbytes;
@@ -383,15 +365,10 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                } else {
                                        /* new item in whole falls into L[0] */
                                        /* Shift lnum[0]-1 items to L[0] */
-                                       ret_val =
-                                           leaf_shift_left(tb, tb->lnum[0] - 1,
-                                                           tb->lbytes);
+                                       ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes);
                                        /* Insert new item into L[0] */
                                        buffer_info_init_left(tb, &bi);
-                                       leaf_insert_into_buf(&bi,
-                                                            n + item_pos -
-                                                            ret_val, ih, body,
-                                                            zeros_num);
+                                       leaf_insert_into_buf(&bi, n + item_pos - ret_val, ih, body, zeros_num);
                                        tb->insert_size[0] = 0;
                                        zeros_num = 0;
                                }
@@ -399,264 +376,117 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,  /* item h
 
                        case M_PASTE:   /* append item in L[0] */
 
-                               if (item_pos == tb->lnum[0] - 1
-                                   && tb->lbytes != -1) {
+                               if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
                                        /* we must shift the part of the appended item */
-                                       if (is_direntry_le_ih
-                                           (B_N_PITEM_HEAD(tbS0, item_pos))) {
+                                       if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) {
 
                                                RFALSE(zeros_num,
                                                       "PAP-12090: invalid parameter in case of a directory");
                                                /* directory item */
                                                if (tb->lbytes > pos_in_item) {
                                                        /* new directory entry falls into L[0] */
-                                                       struct item_head
-                                                           *pasted;
-                                                       int l_pos_in_item =
-                                                           pos_in_item;
+                                                       struct item_head *pasted;
+                                                       int l_pos_in_item = pos_in_item;
 
                                                        /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */
-                                                       ret_val =
-                                                           leaf_shift_left(tb,
-                                                                           tb->
-                                                                           lnum
-                                                                           [0],
-                                                                           tb->
-                                                                           lbytes
-                                                                           -
-                                                                           1);
-                                                       if (ret_val
-                                                           && !item_pos) {
-                                                               pasted =
-                                                                   B_N_PITEM_HEAD
-                                                                   (tb->L[0],
-                                                                    B_NR_ITEMS
-                                                                    (tb->
-                                                                     L[0]) -
-                                                                    1);
-                                                               l_pos_in_item +=
-                                                                   I_ENTRY_COUNT
-                                                                   (pasted) -
-                                                                   (tb->
-                                                                    lbytes -
-                                                                    1);
+                                                       ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1);
+                                                       if (ret_val && !item_pos) {
+                                                               pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1);
+                                                               l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1);
                                                        }
 
                                                        /* Append given directory entry to directory item */
                                                        buffer_info_init_left(tb, &bi);
-                                                       leaf_paste_in_buffer
-                                                           (&bi,
-                                                            n + item_pos -
-                                                            ret_val,
-                                                            l_pos_in_item,
-                                                            tb->insert_size[0],
-                                                            body, zeros_num);
+                                                       leaf_paste_in_buffer(&bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_num);
 
                                                        /* previous string prepared space for pasting new entry, following string pastes this entry */
 
                                                        /* when we have merge directory item, pos_in_item has been changed too */
 
                                                        /* paste new directory entry. 1 is entry number */
-                                                       leaf_paste_entries(&bi,
-                                                                          n +
-                                                                          item_pos
-                                                                          -
-                                                                          ret_val,
-                                                                          l_pos_in_item,
-                                                                          1,
-                                                                          (struct
-                                                                           reiserfs_de_head
-                                                                           *)
-                                                                          body,
-                                                                          body
-                                                                          +
-                                                                          DEH_SIZE,
-                                                                          tb->
-                                                                          insert_size
-                                                                          [0]
-                                                           );
+                                                       leaf_paste_entries(&bi, n + item_pos - ret_val, l_pos_in_item,
+                                                                          1, (struct reiserfs_de_head *) body,
+                                                                          body + DEH_SIZE, tb->insert_size[0]);
                                                        tb->insert_size[0] = 0;
                                                } else {
                                                        /* new directory item doesn't fall into L[0] */
                                                        /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */
-                                                       leaf_shift_left(tb,
-                                                                       tb->
-                                                                       lnum[0],
-                                                                       tb->
-                                                                       lbytes);
+                                                       leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
                                                }
                                                /* Calculate new position to append in item body */
                                                pos_in_item -= tb->lbytes;
                                        } else {
                                                /* regular object */
-                                               RFALSE(tb->lbytes <= 0,
-                                                      "PAP-12095: there is nothing to shift to L[0]. lbytes=%d",
-                                                      tb->lbytes);
-                                               RFALSE(pos_in_item !=
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)),
+                                               RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes);
+                                               RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),
                                                       "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d",
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)),
-                                                      pos_in_item);
+                                                      ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),pos_in_item);
 
                                                if (tb->lbytes >= pos_in_item) {
                                                        /* appended item will be in L[0] in whole */
                                                        int l_n;
 
                                                        /* this bytes number must be appended to the last item of L[h] */
-                                                       l_n =
-                                                           tb->lbytes -
-                                                           pos_in_item;
+                                                       l_n = tb->lbytes - pos_in_item;
 
                                                        /* Calculate new insert_size[0] */
-                                                       tb->insert_size[0] -=
-                                                           l_n;
+                                                       tb->insert_size[0] -= l_n;
 
-                                                       RFALSE(tb->
-                                                              insert_size[0] <=
-                                                              0,
+                                                       RFALSE(tb->insert_size[0] <= 0,
                                                               "PAP-12105: there is nothing to paste into L[0]. insert_size=%d",
-                                                              tb->
-                                                              insert_size[0]);
-                                                       ret_val =
-                                                           leaf_shift_left(tb,
-                                                                           tb->
-                                                                           lnum
-                                                                           [0],
-                                                                           ih_item_len
-                                                                           (B_N_PITEM_HEAD
-                                                                            (tbS0,
-                                                                             item_pos)));
+                                                              tb->insert_size[0]);
+                                                       ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len
+                                                                           (B_N_PITEM_HEAD(tbS0, item_pos)));
                                                        /* Append to body of item in L[0] */
                                                        buffer_info_init_left(tb, &bi);
                                                        leaf_paste_in_buffer
-                                                           (&bi,
-                                                            n + item_pos -
-                                                            ret_val,
-                                                            ih_item_len
-                                                            (B_N_PITEM_HEAD
-                                                             (tb->L[0],
-                                                              n + item_pos -
-                                                              ret_val)), l_n,
-                                                            body,
-                                                            zeros_num >
-                                                            l_n ? l_n :
-                                                            zeros_num);
+                                                           (&bi, n + item_pos - ret_val, ih_item_len
+                                                            (B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)),
+                                                            l_n, body,
+                                                            zeros_num > l_n ? l_n : zeros_num);
                                                        /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */
                                                        {
                                                                int version;
-                                                               int temp_l =
-                                                                   l_n;
-
-                                                               RFALSE
-                                                                   (ih_item_len
-                                                                    (B_N_PITEM_HEAD
-                                                                     (tbS0,
-                                                                      0)),
+                                                               int temp_l = l_n;
+
+                                                               RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)),
                                                                     "PAP-12106: item length must be 0");
-                                                               RFALSE
-                                                                   (comp_short_le_keys
-                                                                    (B_N_PKEY
-                                                                     (tbS0, 0),
-                                                                     B_N_PKEY
-                                                                     (tb->L[0],
-                                                                      n +
-                                                                      item_pos
-                                                                      -
-                                                                      ret_val)),
+                                                               RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY
+                                                                     (tb->L[0], n + item_pos - ret_val)),
                                                                     "PAP-12107: items must be of the same file");
                                                                if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) {
-                                                                       temp_l =
-                                                                           l_n
-                                                                           <<
-                                                                           (tb->
-                                                                            tb_sb->
-                                                                            s_blocksize_bits
-                                                                            -
-                                                                            UNFM_P_SHIFT);
+                                                                       temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT);
                                                                }
                                                                /* update key of first item in S0 */
-                                                               version =
-                                                                   ih_version
-                                                                   (B_N_PITEM_HEAD
-                                                                    (tbS0, 0));
-                                                               set_le_key_k_offset
-                                                                   (version,
-                                                                    B_N_PKEY
-                                                                    (tbS0, 0),
-                                                                    le_key_k_offset
-                                                                    (version,
-                                                                     B_N_PKEY
-                                                                     (tbS0,
-                                                                      0)) +
-                                                                    temp_l);
+                                                               version = ih_version(B_N_PITEM_HEAD(tbS0, 0));
+                                                               set_le_key_k_offset(version, B_N_PKEY(tbS0, 0),
+                                                                    le_key_k_offset(version,B_N_PKEY(tbS0, 0)) + temp_l);
                                                                /* update left delimiting key */
-                                                               set_le_key_k_offset
-                                                                   (version,
-                                                                    B_N_PDELIM_KEY
-                                                                    (tb->
-                                                                     CFL[0],
-                                                                     tb->
-                                                                     lkey[0]),
-                                                                    le_key_k_offset
-                                                                    (version,
-                                                                     B_N_PDELIM_KEY
-                                                                     (tb->
-                                                                      CFL[0],
-                                                                      tb->
-                                                                      lkey[0]))
-                                                                    + temp_l);
+                                                               set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]),
+                                                                    le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l);
                                                        }
 
                                                        /* Calculate new body, position in item and insert_size[0] */
                                                        if (l_n > zeros_num) {
-                                                               body +=
-                                                                   (l_n -
-                                                                    zeros_num);
+                                                               body += (l_n - zeros_num);
                                                                zeros_num = 0;
                                                        } else
-                                                               zeros_num -=
-                                                                   l_n;
+                                                               zeros_num -= l_n;
                                                        pos_in_item = 0;
 
-                                                       RFALSE
-                                                           (comp_short_le_keys
-                                                            (B_N_PKEY(tbS0, 0),
-                                                             B_N_PKEY(tb->L[0],
-                                                                      B_NR_ITEMS
-                                                                      (tb->
-                                                                       L[0]) -
-                                                                      1))
-                                                            ||
-                                                            !op_is_left_mergeable
-                                                            (B_N_PKEY(tbS0, 0),
-                                                             tbS0->b_size)
-                                                            ||
-                                                            !op_is_left_mergeable
-                                                            (B_N_PDELIM_KEY
-                                                             (tb->CFL[0],
-                                                              tb->lkey[0]),
-                                                             tbS0->b_size),
+                                                       RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1))
+                                                            || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)
+                                                            || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size),
                                                             "PAP-12120: item must be merge-able with left neighboring item");
                                                } else {        /* only part of the appended item will be in L[0] */
 
                                                        /* Calculate position in item for append in S[0] */
-                                                       pos_in_item -=
-                                                           tb->lbytes;
+                                                       pos_in_item -= tb->lbytes;
 
-                                                       RFALSE(pos_in_item <= 0,
-                                                              "PAP-12125: no place for paste. pos_in_item=%d",
-                                                              pos_in_item);
+                                                       RFALSE(pos_in_item <= 0, "PAP-12125: no place for paste. pos_in_item=%d", pos_in_item);
 
                                                        /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
-                                                       leaf_shift_left(tb,
-                                                                       tb->
-                                                                       lnum[0],
-                                                                       tb->
-                                                                       lbytes);
+                                                       leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
                                                }
                                        }
                                } else {        /* appended item will be in L[0] in whole */
@@ -665,52 +495,30 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
 
                                        if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) {       /* if we paste into first item of S[0] and it is left mergable */
                                                /* then increment pos_in_item by the size of the last item in L[0] */
-                                               pasted =
-                                                   B_N_PITEM_HEAD(tb->L[0],
-                                                                  n - 1);
+                                               pasted = B_N_PITEM_HEAD(tb->L[0], n - 1);
                                                if (is_direntry_le_ih(pasted))
-                                                       pos_in_item +=
-                                                           ih_entry_count
-                                                           (pasted);
+                                                       pos_in_item += ih_entry_count(pasted);
                                                else
-                                                       pos_in_item +=
-                                                           ih_item_len(pasted);
+                                                       pos_in_item += ih_item_len(pasted);
                                        }
 
                                        /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
-                                       ret_val =
-                                           leaf_shift_left(tb, tb->lnum[0],
-                                                           tb->lbytes);
+                                       ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
                                        /* Append to body of item in L[0] */
                                        buffer_info_init_left(tb, &bi);
-                                       leaf_paste_in_buffer(&bi,
-                                                            n + item_pos -
-                                                            ret_val,
+                                       leaf_paste_in_buffer(&bi, n + item_pos - ret_val,
                                                             pos_in_item,
                                                             tb->insert_size[0],
                                                             body, zeros_num);
 
                                        /* if appended item is directory, paste entry */
-                                       pasted =
-                                           B_N_PITEM_HEAD(tb->L[0],
-                                                          n + item_pos -
-                                                          ret_val);
+                                       pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val);
                                        if (is_direntry_le_ih(pasted))
-                                               leaf_paste_entries(&bi,
-                                                                  n +
-                                                                  item_pos -
-                                                                  ret_val,
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
-                                                   );
+                                               leaf_paste_entries(&bi, n + item_pos - ret_val,
+                                                                  pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *) body,
+                                                                  body + DEH_SIZE,
+                                                                  tb->insert_size[0]);
                                        /* if appended item is indirect item, put unformatted node into un list */
                                        if (is_indirect_le_ih(pasted))
                                                set_ih_free_space(pasted, 0);
@@ -722,13 +530,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
                                reiserfs_panic(tb->tb_sb, "PAP-12130",
                                               "lnum > 0: unexpected mode: "
                                               " %s(%d)",
-                                              (flag ==
-                                               M_DELETE) ? "DELETE" : ((flag ==
-                                                                        M_CUT)
-                                                                       ? "CUT"
-                                                                       :
-                                                                       "UNKNOWN"),
-                                              flag);
+                                              (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                        }
                } else {
                        /* new item doesn't fall into L[0] */
@@ -748,14 +550,12 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                case M_INSERT:  /* insert item */
                        if (n - tb->rnum[0] < item_pos) {       /* new item or its part falls to R[0] */
                                if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) {      /* part of new item falls into R[0] */
-                                       loff_t old_key_comp, old_len,
-                                           r_zeros_number;
+                                       loff_t old_key_comp, old_len, r_zeros_number;
                                        const char *r_body;
                                        int version;
                                        loff_t offset;
 
-                                       leaf_shift_right(tb, tb->rnum[0] - 1,
-                                                        -1);
+                                       leaf_shift_right(tb, tb->rnum[0] - 1, -1);
 
                                        version = ih_version(ih);
                                        /* Remember key component and item length */
@@ -763,29 +563,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        old_len = ih_item_len(ih);
 
                                        /* Calculate key component and item length to insert into R[0] */
-                                       offset =
-                                           le_ih_k_offset(ih) +
-                                           ((old_len -
-                                             tb->
-                                             rbytes) << (is_indirect_le_ih(ih)
-                                                         ? tb->tb_sb->
-                                                         s_blocksize_bits -
-                                                         UNFM_P_SHIFT : 0));
+                                       offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0));
                                        set_le_ih_k_offset(ih, offset);
                                        put_ih_item_len(ih, tb->rbytes);
                                        /* Insert part of the item into R[0] */
                                        buffer_info_init_right(tb, &bi);
                                        if ((old_len - tb->rbytes) > zeros_num) {
                                                r_zeros_number = 0;
-                                               r_body =
-                                                   body + (old_len -
-                                                           tb->rbytes) -
-                                                   zeros_num;
+                                               r_body = body + (old_len - tb->rbytes) - zeros_num;
                                        } else {
                                                r_body = body;
-                                               r_zeros_number =
-                                                   zeros_num - (old_len -
-                                                                tb->rbytes);
+                                               r_zeros_number = zeros_num - (old_len - tb->rbytes);
                                                zeros_num -= r_zeros_number;
                                        }
 
@@ -798,25 +586,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
 
                                        /* Calculate key component and item length to insert into S[0] */
                                        set_le_ih_k_offset(ih, old_key_comp);
-                                       put_ih_item_len(ih,
-                                                       old_len - tb->rbytes);
+                                       put_ih_item_len(ih, old_len - tb->rbytes);
 
                                        tb->insert_size[0] -= tb->rbytes;
 
                                } else {        /* whole new item falls into R[0] */
 
                                        /* Shift rnum[0]-1 items to R[0] */
-                                       ret_val =
-                                           leaf_shift_right(tb,
-                                                            tb->rnum[0] - 1,
-                                                            tb->rbytes);
+                                       ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes);
                                        /* Insert new item into R[0] */
                                        buffer_info_init_right(tb, &bi);
-                                       leaf_insert_into_buf(&bi,
-                                                            item_pos - n +
-                                                            tb->rnum[0] - 1,
-                                                            ih, body,
-                                                            zeros_num);
+                                       leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1,
+                                                            ih, body, zeros_num);
 
                                        if (item_pos - n + tb->rnum[0] - 1 == 0) {
                                                replace_key(tb, tb->CFR[0],
@@ -841,200 +622,97 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
 
                                                RFALSE(zeros_num,
                                                       "PAP-12145: invalid parameter in case of a directory");
-                                               entry_count =
-                                                   I_ENTRY_COUNT(B_N_PITEM_HEAD
-                                                                 (tbS0,
-                                                                  item_pos));
+                                               entry_count = I_ENTRY_COUNT(B_N_PITEM_HEAD
+                                                                 (tbS0, item_pos));
                                                if (entry_count - tb->rbytes <
                                                    pos_in_item)
                                                        /* new directory entry falls into R[0] */
                                                {
                                                        int paste_entry_position;
 
-                                                       RFALSE(tb->rbytes - 1 >=
-                                                              entry_count
-                                                              || !tb->
-                                                              insert_size[0],
+                                                       RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0],
                                                               "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d",
-                                                              tb->rbytes,
-                                                              entry_count);
+                                                              tb->rbytes, entry_count);
                                                        /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */
-                                                       leaf_shift_right(tb,
-                                                                        tb->
-                                                                        rnum
-                                                                        [0],
-                                                                        tb->
-                                                                        rbytes
-                                                                        - 1);
+                                                       leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1);
                                                        /* Paste given directory entry to directory item */
-                                                       paste_entry_position =
-                                                           pos_in_item -
-                                                           entry_count +
-                                                           tb->rbytes - 1;
+                                                       paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1;
                                                        buffer_info_init_right(tb, &bi);
-                                                       leaf_paste_in_buffer
-                                                           (&bi, 0,
-                                                            paste_entry_position,
-                                                            tb->insert_size[0],
-                                                            body, zeros_num);
+                                                       leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, zeros_num);
                                                        /* paste entry */
-                                                       leaf_paste_entries(&bi,
-                                                                          0,
-                                                                          paste_entry_position,
-                                                                          1,
-                                                                          (struct
-                                                                           reiserfs_de_head
-                                                                           *)
-                                                                          body,
-                                                                          body
-                                                                          +
-                                                                          DEH_SIZE,
-                                                                          tb->
-                                                                          insert_size
-                                                                          [0]
-                                                           );
-
-                                                       if (paste_entry_position
-                                                           == 0) {
+                                                       leaf_paste_entries(&bi, 0, paste_entry_position, 1,
+                                                                          (struct reiserfs_de_head *) body,
+                                                                          body + DEH_SIZE, tb->insert_size[0]);
+
+                                                       if (paste_entry_position == 0) {
                                                                /* change delimiting keys */
-                                                               replace_key(tb,
-                                                                           tb->
-                                                                           CFR
-                                                                           [0],
-                                                                           tb->
-                                                                           rkey
-                                                                           [0],
-                                                                           tb->
-                                                                           R
-                                                                           [0],
-                                                                           0);
+                                                               replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0);
                                                        }
 
                                                        tb->insert_size[0] = 0;
                                                        pos_in_item++;
                                                } else {        /* new directory entry doesn't fall into R[0] */
 
-                                                       leaf_shift_right(tb,
-                                                                        tb->
-                                                                        rnum
-                                                                        [0],
-                                                                        tb->
-                                                                        rbytes);
+                                                       leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                                                }
                                        } else {        /* regular object */
 
-                                               int n_shift, n_rem,
-                                                   r_zeros_number;
+                                               int n_shift, n_rem, r_zeros_number;
                                                const char *r_body;
 
                                                /* Calculate number of bytes which must be shifted from appended item */
-                                               if ((n_shift =
-                                                    tb->rbytes -
-                                                    tb->insert_size[0]) < 0)
+                                               if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0)
                                                        n_shift = 0;
 
-                                               RFALSE(pos_in_item !=
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)),
+                                               RFALSE(pos_in_item != ih_item_len
+                                                      (B_N_PITEM_HEAD(tbS0, item_pos)),
                                                       "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d",
-                                                      pos_in_item,
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)));
-
-                                               leaf_shift_right(tb,
-                                                                tb->rnum[0],
-                                                                n_shift);
+                                                      pos_in_item, ih_item_len
+                                                      (B_N_PITEM_HEAD(tbS0, item_pos)));
+
+                                               leaf_shift_right(tb, tb->rnum[0], n_shift);
                                                /* Calculate number of bytes which must remain in body after appending to R[0] */
-                                               if ((n_rem =
-                                                    tb->insert_size[0] -
-                                                    tb->rbytes) < 0)
+                                               if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0)
                                                        n_rem = 0;
 
                                                {
                                                        int version;
-                                                       unsigned long temp_rem =
-                                                           n_rem;
-
-                                                       version =
-                                                           ih_version
-                                                           (B_N_PITEM_HEAD
-                                                            (tb->R[0], 0));
-                                                       if (is_indirect_le_key
-                                                           (version,
-                                                            B_N_PKEY(tb->R[0],
-                                                                     0))) {
-                                                               temp_rem =
-                                                                   n_rem <<
-                                                                   (tb->tb_sb->
-                                                                    s_blocksize_bits
-                                                                    -
-                                                                    UNFM_P_SHIFT);
+                                                       unsigned long temp_rem = n_rem;
+
+                                                       version = ih_version(B_N_PITEM_HEAD(tb->R[0], 0));
+                                                       if (is_indirect_le_key(version, B_N_PKEY(tb->R[0], 0))) {
+                                                               temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT);
                                                        }
-                                                       set_le_key_k_offset
-                                                           (version,
-                                                            B_N_PKEY(tb->R[0],
-                                                                     0),
-                                                            le_key_k_offset
-                                                            (version,
-                                                             B_N_PKEY(tb->R[0],
-                                                                      0)) +
-                                                            temp_rem);
-                                                       set_le_key_k_offset
-                                                           (version,
-                                                            B_N_PDELIM_KEY(tb->
-                                                                           CFR
-                                                                           [0],
-                                                                           tb->
-                                                                           rkey
-                                                                           [0]),
-                                                            le_key_k_offset
-                                                            (version,
-                                                             B_N_PDELIM_KEY
-                                                             (tb->CFR[0],
-                                                              tb->rkey[0])) +
-                                                            temp_rem);
+                                                       set_le_key_k_offset(version, B_N_PKEY(tb->R[0], 0),
+                                                            le_key_k_offset(version, B_N_PKEY(tb->R[0], 0)) + temp_rem);
+                                                       set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]),
+                                                            le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0])) + temp_rem);
                                                }
 /*               k_offset (B_N_PKEY(tb->R[0],0)) += n_rem;
                  k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/
-                                               do_balance_mark_internal_dirty
-                                                   (tb, tb->CFR[0], 0);
+                                               do_balance_mark_internal_dirty(tb, tb->CFR[0], 0);
 
                                                /* Append part of body into R[0] */
                                                buffer_info_init_right(tb, &bi);
                                                if (n_rem > zeros_num) {
                                                        r_zeros_number = 0;
-                                                       r_body =
-                                                           body + n_rem -
-                                                           zeros_num;
+                                                       r_body = body + n_rem - zeros_num;
                                                } else {
                                                        r_body = body;
-                                                       r_zeros_number =
-                                                           zeros_num - n_rem;
-                                                       zeros_num -=
-                                                           r_zeros_number;
+                                                       r_zeros_number = zeros_num - n_rem;
+                                                       zeros_num -= r_zeros_number;
                                                }
 
-                                               leaf_paste_in_buffer(&bi, 0,
-                                                                    n_shift,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0] -
-                                                                    n_rem,
-                                                                    r_body,
-                                                                    r_zeros_number);
-
-                                               if (is_indirect_le_ih
-                                                   (B_N_PITEM_HEAD
-                                                    (tb->R[0], 0))) {
+                                               leaf_paste_in_buffer(&bi, 0, n_shift,
+                                                                    tb->insert_size[0] - n_rem,
+                                                                    r_body, r_zeros_number);
+
+                                               if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->R[0], 0))) {
 #if 0
                                                        RFALSE(n_rem,
                                                               "PAP-12160: paste more than one unformatted node pointer");
 #endif
-                                                       set_ih_free_space
-                                                           (B_N_PITEM_HEAD
-                                                            (tb->R[0], 0), 0);
+                                                       set_ih_free_space(B_N_PITEM_HEAD(tb->R[0], 0), 0);
                                                }
                                                tb->insert_size[0] = n_rem;
                                                if (!n_rem)
@@ -1044,58 +722,28 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
 
                                        struct item_head *pasted;
 
-                                       ret_val =
-                                           leaf_shift_right(tb, tb->rnum[0],
-                                                            tb->rbytes);
+                                       ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                                        /* append item in R[0] */
                                        if (pos_in_item >= 0) {
                                                buffer_info_init_right(tb, &bi);
-                                               leaf_paste_in_buffer(&bi,
-                                                                    item_pos -
-                                                                    n +
-                                                                    tb->
-                                                                    rnum[0],
-                                                                    pos_in_item,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0], body,
-                                                                    zeros_num);
+                                               leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0], pos_in_item,
+                                                                    tb->insert_size[0], body, zeros_num);
                                        }
 
                                        /* paste new entry, if item is directory item */
-                                       pasted =
-                                           B_N_PITEM_HEAD(tb->R[0],
-                                                          item_pos - n +
-                                                          tb->rnum[0]);
-                                       if (is_direntry_le_ih(pasted)
-                                           && pos_in_item >= 0) {
-                                               leaf_paste_entries(&bi,
-                                                                  item_pos -
-                                                                  n +
-                                                                  tb->rnum[0],
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
-                                                   );
+                                       pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]);
+                                       if (is_direntry_le_ih(pasted) && pos_in_item >= 0) {
+                                               leaf_paste_entries(&bi, item_pos - n + tb->rnum[0],
+                                                                  pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *) body,
+                                                                  body + DEH_SIZE, tb->insert_size[0]);
                                                if (!pos_in_item) {
 
-                                                       RFALSE(item_pos - n +
-                                                              tb->rnum[0],
+                                                       RFALSE(item_pos - n + tb->rnum[0],
                                                               "PAP-12165: directory item must be first item of node when pasting is in 0th position");
 
                                                        /* update delimiting keys */
-                                                       replace_key(tb,
-                                                                   tb->CFR[0],
-                                                                   tb->rkey[0],
-                                                                   tb->R[0],
-                                                                   0);
+                                                       replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
                                                }
                                        }
 
@@ -1111,22 +759,16 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                default:        /* cases d and t */
                        reiserfs_panic(tb->tb_sb, "PAP-12175",
                                       "rnum > 0: unexpected mode: %s(%d)",
-                                      (flag ==
-                                       M_DELETE) ? "DELETE" : ((flag ==
-                                                                M_CUT) ? "CUT"
-                                                               : "UNKNOWN"),
-                                      flag);
+                                      (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                }
 
        }
 
        /* tb->rnum[0] > 0 */
        RFALSE(tb->blknum[0] > 3,
-              "PAP-12180: blknum can not be %d. It must be <= 3",
-              tb->blknum[0]);
+              "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]);
        RFALSE(tb->blknum[0] < 0,
-              "PAP-12185: blknum can not be %d. It must be >= 0",
-              tb->blknum[0]);
+              "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]);
 
        /* if while adding to a node we discover that it is possible to split
           it in two, and merge the left part into the left neighbor and the
@@ -1177,8 +819,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
 
                        if (n - snum[i] < item_pos) {   /* new item or it's part falls to first new node S_new[i] */
                                if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) {   /* part of new item falls into S_new[i] */
-                                       int old_key_comp, old_len,
-                                           r_zeros_number;
+                                       int old_key_comp, old_len, r_zeros_number;
                                        const char *r_body;
                                        int version;
 
@@ -1192,15 +833,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        old_len = ih_item_len(ih);
 
                                        /* Calculate key component and item length to insert into S_new[i] */
-                                       set_le_ih_k_offset(ih,
-                                                          le_ih_k_offset(ih) +
-                                                          ((old_len -
-                                                            sbytes[i]) <<
-                                                           (is_indirect_le_ih
-                                                            (ih) ? tb->tb_sb->
-                                                            s_blocksize_bits -
-                                                            UNFM_P_SHIFT :
-                                                            0)));
+                                       set_le_ih_k_offset(ih, le_ih_k_offset(ih) +
+                                                          ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0)));
 
                                        put_ih_item_len(ih, sbytes[i]);
 
@@ -1209,39 +843,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
 
                                        if ((old_len - sbytes[i]) > zeros_num) {
                                                r_zeros_number = 0;
-                                               r_body =
-                                                   body + (old_len -
-                                                           sbytes[i]) -
-                                                   zeros_num;
+                                               r_body = body + (old_len - sbytes[i]) - zeros_num;
                                        } else {
                                                r_body = body;
-                                               r_zeros_number =
-                                                   zeros_num - (old_len -
-                                                                sbytes[i]);
+                                               r_zeros_number = zeros_num - (old_len - sbytes[i]);
                                                zeros_num -= r_zeros_number;
                                        }
 
-                                       leaf_insert_into_buf(&bi, 0, ih, r_body,
-                                                            r_zeros_number);
+                                       leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number);
 
                                        /* Calculate key component and item length to insert into S[i] */
                                        set_le_ih_k_offset(ih, old_key_comp);
-                                       put_ih_item_len(ih,
-                                                       old_len - sbytes[i]);
+                                       put_ih_item_len(ih, old_len - sbytes[i]);
                                        tb->insert_size[0] -= sbytes[i];
                                } else {        /* whole new item falls into S_new[i] */
 
                                        /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */
                                        leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
-                                                       snum[i] - 1, sbytes[i],
-                                                       S_new[i]);
+                                                       snum[i] - 1, sbytes[i], S_new[i]);
 
                                        /* Insert new item into S_new[i] */
                                        buffer_info_init_bh(tb, &bi, S_new[i]);
-                                       leaf_insert_into_buf(&bi,
-                                                            item_pos - n +
-                                                            snum[i] - 1, ih,
-                                                            body, zeros_num);
+                                       leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1,
+                                                            ih, body, zeros_num);
 
                                        zeros_num = tb->insert_size[0] = 0;
                                }
@@ -1268,150 +892,73 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,  /* item h
 
                                                int entry_count;
 
-                                               entry_count =
-                                                   ih_entry_count(aux_ih);
+                                               entry_count = ih_entry_count(aux_ih);
 
-                                               if (entry_count - sbytes[i] <
-                                                   pos_in_item
-                                                   && pos_in_item <=
-                                                   entry_count) {
+                                               if (entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count) {
                                                        /* new directory entry falls into S_new[i] */
 
-                                                       RFALSE(!tb->
-                                                              insert_size[0],
-                                                              "PAP-12215: insert_size is already 0");
-                                                       RFALSE(sbytes[i] - 1 >=
-                                                              entry_count,
+                                                       RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0");
+                                                       RFALSE(sbytes[i] - 1 >= entry_count,
                                                               "PAP-12220: there are no so much entries (%d), only %d",
-                                                              sbytes[i] - 1,
-                                                              entry_count);
+                                                              sbytes[i] - 1, entry_count);
 
                                                        /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */
-                                                       leaf_move_items
-                                                           (LEAF_FROM_S_TO_SNEW,
-                                                            tb, snum[i],
-                                                            sbytes[i] - 1,
-                                                            S_new[i]);
+                                                       leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i] - 1, S_new[i]);
                                                        /* Paste given directory entry to directory item */
                                                        buffer_info_init_bh(tb, &bi, S_new[i]);
-                                                       leaf_paste_in_buffer
-                                                           (&bi, 0,
-                                                            pos_in_item -
-                                                            entry_count +
-                                                            sbytes[i] - 1,
-                                                            tb->insert_size[0],
-                                                            body, zeros_num);
+                                                       leaf_paste_in_buffer(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1,
+                                                            tb->insert_size[0], body, zeros_num);
                                                        /* paste new directory entry */
-                                                       leaf_paste_entries(&bi,
-                                                                          0,
-                                                                          pos_in_item
-                                                                          -
-                                                                          entry_count
-                                                                          +
-                                                                          sbytes
-                                                                          [i] -
-                                                                          1, 1,
-                                                                          (struct
-                                                                           reiserfs_de_head
-                                                                           *)
-                                                                          body,
-                                                                          body
-                                                                          +
-                                                                          DEH_SIZE,
-                                                                          tb->
-                                                                          insert_size
-                                                                          [0]
-                                                           );
+                                                       leaf_paste_entries(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, 1,
+                                                                          (struct reiserfs_de_head *) body,
+                                                                          body + DEH_SIZE, tb->insert_size[0]);
                                                        tb->insert_size[0] = 0;
                                                        pos_in_item++;
                                                } else {        /* new directory entry doesn't fall into S_new[i] */
-                                                       leaf_move_items
-                                                           (LEAF_FROM_S_TO_SNEW,
-                                                            tb, snum[i],
-                                                            sbytes[i],
-                                                            S_new[i]);
+                                                       leaf_move_items(LEAF_FROM_S_TO_SNEW,tb, snum[i], sbytes[i], S_new[i]);
                                                }
                                        } else {        /* regular object */
 
-                                               int n_shift, n_rem,
-                                                   r_zeros_number;
+                                               int n_shift, n_rem, r_zeros_number;
                                                const char *r_body;
 
-                                               RFALSE(pos_in_item !=
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos))
-                                                      || tb->insert_size[0] <=
-                                                      0,
+                                               RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)) || tb->insert_size[0] <= 0,
                                                       "PAP-12225: item too short or insert_size <= 0");
 
                                                /* Calculate number of bytes which must be shifted from appended item */
-                                               n_shift =
-                                                   sbytes[i] -
-                                                   tb->insert_size[0];
+                                               n_shift = sbytes[i] - tb->insert_size[0];
                                                if (n_shift < 0)
                                                        n_shift = 0;
-                                               leaf_move_items
-                                                   (LEAF_FROM_S_TO_SNEW, tb,
-                                                    snum[i], n_shift,
-                                                    S_new[i]);
+                                               leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]);
 
                                                /* Calculate number of bytes which must remain in body after append to S_new[i] */
-                                               n_rem =
-                                                   tb->insert_size[0] -
-                                                   sbytes[i];
+                                               n_rem = tb->insert_size[0] - sbytes[i];
                                                if (n_rem < 0)
                                                        n_rem = 0;
                                                /* Append part of body into S_new[0] */
                                                buffer_info_init_bh(tb, &bi, S_new[i]);
                                                if (n_rem > zeros_num) {
                                                        r_zeros_number = 0;
-                                                       r_body =
-                                                           body + n_rem -
-                                                           zeros_num;
+                                                       r_body = body + n_rem - zeros_num;
                                                } else {
                                                        r_body = body;
-                                                       r_zeros_number =
-                                                           zeros_num - n_rem;
-                                                       zeros_num -=
-                                                           r_zeros_number;
+                                                       r_zeros_number = zeros_num - n_rem;
+                                                       zeros_num -= r_zeros_number;
                                                }
 
-                                               leaf_paste_in_buffer(&bi, 0,
-                                                                    n_shift,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0] -
-                                                                    n_rem,
-                                                                    r_body,
-                                                                    r_zeros_number);
+                                               leaf_paste_in_buffer(&bi, 0, n_shift,
+                                                                    tb->insert_size[0] - n_rem,
+                                                                    r_body, r_zeros_number);
                                                {
                                                        struct item_head *tmp;
 
-                                                       tmp =
-                                                           B_N_PITEM_HEAD(S_new
-                                                                          [i],
-                                                                          0);
+                                                       tmp = B_N_PITEM_HEAD(S_new[i], 0);
                                                        if (is_indirect_le_ih
                                                            (tmp)) {
-                                                               set_ih_free_space
-                                                                   (tmp, 0);
-                                                               set_le_ih_k_offset
-                                                                   (tmp,
-                                                                    le_ih_k_offset
-                                                                    (tmp) +
-                                                                    (n_rem <<
-                                                                     (tb->
-                                                                      tb_sb->
-                                                                      s_blocksize_bits
-                                                                      -
-                                                                      UNFM_P_SHIFT)));
+                                                               set_ih_free_space(tmp, 0);
+                                                               set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT)));
                                                        } else {
-                                                               set_le_ih_k_offset
-                                                                   (tmp,
-                                                                    le_ih_k_offset
-                                                                    (tmp) +
-                                                                    n_rem);
+                                                               set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem);
                                                        }
                                                }
 
@@ -1426,8 +973,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
                                        struct item_head *pasted;
 
 #ifdef CONFIG_REISERFS_CHECK
-                                       struct item_head *ih_check =
-                                           B_N_PITEM_HEAD(tbS0, item_pos);
+                                       struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos);
 
                                        if (!is_direntry_le_ih(ih_check)
                                            && (pos_in_item != ih_item_len(ih_check)
@@ -1439,8 +985,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
                                                             "to ih_item_len");
 #endif                         /* CONFIG_REISERFS_CHECK */
 
-                                       leaf_mi =
-                                           leaf_move_items(LEAF_FROM_S_TO_SNEW,
+                                       leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW,
                                                            tb, snum[i],
                                                            sbytes[i],
                                                            S_new[i]);
@@ -1452,30 +997,19 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                                        /* paste into item */
                                        buffer_info_init_bh(tb, &bi, S_new[i]);
                                        leaf_paste_in_buffer(&bi,
-                                                            item_pos - n +
-                                                            snum[i],
+                                                            item_pos - n + snum[i],
                                                             pos_in_item,
                                                             tb->insert_size[0],
                                                             body, zeros_num);
 
-                                       pasted =
-                                           B_N_PITEM_HEAD(S_new[i],
-                                                          item_pos - n +
-                                                          snum[i]);
+                                       pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]);
                                        if (is_direntry_le_ih(pasted)) {
                                                leaf_paste_entries(&bi,
-                                                                  item_pos -
-                                                                  n + snum[i],
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
+                                                                  item_pos - n + snum[i],
+                                                                  pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *)body,
+                                                                  body + DEH_SIZE,
+                                                                  tb->insert_size[0]
                                                    );
                                        }
 
@@ -1495,11 +1029,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                default:        /* cases d and t */
                        reiserfs_panic(tb->tb_sb, "PAP-12245",
                                       "blknum > 2: unexpected mode: %s(%d)",
-                                      (flag ==
-                                       M_DELETE) ? "DELETE" : ((flag ==
-                                                                M_CUT) ? "CUT"
-                                                               : "UNKNOWN"),
-                                      flag);
+                                      (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                }
 
                memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE);
@@ -1524,9 +1054,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                        /* If we insert the first key change the delimiting key */
                        if (item_pos == 0) {
                                if (tb->CFL[0]) /* can be 0 in reiserfsck */
-                                       replace_key(tb, tb->CFL[0], tb->lkey[0],
-                                                   tbS0, 0);
-
+                                       replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
                        }
                        break;
 
@@ -1536,53 +1064,27 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,  /* item h
                                pasted = B_N_PITEM_HEAD(tbS0, item_pos);
                                /* when directory, may be new entry already pasted */
                                if (is_direntry_le_ih(pasted)) {
-                                       if (pos_in_item >= 0 &&
-                                           pos_in_item <=
-                                           ih_entry_count(pasted)) {
+                                       if (pos_in_item >= 0 && pos_in_item <= ih_entry_count(pasted)) {
 
                                                RFALSE(!tb->insert_size[0],
                                                       "PAP-12260: insert_size is 0 already");
 
                                                /* prepare space */
                                                buffer_info_init_tbS0(tb, &bi);
-                                               leaf_paste_in_buffer(&bi,
-                                                                    item_pos,
-                                                                    pos_in_item,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0], body,
+                                               leaf_paste_in_buffer(&bi, item_pos, pos_in_item,
+                                                                    tb->insert_size[0], body,
                                                                     zeros_num);
 
                                                /* paste entry */
-                                               leaf_paste_entries(&bi,
-                                                                  item_pos,
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
-                                                   );
+                                               leaf_paste_entries(&bi, item_pos, pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *)body,
+                                                                  body + DEH_SIZE,
+                                                                  tb->insert_size[0]);
                                                if (!item_pos && !pos_in_item) {
-                                                       RFALSE(!tb->CFL[0]
-                                                              || !tb->L[0],
+                                                       RFALSE(!tb->CFL[0] || !tb->L[0],
                                                               "PAP-12270: CFL[0]/L[0] must be specified");
-                                                       if (tb->CFL[0]) {
-                                                               replace_key(tb,
-                                                                           tb->
-                                                                           CFL
-                                                                           [0],
-                                                                           tb->
-                                                                           lkey
-                                                                           [0],
-                                                                           tbS0,
-                                                                           0);
-
-                                                       }
+                                                       if (tb->CFL[0])
+                                                               replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
                                                }
                                                tb->insert_size[0] = 0;
                                        }
@@ -1593,13 +1095,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                                                       "PAP-12275: insert size must not be %d",
                                                       tb->insert_size[0]);
                                                buffer_info_init_tbS0(tb, &bi);
-                                               leaf_paste_in_buffer(&bi,
-                                                                    item_pos,
-                                                                    pos_in_item,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0], body,
-                                                                    zeros_num);
+                                               leaf_paste_in_buffer(&bi, item_pos, pos_in_item,
+                                                                    tb->insert_size[0], body, zeros_num);
 
                                                if (is_indirect_le_ih(pasted)) {
 #if 0
@@ -1611,8 +1108,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                                               tb->
                                                               insert_size[0]);
 #endif
-                                                       set_ih_free_space
-                                                           (pasted, 0);
+                                                       set_ih_free_space(pasted, 0);
                                                }
                                                tb->insert_size[0] = 0;
                                        }
@@ -1620,8 +1116,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        else {
                                                if (tb->insert_size[0]) {
                                                        print_cur_tb("12285");
-                                                       reiserfs_panic(tb->
-                                                                      tb_sb,
+                                                       reiserfs_panic(tb->tb_sb,
                                                            "PAP-12285",
                                                            "insert_size "
                                                            "must be 0 "
index e8ba024a055b5a55d6320ba38edf1338c7d90e65..b28d1dd10e8b70194a604a1fca654237edd817be 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
  * wait == 1 case since in that case write_inode() functions do
  * sync_dirty_buffer() and thus effectively write one block at a time.
  */
-static int __sync_filesystem(struct super_block *sb, int wait,
-                            unsigned long start)
+static int __sync_filesystem(struct super_block *sb, int wait)
 {
        if (wait)
-               sync_inodes_sb(sb, start);
+               sync_inodes_sb(sb);
        else
                writeback_inodes_sb(sb, WB_REASON_SYNC);
 
@@ -48,7 +47,6 @@ static int __sync_filesystem(struct super_block *sb, int wait,
 int sync_filesystem(struct super_block *sb)
 {
        int ret;
-       unsigned long start = jiffies;
 
        /*
         * We need to be protected against the filesystem going from
@@ -62,17 +60,17 @@ int sync_filesystem(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
-       ret = __sync_filesystem(sb, 0, start);
+       ret = __sync_filesystem(sb, 0);
        if (ret < 0)
                return ret;
-       return __sync_filesystem(sb, 1, start);
+       return __sync_filesystem(sb, 1);
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
 static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
        if (!(sb->s_flags & MS_RDONLY))
-               sync_inodes_sb(sb, *((unsigned long *)arg));
+               sync_inodes_sb(sb);
 }
 
 static void sync_fs_one_sb(struct super_block *sb, void *arg)
@@ -104,10 +102,9 @@ static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
 SYSCALL_DEFINE0(sync)
 {
        int nowait = 0, wait = 1;
-       unsigned long start = jiffies;
 
        wakeup_flusher_threads(0, WB_REASON_SYNC);
-       iterate_supers(sync_inodes_one_sb, &start);
+       iterate_supers(sync_inodes_one_sb, NULL);
        iterate_supers(sync_fs_one_sb, &nowait);
        iterate_supers(sync_fs_one_sb, &wait);
        iterate_bdevs(fdatawrite_one_bdev, NULL);
index 6211230814fd89dcc1a0a4b0acbabe000428e5b8..3eaf5c6622eb4fafc82137bc501aac803d7952f4 100644 (file)
@@ -27,6 +27,7 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
 {
        struct dentry *root;
        void *ns;
+       bool new_sb;
 
        if (!(flags & MS_KERNMOUNT)) {
                if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
@@ -37,8 +38,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        }
 
        ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
-       root = kernfs_mount_ns(fs_type, flags, sysfs_root, ns);
-       if (IS_ERR(root))
+       root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns);
+       if (IS_ERR(root) || !new_sb)
                kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
        return root;
 }
index c02a27a19c6df0984eb3ea13fc5a06c5e251aaa5..1037637957c7670e1a66e6bf1a8e51c80fbcc49d 100644 (file)
@@ -144,6 +144,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        size_t count = iocb->ki_nbytes;
        struct udf_inode_info *iinfo = UDF_I(inode);
 
+       mutex_lock(&inode->i_mutex);
        down_write(&iinfo->i_data_sem);
        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
                if (file->f_flags & O_APPEND)
@@ -156,6 +157,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                                pos + count)) {
                        err = udf_expand_file_adinicb(inode);
                        if (err) {
+                               mutex_unlock(&inode->i_mutex);
                                udf_debug("udf_expand_adinicb: err=%d\n", err);
                                return err;
                        }
@@ -169,9 +171,17 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        } else
                up_write(&iinfo->i_data_sem);
 
-       retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
-       if (retval > 0)
+       retval = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
+       mutex_unlock(&inode->i_mutex);
+
+       if (retval > 0) {
+               ssize_t err;
+
                mark_inode_dirty(inode);
+               err = generic_write_sync(file, iocb->ki_pos - retval, retval);
+               if (err < 0)
+                       retval = err;
+       }
 
        return retval;
 }
index 062b7925bca04c02949919ac37aab790d7b982a2..982ce05c87ed61c86dfc9200731a28f2db44b70b 100644 (file)
@@ -265,6 +265,7 @@ int udf_expand_file_adinicb(struct inode *inode)
                .nr_to_write = 1,
        };
 
+       WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
        if (!iinfo->i_lenAlloc) {
                if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
                        iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
index f35d5c953ff953dcde133c4b55568d1920db3589..9ddfb8190ca1cd56b5f1cd2247e9f54925fce68f 100644 (file)
@@ -705,7 +705,6 @@ xfs_setattr_size(
 {
        struct xfs_mount        *mp = ip->i_mount;
        struct inode            *inode = VFS_I(ip);
-       int                     mask = iattr->ia_valid;
        xfs_off_t               oldsize, newsize;
        struct xfs_trans        *tp;
        int                     error;
@@ -726,8 +725,8 @@ xfs_setattr_size(
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        ASSERT(S_ISREG(ip->i_d.di_mode));
-       ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
-                       ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+       ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+               ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
 
        oldsize = inode->i_size;
        newsize = iattr->ia_size;
@@ -736,7 +735,7 @@ xfs_setattr_size(
         * Short circuit the truncate case for zero length files.
         */
        if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
-               if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
+               if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
                        return 0;
 
                /*
@@ -824,10 +823,11 @@ xfs_setattr_size(
         * these flags set.  For all other operations the VFS set these flags
         * explicitly if it wants a timestamp update.
         */
-       if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+       if (newsize != oldsize &&
+           !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
                iattr->ia_ctime = iattr->ia_mtime =
                        current_fs_time(inode->i_sb);
-               mask |= ATTR_CTIME | ATTR_MTIME;
+               iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
        }
 
        /*
@@ -863,9 +863,9 @@ xfs_setattr_size(
                xfs_inode_clear_eofblocks_tag(ip);
        }
 
-       if (mask & ATTR_MODE)
+       if (iattr->ia_valid & ATTR_MODE)
                xfs_setattr_mode(ip, iattr);
-       if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+       if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
                xfs_setattr_time(ip, iattr);
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
index cdebd832c3dba1fcd937869d1cedcebe09113c25..4ef6fdbced78b7e99680f9e4e8afbb502a7bce92 100644 (file)
@@ -205,16 +205,25 @@ xlog_cil_insert_format_items(
                /*
                 * We 64-bit align the length of each iovec so that the start
                 * of the next one is naturally aligned.  We'll need to
-                * account for that slack space here.
+                * account for that slack space here. Then round nbytes up
+                * to 64-bit alignment so that the initial buffer alignment is
+                * easy to calculate and verify.
                 */
                nbytes += niovecs * sizeof(uint64_t);
+               nbytes = round_up(nbytes, sizeof(uint64_t));
 
                /* grab the old item if it exists for reservation accounting */
                old_lv = lip->li_lv;
 
-               /* calc buffer size */
-               buf_size = sizeof(struct xfs_log_vec) + nbytes +
-                               niovecs * sizeof(struct xfs_log_iovec);
+               /*
+                * The data buffer needs to start 64-bit aligned, so round up
+                * that space to ensure we can align it appropriately and not
+                * overrun the buffer.
+                */
+               buf_size = nbytes +
+                          round_up((sizeof(struct xfs_log_vec) +
+                                    niovecs * sizeof(struct xfs_log_iovec)),
+                                   sizeof(uint64_t));
 
                /* compare to existing item size */
                if (lip->li_lv && buf_size <= lip->li_lv->lv_size) {
@@ -251,6 +260,8 @@ xlog_cil_insert_format_items(
                /* The allocated data region lies beyond the iovec region */
                lv->lv_buf_len = 0;
                lv->lv_buf = (char *)lv + buf_size - nbytes;
+               ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t)));
+
                lip->li_ops->iop_format(lip, lv);
 insert:
                ASSERT(lv->lv_buf_len <= nbytes);
index 02df7b408a2623d6a32e7a2bc8285be9348ca646..f96c05669a9e06298980bd14e377e34536d0119b 100644 (file)
@@ -282,22 +282,29 @@ xfs_readsb(
        struct xfs_sb   *sbp = &mp->m_sb;
        int             error;
        int             loud = !(flags & XFS_MFSI_QUIET);
+       const struct xfs_buf_ops *buf_ops;
 
        ASSERT(mp->m_sb_bp == NULL);
        ASSERT(mp->m_ddev_targp != NULL);
 
+       /*
+        * For the initial read, we must guess at the sector
+        * size based on the block device.  It's enough to
+        * get the sb_sectsize out of the superblock and
+        * then reread with the proper length.
+        * We don't verify it yet, because it may not be complete.
+        */
+       sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
+       buf_ops = NULL;
+
        /*
         * Allocate a (locked) buffer to hold the superblock.
         * This will be kept around at all times to optimize
         * access to the superblock.
         */
-       sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
-
 reread:
        bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
-                                  BTOBB(sector_size), 0,
-                                  loud ? &xfs_sb_buf_ops
-                                       : &xfs_sb_quiet_buf_ops);
+                                  BTOBB(sector_size), 0, buf_ops);
        if (!bp) {
                if (loud)
                        xfs_warn(mp, "SB buffer read failed");
@@ -328,12 +335,13 @@ reread:
        }
 
        /*
-        * If device sector size is smaller than the superblock size,
-        * re-read the superblock so the buffer is correctly sized.
+        * Re-read the superblock so the buffer is correctly sized,
+        * and properly verified.
         */
-       if (sector_size < sbp->sb_sectsize) {
+       if (buf_ops == NULL) {
                xfs_buf_relse(bp);
                sector_size = sbp->sb_sectsize;
+               buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops;
                goto reread;
        }
 
index b7c9aea77f8fd2e7ca88537df77536eca8148418..1e116794bb6622d686487f36a461f8f644fd27c2 100644 (file)
@@ -295,8 +295,7 @@ xfs_mount_validate_sb(
            sbp->sb_dblocks == 0                                        ||
            sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)                      ||
            sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
-               XFS_CORRUPTION_ERROR("SB sanity check failed",
-                               XFS_ERRLEVEL_LOW, mp, sbp);
+               xfs_notice(mp, "SB sanity check failed");
                return XFS_ERROR(EFSCORRUPTED);
        }
 
@@ -611,10 +610,10 @@ xfs_sb_read_verify(
                                                XFS_SB_VERSION_5) ||
             dsb->sb_crc != 0)) {
 
-               if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize),
+               if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
                                      offsetof(struct xfs_sb, sb_crc))) {
                        /* Only fail bad secondaries on a known V5 filesystem */
-                       if (bp->b_bn != XFS_SB_DADDR &&
+                       if (bp->b_bn == XFS_SB_DADDR ||
                            xfs_sb_version_hascrc(&mp->m_sb)) {
                                error = EFSCORRUPTED;
                                goto out_error;
@@ -625,7 +624,7 @@ xfs_sb_read_verify(
 
 out_error:
        if (error) {
-               if (error != EWRONGFS)
+               if (error == EFSCORRUPTED)
                        XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
                                             mp, bp->b_addr);
                xfs_buf_ioerror(bp, error);
@@ -644,7 +643,6 @@ xfs_sb_quiet_read_verify(
 {
        struct xfs_dsb  *dsb = XFS_BUF_TO_SBP(bp);
 
-
        if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) {
                /* XFS filesystem, verify noisily! */
                xfs_sb_read_verify(bp);
index f317488263dd975eb85eb44d9746abfb974ef46f..d971f4932b5d8bb92d5efe645f372462abfbbe81 100644 (file)
@@ -913,7 +913,7 @@ xfs_flush_inodes(
        struct super_block      *sb = mp->m_super;
 
        if (down_read_trylock(&sb->s_umount)) {
-               sync_inodes_sb(sb, jiffies);
+               sync_inodes_sb(sb);
                up_read(&sb->s_umount);
        }
 }
index 8e4f41d9af4d47279e13a33edd317ce5de32e451..34c7bdc06014c0b5c787ec2faa85ab4d2b388096 100644 (file)
@@ -701,6 +701,18 @@ static inline pte_t pte_mknuma(pte_t pte)
 }
 #endif
 
+#ifndef ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pte_t *ptep)
+{
+       pte_t ptent = *ptep;
+
+       ptent = pte_mknuma(ptent);
+       set_pte_at(mm, addr, ptep, ptent);
+       return;
+}
+#endif
+
 #ifndef pmd_mknuma
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
@@ -708,6 +720,18 @@ static inline pmd_t pmd_mknuma(pmd_t pmd)
        return pmd_clear_flags(pmd, _PAGE_PRESENT);
 }
 #endif
+
+#ifndef pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pmd_t *pmdp)
+{
+       pmd_t pmd = *pmdp;
+
+       pmd = pmd_mknuma(pmd);
+       set_pmd_at(mm, addr, pmdp, pmd);
+       return;
+}
+#endif
 #else
 extern int pte_numa(pte_t pte);
 extern int pmd_numa(pmd_t pmd);
@@ -715,6 +739,8 @@ extern pte_t pte_mknonnuma(pte_t pte);
 extern pmd_t pmd_mknonnuma(pmd_t pmd);
 extern pte_t pte_mknuma(pte_t pte);
 extern pmd_t pmd_mknuma(pmd_t pmd);
+extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp);
 #endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
 #else
 static inline int pmd_numa(pmd_t pmd)
@@ -742,10 +768,23 @@ static inline pte_t pte_mknuma(pte_t pte)
        return pte;
 }
 
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pte_t *ptep)
+{
+       return;
+}
+
+
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
        return pmd;
 }
+
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pmd_t *pmdp)
+{
+       return ;
+}
 #endif /* CONFIG_NUMA_BALANCING */
 
 #endif /* CONFIG_MMU */
index 71727b6210ae57d5b064be1cab19a4dc660df6f8..8f3dee09757999c7c959e284250142c143d37d7d 100644 (file)
@@ -907,6 +907,9 @@ struct drm_mode_config {
 
        /* whether async page flip is supported or not */
        bool async_page_flip;
+
+       /* cursor size */
+       uint32_t cursor_width, cursor_height;
 };
 
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
index d1f61bfe0ebe49841cc5f249c8307b75973b98a7..49a828425fa2d984615b6352812681a455d7d99b 100644 (file)
@@ -29,6 +29,8 @@
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_memory.h>
 
+struct device;
+
 /**
  * Initialize pool allocator.
  */
index 2623cffc73a17b32cf9660bf67cf05bd9ae4b45f..25bfb0eff7720b459ffefa45ec035ec0229c8b1c 100644 (file)
@@ -373,8 +373,9 @@ extern const char *ceph_mds_op_name(int op);
 /*
  * Ceph setxattr request flags.
  */
-#define CEPH_XATTR_CREATE  1
-#define CEPH_XATTR_REPLACE 2
+#define CEPH_XATTR_CREATE  (1 << 0)
+#define CEPH_XATTR_REPLACE (1 << 1)
+#define CEPH_XATTR_REMOVE  (1 << 31)
 
 union ceph_mds_request_args {
        struct {
index 5c097596104b80535a0a00bdd45b4a2441fac889..9450f025fe0c01ac52bf78caccf114c30312a2e4 100644 (file)
@@ -166,6 +166,8 @@ struct cgroup {
         *
         * The ID of the root cgroup is always 0, and a new cgroup
         * will be assigned with a smallest available ID.
+        *
+        * Allocating/Removing ID must be protected by cgroup_mutex.
         */
        int id;
 
index dfac5ed311205d2469628273b161e4008fcfcbfb..f886985a28b2d5c0db1f1a798817eb167d2cb23c 100644 (file)
@@ -171,7 +171,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
                               size_t size, int flags, const char *);
 
 #define dma_buf_export(priv, ops, size, flags) \
-       dma_buf_export_named(priv, ops, size, flags, __FILE__)
+       dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME)
 
 int dma_buf_fd(struct dma_buf *dmabuf, int flags);
 struct dma_buf *dma_buf_get(int fd);
index 3d286ff49ab0c82309ec3499bf27cc77f75f3670..64cf3ef50696c7bf50b3c3a3e211cfa9d3accb0d 100644 (file)
@@ -99,7 +99,7 @@ struct fsnotify_ops {
                            struct fsnotify_mark *inode_mark,
                            struct fsnotify_mark *vfsmount_mark,
                            u32 mask, void *data, int data_type,
-                           const unsigned char *file_name);
+                           const unsigned char *file_name, u32 cookie);
        void (*free_group_priv)(struct fsnotify_group *group);
        void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
        void (*free_event)(struct fsnotify_event *event);
@@ -160,7 +160,7 @@ struct fsnotify_group {
 
        struct fasync_struct *fsn_fa;    /* async notification */
 
-       struct fsnotify_event overflow_event;   /* Event we queue when the
+       struct fsnotify_event *overflow_event;  /* Event we queue when the
                                                 * notification list is too
                                                 * full */
 
index e7831d20373776f5c3dc80c5a04147e8aa611c85..35e7eca4e33b1fbbde3029b5f3cb2be350d0dafc 100644 (file)
@@ -118,9 +118,7 @@ extern int mq_init_ns(struct ipc_namespace *ns);
  *     the new maximum will handle anyone else.  I may have to revisit this
  *     in the future.
  */
-#define MIN_QUEUESMAX                  1
 #define DFLT_QUEUESMAX               256
-#define HARD_QUEUESMAX              1024
 #define MIN_MSGMAX                     1
 #define DFLT_MSG                      10U
 #define DFLT_MSGMAX                   10
index 5be9f0228a3bbc8ddfad7a2fc245f6601cfc1f17..d267623c28cfdaa385ab5f288683c0157f9e8ef4 100644 (file)
@@ -249,7 +249,8 @@ void kernfs_notify(struct kernfs_node *kn);
 
 const void *kernfs_super_ns(struct super_block *sb);
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-                              struct kernfs_root *root, const void *ns);
+                              struct kernfs_root *root, bool *new_sb_created,
+                              const void *ns);
 void kernfs_kill_sb(struct super_block *sb);
 
 void kernfs_init(void);
@@ -317,7 +318,7 @@ static inline const void *kernfs_super_ns(struct super_block *sb)
 
 static inline struct dentry *
 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-               struct kernfs_root *root, const void *ns)
+               struct kernfs_root *root, bool *new_sb_created, const void *ns)
 { return ERR_PTR(-ENOSYS); }
 
 static inline void kernfs_kill_sb(struct super_block *sb) { }
@@ -368,9 +369,9 @@ static inline int kernfs_remove_by_name(struct kernfs_node *parent,
 
 static inline struct dentry *
 kernfs_mount(struct file_system_type *fs_type, int flags,
-            struct kernfs_root *root)
+            struct kernfs_root *root, bool *new_sb_created)
 {
-       return kernfs_mount_ns(fs_type, flags, root, NULL);
+       return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL);
 }
 
 #endif /* __LINUX_KERNFS_H */
index ad1ae7f345ad9482df4a47c0ddc4ab11bd34e2ec..78c76cd4d37bdff2d1c56e2a9c1c199af6b7a77d 100644 (file)
@@ -387,7 +387,7 @@ struct max8997_dev {
        struct i2c_client *muic; /* slave addr 0x4a */
        struct mutex iolock;
 
-       int type;
+       unsigned long type;
        struct platform_device *battery; /* battery control (not fuel gauge) */
 
        int irq;
index 4ecb24b4b863be4158263466ce919e78b42714d5..d68ada502ff37c1e08164f723db8ef3e33d96a50 100644 (file)
@@ -163,7 +163,7 @@ struct max8998_dev {
        int ono;
        u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS];
        u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS];
-       int type;
+       unsigned long type;
        bool wakeup;
 };
 
index a5a7f0130e9604837982d4b2f3bb9920fd5d090c..54b5458ec084a50ec06cc9f418d4e623e0aaf7bc 100644 (file)
@@ -252,7 +252,7 @@ struct tps65217_board {
 struct tps65217 {
        struct device *dev;
        struct tps65217_board *pdata;
-       unsigned int id;
+       unsigned long id;
        struct regulator_desc desc[TPS65217_NUM_REGULATOR];
        struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
        struct regmap *regmap;
@@ -263,7 +263,7 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev)
        return dev_get_drvdata(dev);
 }
 
-static inline int tps65217_chip_id(struct tps65217 *tps65217)
+static inline unsigned long tps65217_chip_id(struct tps65217 *tps65217)
 {
        return tps65217->id;
 }
index 440a02ee6f92cda68d3438ab88af3896d7c41af2..e8eeebd49a98279837bb6e30afa82f3645465452 100644 (file)
@@ -752,6 +752,9 @@ struct netdev_phys_port_id {
        unsigned char id_len;
 };
 
+typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
+                                      struct sk_buff *skb);
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -783,7 +786,7 @@ struct netdev_phys_port_id {
  *     Required can not be NULL.
  *
  * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
- *                         void *accel_priv);
+ *                         void *accel_priv, select_queue_fallback_t fallback);
  *     Called to decide which queue to when device supports multiple
  *     transmit queues.
  *
@@ -1005,7 +1008,8 @@ struct net_device_ops {
                                                   struct net_device *dev);
        u16                     (*ndo_select_queue)(struct net_device *dev,
                                                    struct sk_buff *skb,
-                                                   void *accel_priv);
+                                                   void *accel_priv,
+                                                   select_queue_fallback_t fallback);
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
@@ -1551,7 +1555,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
                                    struct sk_buff *skb,
                                    void *accel_priv);
-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
  * Net namespace inlines
@@ -2275,6 +2278,26 @@ static inline void netdev_reset_queue(struct net_device *dev_queue)
        netdev_tx_reset_queue(netdev_get_tx_queue(dev_queue, 0));
 }
 
+/**
+ *     netdev_cap_txqueue - check if selected tx queue exceeds device queues
+ *     @dev: network device
+ *     @queue_index: given tx queue index
+ *
+ *     Returns 0 if given tx queue index >= number of device tx queues,
+ *     otherwise returns the originally passed tx queue index.
+ */
+static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)
+{
+       if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+               net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
+                                    dev->name, queue_index,
+                                    dev->real_num_tx_queues);
+               return 0;
+       }
+
+       return queue_index;
+}
+
 /**
  *     netif_running - test if up
  *     @dev: network device
@@ -3068,7 +3091,12 @@ void netdev_change_features(struct net_device *dev);
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
                                        struct net_device *dev);
 
-netdev_features_t netif_skb_features(struct sk_buff *skb);
+netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+                                        const struct net_device *dev);
+static inline netdev_features_t netif_skb_features(struct sk_buff *skb)
+{
+       return netif_skb_dev_features(skb, skb->dev);
+}
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
index fb57c892b214d6b3482c63a28061130f3a700a9c..33aa2caf0f0c9e5bd9e7cf07c8d92b08207be959 100644 (file)
@@ -1169,8 +1169,23 @@ void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 void pci_restore_msi_state(struct pci_dev *dev);
 int pci_msi_enabled(void);
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);
+static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+{
+       int rc = pci_enable_msi_range(dev, nvec, nvec);
+       if (rc < 0)
+               return rc;
+       return 0;
+}
 int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
                          int minvec, int maxvec);
+static inline int pci_enable_msix_exact(struct pci_dev *dev,
+                                       struct msix_entry *entries, int nvec)
+{
+       int rc = pci_enable_msix_range(dev, entries, nvec, nvec);
+       if (rc < 0)
+               return rc;
+       return 0;
+}
 #else
 static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
 static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
@@ -1189,9 +1204,14 @@ static inline int pci_msi_enabled(void) { return 0; }
 static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec,
                                       int maxvec)
 { return -ENOSYS; }
+static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+{ return -ENOSYS; }
 static inline int pci_enable_msix_range(struct pci_dev *dev,
                      struct msix_entry *entries, int minvec, int maxvec)
 { return -ENOSYS; }
+static inline int pci_enable_msix_exact(struct pci_dev *dev,
+                     struct msix_entry *entries, int nvec)
+{ return -ENOSYS; }
 #endif
 
 #ifdef CONFIG_PCIEPORTBUS
index f589c9af8cbf1250da1945bac436f27d92987e80..3ebbbe7b6d05fadbccaf66bac9ad1d8cfe7c5c17 100644 (file)
@@ -2916,5 +2916,22 @@ static inline bool skb_head_is_locked(const struct sk_buff *skb)
 {
        return !skb->head_frag || skb_cloned(skb);
 }
+
+/**
+ * skb_gso_network_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_network_seglen is used to determine the real size of the
+ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
+ *
+ * The MAC/L2 header is not accounted for.
+ */
+static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
+{
+       unsigned int hdr_len = skb_transport_header(skb) -
+                              skb_network_header(skb);
+       return hdr_len + skb_gso_transport_seglen(skb);
+}
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */
index 40ed9e9a77e53c77448104a921c0595f2a7927eb..a747a77ea584aafb124ae230862360c8dd0b6073 100644 (file)
@@ -281,13 +281,15 @@ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
 asmlinkage long sys_sched_setparam(pid_t pid,
                                        struct sched_param __user *param);
 asmlinkage long sys_sched_setattr(pid_t pid,
-                                       struct sched_attr __user *attr);
+                                       struct sched_attr __user *attr,
+                                       unsigned int flags);
 asmlinkage long sys_sched_getscheduler(pid_t pid);
 asmlinkage long sys_sched_getparam(pid_t pid,
                                        struct sched_param __user *param);
 asmlinkage long sys_sched_getattr(pid_t pid,
                                        struct sched_attr __user *attr,
-                                       unsigned int size);
+                                       unsigned int size,
+                                       unsigned int flags);
 asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
                                        unsigned long __user *user_mask_ptr);
 asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
index 594521ba0d43f73e887375968006429c9ec19502..704f4f652d0af8b28406154678ee38b5f98298bf 100644 (file)
@@ -419,10 +419,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
        static struct lock_class_key __key;                             \
        const char *__lock_name;                                        \
                                                                        \
-       if (__builtin_constant_p(fmt))                                  \
-               __lock_name = (fmt);                                    \
-       else                                                            \
-               __lock_name = #fmt;                                     \
+       __lock_name = #fmt#args;                                        \
                                                                        \
        __alloc_workqueue_key((fmt), (flags), (max_active),             \
                              &__key, __lock_name, ##args);             \
index fc0e4320aa6d50d0e5f966e3f8b649506d461ac7..021b8a319b9e2cf7f0f60a5f6fedcfe3367f8016 100644 (file)
@@ -97,7 +97,7 @@ void writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
 int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason);
 int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
                                  enum wb_reason reason);
-void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this);
+void sync_inodes_sb(struct super_block *);
 void wakeup_flusher_threads(long nr_pages, enum wb_reason reason);
 void inode_wait_for_writeback(struct inode *inode);
 
index d992ca3145fec9826c1df1cf0affc95272a6af25..6ee76c804893fc9f291a469550b2356fe1b93c39 100644 (file)
@@ -1653,17 +1653,6 @@ struct sctp_association {
        /* This is the last advertised value of rwnd over a SACK chunk. */
        __u32 a_rwnd;
 
-       /* Number of bytes by which the rwnd has slopped.  The rwnd is allowed
-        * to slop over a maximum of the association's frag_point.
-        */
-       __u32 rwnd_over;
-
-       /* Keeps treack of rwnd pressure.  This happens when we have
-        * a window, but not recevie buffer (i.e small packets).  This one
-        * is releases slowly (1 PMTU at a time ).
-        */
-       __u32 rwnd_press;
-
        /* This is the sndbuf size in use for the association.
         * This corresponds to the sndbuf size for the association,
         * as specified in the sk->sndbuf.
@@ -1892,8 +1881,7 @@ void sctp_assoc_update(struct sctp_association *old,
 __u32 sctp_association_get_next_tsn(struct sctp_association *);
 
 void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *);
-void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
-void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
+void sctp_assoc_rwnd_update(struct sctp_association *, bool);
 void sctp_assoc_set_primary(struct sctp_association *,
                            struct sctp_transport *);
 void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
index 68d92e36facda52f6e4b249e108bd43c8847e92e..6e89ef6c11c1a42c853a8f87021bbf1244a14ffc 100644 (file)
@@ -449,14 +449,22 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
 /* dapm audio pin control and status */
 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm,
                            const char *pin);
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                    const char *pin);
 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
                             const char *pin);
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                     const char *pin);
 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin);
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                const char *pin);
 int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
                                const char *pin);
 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
 int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
                                  const char *pin);
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                          const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
                                const char *pin);
 void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
index c7bbbe794e65cdd0a41c7235bcee6e9718970876..464ea82e10dbf1f1a519b75c52f9e129a5a715e0 100644 (file)
@@ -287,11 +287,11 @@ TRACE_EVENT(writeback_queue_io,
                __field(int,            reason)
        ),
        TP_fast_assign(
-               unsigned long older_than_this = work->older_than_this;
+               unsigned long *older_than_this = work->older_than_this;
                strncpy(__entry->name, dev_name(wb->bdi->dev), 32);
-               __entry->older  = older_than_this;
+               __entry->older  = older_than_this ?  *older_than_this : 0;
                __entry->age    = older_than_this ?
-                                 (jiffies - older_than_this) * 1000 / HZ : -1;
+                                 (jiffies - *older_than_this) * 1000 / HZ : -1;
                __entry->moved  = moved;
                __entry->reason = work->reason;
        ),
index a20a9b4d38713f5a92982457f0e8f330b0bfd58c..dde8041f40d2e8a29a25a6205dd38577f2b46bce 100644 (file)
@@ -692,9 +692,13 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
 __SYSCALL(__NR_kcmp, sys_kcmp)
 #define __NR_finit_module 273
 __SYSCALL(__NR_finit_module, sys_finit_module)
+#define __NR_sched_setattr 274
+__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+#define __NR_sched_getattr 275
+__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
 
 #undef __NR_syscalls
-#define __NR_syscalls 274
+#define __NR_syscalls 276
 
 /*
  * All syscalls below here should go away really,
index 3c9a833992e872f095a4373d6cb5e33602129acc..b06c8ed687079759ea7e585589aac199ac288e22 100644 (file)
@@ -619,6 +619,8 @@ struct drm_gem_open {
 #define  DRM_PRIME_CAP_EXPORT          0x2
 #define DRM_CAP_TIMESTAMP_MONOTONIC    0x6
 #define DRM_CAP_ASYNC_PAGE_FLIP                0x7
+#define DRM_CAP_CURSOR_WIDTH           0x8
+#define DRM_CAP_CURSOR_HEIGHT          0x9
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
index 9971c560ed9aa42dc841e76b9586f05e25225d96..87792a5fee3bad7d143de81555a56ede7e532f1a 100644 (file)
@@ -87,6 +87,7 @@
 #define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
 #define DRM_VMW_PARAM_3D_CAPS_SIZE     8
 #define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
+#define DRM_VMW_PARAM_MAX_MOB_SIZE     10
 
 /**
  * struct drm_vmw_getparam_arg
index 383d638340b8417c8e31f53b935f8e8d833b2707..5bb8bfe671496e55b6c62df1d28922454a2a2dcf 100644 (file)
@@ -22,6 +22,16 @@ static void *get_mq(ctl_table *table)
        return which;
 }
 
+static int proc_mq_dointvec(ctl_table *table, int write,
+                           void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table mq_table;
+       memcpy(&mq_table, table, sizeof(mq_table));
+       mq_table.data = get_mq(table);
+
+       return proc_dointvec(&mq_table, write, buffer, lenp, ppos);
+}
+
 static int proc_mq_dointvec_minmax(ctl_table *table, int write,
        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -33,12 +43,10 @@ static int proc_mq_dointvec_minmax(ctl_table *table, int write,
                                        lenp, ppos);
 }
 #else
+#define proc_mq_dointvec NULL
 #define proc_mq_dointvec_minmax NULL
 #endif
 
-static int msg_queues_limit_min = MIN_QUEUESMAX;
-static int msg_queues_limit_max = HARD_QUEUESMAX;
-
 static int msg_max_limit_min = MIN_MSGMAX;
 static int msg_max_limit_max = HARD_MSGMAX;
 
@@ -51,9 +59,7 @@ static ctl_table mq_sysctls[] = {
                .data           = &init_ipc_ns.mq_queues_max,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_mq_dointvec_minmax,
-               .extra1         = &msg_queues_limit_min,
-               .extra2         = &msg_queues_limit_max,
+               .proc_handler   = proc_mq_dointvec,
        },
        {
                .procname       = "msg_max",
index ccf1f9fd263acdfae7dc56a87bceddd3170f69d9..c3b31179122c326342597d40cd58db11d51da940 100644 (file)
@@ -433,9 +433,9 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
                error = -EACCES;
                goto out_unlock;
        }
-       if (ipc_ns->mq_queues_count >= HARD_QUEUESMAX ||
-           (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
-            !capable(CAP_SYS_RESOURCE))) {
+
+       if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
+           !capable(CAP_SYS_RESOURCE)) {
                error = -ENOSPC;
                goto out_unlock;
        }
index 67ccf0e7cca92412f457175d5ff3e784b254966a..135944a7b28ab901a400d06fd583d831ac8167b9 100644 (file)
@@ -916,7 +916,7 @@ static int audit_tree_handle_event(struct fsnotify_group *group,
                                   struct fsnotify_mark *inode_mark,
                                   struct fsnotify_mark *vfsmount_mark,
                                   u32 mask, void *data, int data_type,
-                                  const unsigned char *file_name)
+                                  const unsigned char *file_name, u32 cookie)
 {
        return 0;
 }
index 2596fac5dcb4552a0d574decada597424df0587b..70b4554d2fbe093e4f83a045ed84705c7a9cffe0 100644 (file)
@@ -471,7 +471,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
                                    struct fsnotify_mark *inode_mark,
                                    struct fsnotify_mark *vfsmount_mark,
                                    u32 mask, void *data, int data_type,
-                                   const unsigned char *dname)
+                                   const unsigned char *dname, u32 cookie)
 {
        struct inode *inode;
        struct audit_parent *parent;
index e2f46ba37f7243c4278de77a8c8536ddc4c0aad5..105f273b6f86a74984d2b62b7d3ba19f95369a78 100644 (file)
@@ -886,7 +886,9 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                 * per-subsystem and moved to css->id so that lookups are
                 * successful until the target css is released.
                 */
+               mutex_lock(&cgroup_mutex);
                idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+               mutex_unlock(&cgroup_mutex);
                cgrp->id = -1;
 
                call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
@@ -1566,10 +1568,10 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
                mutex_lock(&cgroup_mutex);
                mutex_lock(&cgroup_root_mutex);
 
-               root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp,
-                                          0, 1, GFP_KERNEL);
-               if (root_cgrp->id < 0)
+               ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL);
+               if (ret < 0)
                        goto unlock_drop;
+               root_cgrp->id = ret;
 
                /* Check for name clashes with existing mounts */
                ret = -EBUSY;
@@ -2763,10 +2765,7 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
         */
        update_before = cgroup_serial_nr_next;
 
-       mutex_unlock(&cgroup_mutex);
-
        /* add/rm files for all cgroups created before */
-       rcu_read_lock();
        css_for_each_descendant_pre(css, cgroup_css(root, ss)) {
                struct cgroup *cgrp = css->cgroup;
 
@@ -2775,23 +2774,19 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
 
                inode = cgrp->dentry->d_inode;
                dget(cgrp->dentry);
-               rcu_read_unlock();
-
                dput(prev);
                prev = cgrp->dentry;
 
+               mutex_unlock(&cgroup_mutex);
                mutex_lock(&inode->i_mutex);
                mutex_lock(&cgroup_mutex);
                if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
                        ret = cgroup_addrm_files(cgrp, cfts, is_add);
-               mutex_unlock(&cgroup_mutex);
                mutex_unlock(&inode->i_mutex);
-
-               rcu_read_lock();
                if (ret)
                        break;
        }
-       rcu_read_unlock();
+       mutex_unlock(&cgroup_mutex);
        dput(prev);
        deactivate_super(sb);
        return ret;
@@ -2910,9 +2905,14 @@ static void cgroup_enable_task_cg_lists(void)
                 * We should check if the process is exiting, otherwise
                 * it will race with cgroup_exit() in that the list
                 * entry won't be deleted though the process has exited.
+                * Do it while holding siglock so that we don't end up
+                * racing against cgroup_exit().
                 */
+               spin_lock_irq(&p->sighand->siglock);
                if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
                        list_add(&p->cg_list, &task_css_set(p)->tasks);
+               spin_unlock_irq(&p->sighand->siglock);
+
                task_unlock(p);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
@@ -4158,7 +4158,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        struct cgroup *cgrp;
        struct cgroup_name *name;
        struct cgroupfs_root *root = parent->root;
-       int ssid, err = 0;
+       int ssid, err;
        struct cgroup_subsys *ss;
        struct super_block *sb = root->sb;
 
@@ -4168,18 +4168,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                return -ENOMEM;
 
        name = cgroup_alloc_name(dentry);
-       if (!name)
+       if (!name) {
+               err = -ENOMEM;
                goto err_free_cgrp;
+       }
        rcu_assign_pointer(cgrp->name, name);
 
-       /*
-        * Temporarily set the pointer to NULL, so idr_find() won't return
-        * a half-baked cgroup.
-        */
-       cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
-       if (cgrp->id < 0)
-               goto err_free_name;
-
        /*
         * Only live parents can have children.  Note that the liveliness
         * check isn't strictly necessary because cgroup_mkdir() and
@@ -4189,7 +4183,17 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
         */
        if (!cgroup_lock_live_group(parent)) {
                err = -ENODEV;
-               goto err_free_id;
+               goto err_free_name;
+       }
+
+       /*
+        * Temporarily set the pointer to NULL, so idr_find() won't return
+        * a half-baked cgroup.
+        */
+       cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
+       if (cgrp->id < 0) {
+               err = -ENOMEM;
+               goto err_unlock;
        }
 
        /* Grab a reference on the superblock so the hierarchy doesn't
@@ -4221,7 +4225,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
         */
        err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
        if (err < 0)
-               goto err_unlock;
+               goto err_free_id;
        lockdep_assert_held(&dentry->d_inode->i_mutex);
 
        cgrp->serial_nr = cgroup_serial_nr_next++;
@@ -4257,12 +4261,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 
        return 0;
 
-err_unlock:
-       mutex_unlock(&cgroup_mutex);
-       /* Release the reference count that we took on the superblock */
-       deactivate_super(sb);
 err_free_id:
        idr_remove(&root->cgroup_idr, cgrp->id);
+       /* Release the reference count that we took on the superblock */
+       deactivate_super(sb);
+err_unlock:
+       mutex_unlock(&cgroup_mutex);
 err_free_name:
        kfree(rcu_dereference_raw(cgrp->name));
 err_free_cgrp:
index 56003c6edfd38c03e8dd523f1efb01d99bcf2e84..fa0b2d4ad83c5f7a08dfecf27d16d33d928a80f2 100644 (file)
@@ -7856,14 +7856,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu)
 static void __perf_event_exit_context(void *__info)
 {
        struct perf_event_context *ctx = __info;
-       struct perf_event *event, *tmp;
+       struct perf_event *event;
 
        perf_pmu_rotate_stop(ctx->pmu);
 
-       list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
-               __perf_remove_from_context(event);
-       list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
+       rcu_read_lock();
+       list_for_each_entry_rcu(event, &ctx->event_list, event_entry)
                __perf_remove_from_context(event);
+       rcu_read_unlock();
 }
 
 static void perf_event_exit_cpu_context(int cpu)
@@ -7887,11 +7887,11 @@ static void perf_event_exit_cpu(int cpu)
 {
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
+       perf_event_exit_cpu_context(cpu);
+
        mutex_lock(&swhash->hlist_mutex);
        swevent_hlist_release(swhash);
        mutex_unlock(&swhash->hlist_mutex);
-
-       perf_event_exit_cpu_context(cpu);
 }
 #else
 static inline void perf_event_exit_cpu(int cpu) { }
index eacb8bd8cab4e1205230ecfdde12483be9846cf7..aba9c545a0e3940481f3b5ce54221906edb760e2 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kbd_kern.h>
 #include <linux/vt.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "power.h"
 
 #define SUSPEND_CONSOLE        (MAX_NR_CONSOLES-1)
index b1d255f041351779dacb5341dbcb0c0c4a09fb87..4dae9cbe9259f6a80712589370a39c705132f631 100644 (file)
@@ -1076,7 +1076,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                next_seq = log_next_seq;
 
                len = 0;
-               prev = 0;
                while (len >= 0 && seq < next_seq) {
                        struct printk_log *msg = log_from_idx(idx);
                        int textlen;
@@ -2788,7 +2787,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        next_idx = idx;
 
        l = 0;
-       prev = 0;
        while (seq < dumper->next_seq) {
                struct printk_log *msg = log_from_idx(idx);
 
index b46131ef6aab0ac48149482a03f8354330adf188..6edbef296ece25a6ee68facac279445414692368 100644 (file)
@@ -1952,7 +1952,7 @@ static int dl_overflow(struct task_struct *p, int policy,
 {
 
        struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
-       u64 period = attr->sched_period;
+       u64 period = attr->sched_period ?: attr->sched_deadline;
        u64 runtime = attr->sched_runtime;
        u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
        int cpus, err = -1;
@@ -3661,13 +3661,14 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
  * @pid: the pid in question.
  * @uattr: structure containing the extended parameters.
  */
-SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr)
+SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
+                              unsigned int, flags)
 {
        struct sched_attr attr;
        struct task_struct *p;
        int retval;
 
-       if (!uattr || pid < 0)
+       if (!uattr || pid < 0 || flags)
                return -EINVAL;
 
        if (sched_copy_attr(uattr, &attr))
@@ -3786,7 +3787,7 @@ static int sched_read_attr(struct sched_attr __user *uattr,
                attr->size = usize;
        }
 
-       ret = copy_to_user(uattr, attr, usize);
+       ret = copy_to_user(uattr, attr, attr->size);
        if (ret)
                return -EFAULT;
 
@@ -3804,8 +3805,8 @@ err_size:
  * @uattr: structure containing the extended parameters.
  * @size: sizeof(attr) for fwd/bwd comp.
  */
-SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
-               unsigned int, size)
+SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
+               unsigned int, size, unsigned int, flags)
 {
        struct sched_attr attr = {
                .size = sizeof(struct sched_attr),
@@ -3814,7 +3815,7 @@ SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
        int retval;
 
        if (!uattr || pid < 0 || size > PAGE_SIZE ||
-           size < SCHED_ATTR_SIZE_VER0)
+           size < SCHED_ATTR_SIZE_VER0 || flags)
                return -EINVAL;
 
        rcu_read_lock();
@@ -7422,6 +7423,7 @@ static int sched_dl_global_constraints(void)
        u64 period = global_rt_period();
        u64 new_bw = to_ratio(period, runtime);
        int cpu, ret = 0;
+       unsigned long flags;
 
        /*
         * Here we want to check the bandwidth not being set to some
@@ -7435,10 +7437,10 @@ static int sched_dl_global_constraints(void)
        for_each_possible_cpu(cpu) {
                struct dl_bw *dl_b = dl_bw_of(cpu);
 
-               raw_spin_lock(&dl_b->lock);
+               raw_spin_lock_irqsave(&dl_b->lock, flags);
                if (new_bw < dl_b->total_bw)
                        ret = -EBUSY;
-               raw_spin_unlock(&dl_b->lock);
+               raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
                if (ret)
                        break;
@@ -7451,6 +7453,7 @@ static void sched_dl_do_global(void)
 {
        u64 new_bw = -1;
        int cpu;
+       unsigned long flags;
 
        def_dl_bandwidth.dl_period = global_rt_period();
        def_dl_bandwidth.dl_runtime = global_rt_runtime();
@@ -7464,9 +7467,9 @@ static void sched_dl_do_global(void)
        for_each_possible_cpu(cpu) {
                struct dl_bw *dl_b = dl_bw_of(cpu);
 
-               raw_spin_lock(&dl_b->lock);
+               raw_spin_lock_irqsave(&dl_b->lock, flags);
                dl_b->bw = new_bw;
-               raw_spin_unlock(&dl_b->lock);
+               raw_spin_unlock_irqrestore(&dl_b->lock, flags);
        }
 }
 
@@ -7475,7 +7478,8 @@ static int sched_rt_global_validate(void)
        if (sysctl_sched_rt_period <= 0)
                return -EINVAL;
 
-       if (sysctl_sched_rt_runtime > sysctl_sched_rt_period)
+       if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
+               (sysctl_sched_rt_runtime > sysctl_sched_rt_period))
                return -EINVAL;
 
        return 0;
index 045fc74e3f0928fd73e1924b5b678f7d56654613..5b8838b56d1c8dee47354f3a1a697263678d00ea 100644 (file)
@@ -70,7 +70,7 @@ static void cpudl_heapify(struct cpudl *cp, int idx)
 
 static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl)
 {
-       WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID);
+       WARN_ON(!cpu_present(idx) || idx == IDX_INVALID);
 
        if (dl_time_before(new_dl, cp->elements[idx].dl)) {
                cp->elements[idx].dl = new_dl;
@@ -117,7 +117,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
        }
 
 out:
-       WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1);
+       WARN_ON(!cpu_present(best_cpu) && best_cpu != -1);
 
        return best_cpu;
 }
@@ -137,7 +137,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid)
        int old_idx, new_cpu;
        unsigned long flags;
 
-       WARN_ON(cpu > num_present_cpus());
+       WARN_ON(!cpu_present(cpu));
 
        raw_spin_lock_irqsave(&cp->lock, flags);
        old_idx = cp->cpu_to_idx[cpu];
index 0dd5e0971a0778a3e09ee8a91f5851dfa1dc25a9..15cbc17fbf84d57ac52aa9b752d9552a4b4335ee 100644 (file)
@@ -121,7 +121,7 @@ static inline void dl_clear_overload(struct rq *rq)
 
 static void update_dl_migration(struct dl_rq *dl_rq)
 {
-       if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_total > 1) {
+       if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_running > 1) {
                if (!dl_rq->overloaded) {
                        dl_set_overload(rq_of_dl_rq(dl_rq));
                        dl_rq->overloaded = 1;
@@ -137,7 +137,6 @@ static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
        struct task_struct *p = dl_task_of(dl_se);
        dl_rq = &rq_of_dl_rq(dl_rq)->dl;
 
-       dl_rq->dl_nr_total++;
        if (p->nr_cpus_allowed > 1)
                dl_rq->dl_nr_migratory++;
 
@@ -149,7 +148,6 @@ static void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
        struct task_struct *p = dl_task_of(dl_se);
        dl_rq = &rq_of_dl_rq(dl_rq)->dl;
 
-       dl_rq->dl_nr_total--;
        if (p->nr_cpus_allowed > 1)
                dl_rq->dl_nr_migratory--;
 
@@ -717,6 +715,7 @@ void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
 
        WARN_ON(!dl_prio(prio));
        dl_rq->dl_nr_running++;
+       inc_nr_running(rq_of_dl_rq(dl_rq));
 
        inc_dl_deadline(dl_rq, deadline);
        inc_dl_migration(dl_se, dl_rq);
@@ -730,6 +729,7 @@ void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
        WARN_ON(!dl_prio(prio));
        WARN_ON(!dl_rq->dl_nr_running);
        dl_rq->dl_nr_running--;
+       dec_nr_running(rq_of_dl_rq(dl_rq));
 
        dec_dl_deadline(dl_rq, dl_se->deadline);
        dec_dl_migration(dl_se, dl_rq);
@@ -836,8 +836,6 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
 
        if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
                enqueue_pushable_dl_task(rq, p);
-
-       inc_nr_running(rq);
 }
 
 static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
@@ -850,8 +848,6 @@ static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
 {
        update_curr_dl(rq);
        __dequeue_task_dl(rq, p, flags);
-
-       dec_nr_running(rq);
 }
 
 /*
index 966cc2bfcb77586d2ce9c55986aae2a3f2dce521..78157099b167c64f034c8c3348c02eaeb41c888a 100644 (file)
@@ -1757,6 +1757,8 @@ void task_numa_work(struct callback_head *work)
                        start = end;
                        if (pages <= 0)
                                goto out;
+
+                       cond_resched();
                } while (end != vma->vm_end);
        }
 
index c2119fd20f8b6dc2042a80603d44223ab9365dec..f964add50f3863805f725e8fc13b447806f41022 100644 (file)
@@ -462,7 +462,6 @@ struct dl_rq {
        } earliest_dl;
 
        unsigned long dl_nr_migratory;
-       unsigned long dl_nr_total;
        int overloaded;
 
        /*
index 0abb364642818e4ef842ab2f3631d15cb80400f2..4d23dc4d8139988e13946ee48d37a76333c916c0 100644 (file)
@@ -116,20 +116,42 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
 void __init sched_clock_register(u64 (*read)(void), int bits,
                                 unsigned long rate)
 {
+       u64 res, wrap, new_mask, new_epoch, cyc, ns;
+       u32 new_mult, new_shift;
+       ktime_t new_wrap_kt;
        unsigned long r;
-       u64 res, wrap;
        char r_unit;
 
        if (cd.rate > rate)
                return;
 
        WARN_ON(!irqs_disabled());
-       read_sched_clock = read;
-       sched_clock_mask = CLOCKSOURCE_MASK(bits);
-       cd.rate = rate;
 
        /* calculate the mult/shift to convert counter ticks to ns. */
-       clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
+       clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
+
+       new_mask = CLOCKSOURCE_MASK(bits);
+
+       /* calculate how many ns until we wrap */
+       wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask);
+       new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
+
+       /* update epoch for new counter and update epoch_ns from old counter*/
+       new_epoch = read();
+       cyc = read_sched_clock();
+       ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
+                         cd.mult, cd.shift);
+
+       raw_write_seqcount_begin(&cd.seq);
+       read_sched_clock = read;
+       sched_clock_mask = new_mask;
+       cd.rate = rate;
+       cd.wrap_kt = new_wrap_kt;
+       cd.mult = new_mult;
+       cd.shift = new_shift;
+       cd.epoch_cyc = new_epoch;
+       cd.epoch_ns = ns;
+       raw_write_seqcount_end(&cd.seq);
 
        r = rate;
        if (r >= 4000000) {
@@ -141,22 +163,12 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
        } else
                r_unit = ' ';
 
-       /* calculate how many ns until we wrap */
-       wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
-       cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
-
        /* calculate the ns resolution of this counter */
-       res = cyc_to_ns(1ULL, cd.mult, cd.shift);
+       res = cyc_to_ns(1ULL, new_mult, new_shift);
+
        pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
                bits, r, r_unit, res, wrap);
 
-       update_sched_clock();
-
-       /*
-        * Ensure that sched_clock() starts off at 0ns
-        */
-       cd.epoch_ns = 0;
-
        /* Enable IRQ time accounting if we have a fast enough sched_clock */
        if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
                enable_sched_clock_irqtime();
index 240fb62cf3945aa0f7b601b343db65312a42f345..dd06439b9c84fe80463121905339c41493710998 100644 (file)
@@ -225,7 +225,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id)
  *
  *     When there is no mapping defined for the user-namespace uid
  *     pair INVALID_UID is returned.  Callers are expected to test
- *     for and handle handle INVALID_UID being returned.  INVALID_UID
+ *     for and handle INVALID_UID being returned.  INVALID_UID
  *     may be tested for using uid_valid().
  */
 kuid_t make_kuid(struct user_namespace *ns, uid_t uid)
index 82ef9f3b7473a81ef5004362c7281ae9f4aea82a..193e977a10eaeb6a7f9ca5927d08f558d68df434 100644 (file)
@@ -1851,6 +1851,12 @@ static void destroy_worker(struct worker *worker)
        if (worker->flags & WORKER_IDLE)
                pool->nr_idle--;
 
+       /*
+        * Once WORKER_DIE is set, the kworker may destroy itself at any
+        * point.  Pin to ensure the task stays until we're done with it.
+        */
+       get_task_struct(worker->task);
+
        list_del_init(&worker->entry);
        worker->flags |= WORKER_DIE;
 
@@ -1859,6 +1865,7 @@ static void destroy_worker(struct worker *worker)
        spin_unlock_irq(&pool->lock);
 
        kthread_stop(worker->task);
+       put_task_struct(worker->task);
        kfree(worker);
 
        spin_lock_irq(&pool->lock);
index 82166bf974e14262ecfb064ea7c173d006d3ab98..4df39b1bde91ff9c9300db00f9df485733c064db 100644 (file)
@@ -1166,8 +1166,10 @@ alloc:
                } else {
                        ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
                                        pmd, orig_pmd, page, haddr);
-                       if (ret & VM_FAULT_OOM)
+                       if (ret & VM_FAULT_OOM) {
                                split_huge_page(page);
+                               ret |= VM_FAULT_FALLBACK;
+                       }
                        put_page(page);
                }
                count_vm_event(THP_FAULT_FALLBACK);
@@ -1179,9 +1181,10 @@ alloc:
                if (page) {
                        split_huge_page(page);
                        put_page(page);
-               }
+               } else
+                       split_huge_page_pmd(vma, address, pmd);
+               ret |= VM_FAULT_FALLBACK;
                count_vm_event(THP_FAULT_FALLBACK);
-               ret |= VM_FAULT_OOM;
                goto out;
        }
 
@@ -1545,6 +1548,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                                entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
+                       set_pmd_at(mm, addr, pmd, entry);
                        BUG_ON(pmd_write(entry));
                } else {
                        struct page *page = pmd_page(*pmd);
@@ -1557,16 +1561,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                         */
                        if (!is_huge_zero_page(page) &&
                            !pmd_numa(*pmd)) {
-                               entry = *pmd;
-                               entry = pmd_mknuma(entry);
+                               pmdp_set_numa(mm, addr, pmd);
                                ret = HPAGE_PMD_NR;
                        }
                }
-
-               /* Set PMD if cleared earlier */
-               if (ret == HPAGE_PMD_NR)
-                       set_pmd_at(mm, addr, pmd, entry);
-
                spin_unlock(ptl);
        }
 
index 53385cd4e6f02cfae85f99a2629f735094130c78..ce7a8cc7b40417556c7e2cffd4f5172ababb57c5 100644 (file)
@@ -1687,7 +1687,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
         * protects memcg_name and makes sure that parallel ooms do not
         * interleave
         */
-       static DEFINE_SPINLOCK(oom_info_lock);
+       static DEFINE_MUTEX(oom_info_lock);
        struct cgroup *task_cgrp;
        struct cgroup *mem_cgrp;
        static char memcg_name[PATH_MAX];
@@ -1698,7 +1698,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
        if (!p)
                return;
 
-       spin_lock(&oom_info_lock);
+       mutex_lock(&oom_info_lock);
        rcu_read_lock();
 
        mem_cgrp = memcg->css.cgroup;
@@ -1767,7 +1767,7 @@ done:
 
                pr_cont("\n");
        }
-       spin_unlock(&oom_info_lock);
+       mutex_unlock(&oom_info_lock);
 }
 
 /*
index be6a0c0d4ae081d48edd26f09d37f67cc70b1c52..22dfa617bddb69af777298c45739a0113f965b13 100644 (file)
@@ -3348,6 +3348,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                if (ret & VM_FAULT_LOCKED)
                        unlock_page(vmf.page);
                ret = VM_FAULT_HWPOISON;
+               page_cache_release(vmf.page);
                goto uncharge_out;
        }
 
@@ -3703,7 +3704,6 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(is_vm_hugetlb_page(vma)))
                return hugetlb_fault(mm, vma, address, flags);
 
-retry:
        pgd = pgd_offset(mm, address);
        pud = pud_alloc(mm, pgd, address);
        if (!pud)
@@ -3741,20 +3741,13 @@ retry:
                        if (dirty && !pmd_write(orig_pmd)) {
                                ret = do_huge_pmd_wp_page(mm, vma, address, pmd,
                                                          orig_pmd);
-                               /*
-                                * If COW results in an oom, the huge pmd will
-                                * have been split, so retry the fault on the
-                                * pte for a smaller charge.
-                                */
-                               if (unlikely(ret & VM_FAULT_OOM))
-                                       goto retry;
-                               return ret;
+                               if (!(ret & VM_FAULT_FALLBACK))
+                                       return ret;
                        } else {
                                huge_pmd_set_accessed(mm, vma, address, pmd,
                                                      orig_pmd, dirty);
+                               return 0;
                        }
-
-                       return 0;
                }
        }
 
index 7332c1785744fa0517a213b489e9c5b6bf350937..769a67a158037197341742104d2a9023cb1e03a0 100644 (file)
@@ -58,36 +58,27 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                                if (pte_numa(ptent))
                                        ptent = pte_mknonnuma(ptent);
                                ptent = pte_modify(ptent, newprot);
+                               /*
+                                * Avoid taking write faults for pages we
+                                * know to be dirty.
+                                */
+                               if (dirty_accountable && pte_dirty(ptent))
+                                       ptent = pte_mkwrite(ptent);
+                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                                updated = true;
                        } else {
                                struct page *page;
 
-                               ptent = *pte;
                                page = vm_normal_page(vma, addr, oldpte);
                                if (page && !PageKsm(page)) {
                                        if (!pte_numa(oldpte)) {
-                                               ptent = pte_mknuma(ptent);
-                                               set_pte_at(mm, addr, pte, ptent);
+                                               ptep_set_numa(mm, addr, pte);
                                                updated = true;
                                        }
                                }
                        }
-
-                       /*
-                        * Avoid taking write faults for pages we know to be
-                        * dirty.
-                        */
-                       if (dirty_accountable && pte_dirty(ptent)) {
-                               ptent = pte_mkwrite(ptent);
-                               updated = true;
-                       }
-
                        if (updated)
                                pages++;
-
-                       /* Only !prot_numa always clears the pte */
-                       if (!prot_numa)
-                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
index 196970a4541f0c07108eff49b7cb8d12fd930b06..d4042e75f7c7e7c7d498c4fcc33c90f1d1de2bff 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/vmstat.h>
 #include <linux/eventfd.h>
+#include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/printk.h>
 #include <linux/vmpressure.h>
index 512159bf607f0d4a3b09eae9af101775a8b56441..8323bced8e5bc9e8e1f6d552f7e94222c3f218ab 100644 (file)
@@ -241,19 +241,19 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr)
        size = bat_priv->num_ifaces * sizeof(uint8_t);
        orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC);
        if (!orig_node->bat_iv.bcast_own_sum)
-               goto free_bcast_own;
+               goto free_orig_node;
 
        hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
                                     batadv_choose_orig, orig_node,
                                     &orig_node->hash_entry);
        if (hash_added != 0)
-               goto free_bcast_own;
+               goto free_orig_node;
 
        return orig_node;
 
-free_bcast_own:
-       kfree(orig_node->bat_iv.bcast_own);
 free_orig_node:
+       /* free twice, as batadv_orig_node_new sets refcount to 2 */
+       batadv_orig_node_free_ref(orig_node);
        batadv_orig_node_free_ref(orig_node);
 
        return NULL;
@@ -266,7 +266,7 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
                        struct batadv_orig_node *orig_neigh)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
-       struct batadv_neigh_node *neigh_node;
+       struct batadv_neigh_node *neigh_node, *tmp_neigh_node;
 
        neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node);
        if (!neigh_node)
@@ -281,14 +281,24 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
        neigh_node->orig_node = orig_neigh;
        neigh_node->if_incoming = hard_iface;
 
-       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                  "Creating new neighbor %pM for orig_node %pM on interface %s\n",
-                  neigh_addr, orig_node->orig, hard_iface->net_dev->name);
-
        spin_lock_bh(&orig_node->neigh_list_lock);
-       hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+       tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface,
+                                              neigh_addr);
+       if (!tmp_neigh_node) {
+               hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+       } else {
+               kfree(neigh_node);
+               batadv_hardif_free_ref(hard_iface);
+               neigh_node = tmp_neigh_node;
+       }
        spin_unlock_bh(&orig_node->neigh_list_lock);
 
+       if (!tmp_neigh_node)
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Creating new neighbor %pM for orig_node %pM on interface %s\n",
+                          neigh_addr, orig_node->orig,
+                          hard_iface->net_dev->name);
+
 out:
        return neigh_node;
 }
index 3d417d3641c6d83a4ecb4f87bdf48d4f26d48242..b851cc58085330acbab02848fedf3cb01751a060 100644 (file)
@@ -241,7 +241,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        const struct batadv_hard_iface *hard_iface;
-       int min_mtu = ETH_DATA_LEN;
+       int min_mtu = INT_MAX;
 
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -256,8 +256,6 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
        }
        rcu_read_unlock();
 
-       atomic_set(&bat_priv->packet_size_max, min_mtu);
-
        if (atomic_read(&bat_priv->fragmentation) == 0)
                goto out;
 
@@ -268,13 +266,21 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
        min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE);
        min_mtu -= sizeof(struct batadv_frag_packet);
        min_mtu *= BATADV_FRAG_MAX_FRAGMENTS;
-       atomic_set(&bat_priv->packet_size_max, min_mtu);
-
-       /* with fragmentation enabled we can fragment external packets easily */
-       min_mtu = min_t(int, min_mtu, ETH_DATA_LEN);
 
 out:
-       return min_mtu - batadv_max_header_len();
+       /* report to the other components the maximum amount of bytes that
+        * batman-adv can send over the wire (without considering the payload
+        * overhead). For example, this value is used by TT to compute the
+        * maximum local table table size
+        */
+       atomic_set(&bat_priv->packet_size_max, min_mtu);
+
+       /* the real soft-interface MTU is computed by removing the payload
+        * overhead from the maximum amount of bytes that was just computed.
+        *
+        * However batman-adv does not support MTUs bigger than ETH_DATA_LEN
+        */
+       return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN);
 }
 
 /* adjusts the MTU if a new interface with a smaller MTU appeared. */
index 6df12a2e36052b7f8a07dea276565c362890863f..853941629dc15a3c60b569d315815aee4987fe08 100644 (file)
@@ -457,6 +457,42 @@ out:
        return neigh_node;
 }
 
+/**
+ * batadv_neigh_node_get - retrieve a neighbour from the list
+ * @orig_node: originator which the neighbour belongs to
+ * @hard_iface: the interface where this neighbour is connected to
+ * @addr: the address of the neighbour
+ *
+ * Looks for and possibly returns a neighbour belonging to this originator list
+ * which is connected through the provided hard interface.
+ * Returns NULL if the neighbour is not found.
+ */
+struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+                     const struct batadv_hard_iface *hard_iface,
+                     const uint8_t *addr)
+{
+       struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
+               if (!batadv_compare_eth(tmp_neigh_node->addr, addr))
+                       continue;
+
+               if (tmp_neigh_node->if_incoming != hard_iface)
+                       continue;
+
+               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+                       continue;
+
+               res = tmp_neigh_node;
+               break;
+       }
+       rcu_read_unlock();
+
+       return res;
+}
+
 /**
  * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
  * @rcu: rcu pointer of the orig_ifinfo object
index 37be290f63f6e603cb849e1484311389464682b3..db3a9ed734cb7c858c28d00e53250fd22d15f828 100644 (file)
@@ -29,6 +29,10 @@ void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node);
 struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
                                              const uint8_t *addr);
 struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+                     const struct batadv_hard_iface *hard_iface,
+                     const uint8_t *addr);
+struct batadv_neigh_node *
 batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
                      const uint8_t *neigh_addr,
                      struct batadv_orig_node *orig_node);
index 1ed9f7c9ecea4108f00d7beb6c2cb056f5ff87ed..a953d5b196a3825020ba306c8df42130a0d26eda 100644 (file)
@@ -688,7 +688,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
        int is_old_ttvn;
 
        /* check if there is enough data before accessing it */
-       if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0)
+       if (!pskb_may_pull(skb, hdr_len + ETH_HLEN))
                return 0;
 
        /* create a copy of the skb (in case of for re-routing) to modify it. */
@@ -918,6 +918,8 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
 
        if (ret != NET_RX_SUCCESS)
                ret = batadv_route_unicast_packet(skb, recv_if);
+       else
+               consume_skb(skb);
 
        return ret;
 }
index 579f5f00a385689f29a60ac111adf8b8682e1aa6..843febd1e5198914a398215037cd2d926f167738 100644 (file)
@@ -254,9 +254,9 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
                                   struct batadv_orig_node *orig_node,
                                   unsigned short vid)
 {
-       struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+       struct ethhdr *ethhdr;
        struct batadv_unicast_packet *unicast_packet;
-       int ret = NET_XMIT_DROP;
+       int ret = NET_XMIT_DROP, hdr_size;
 
        if (!orig_node)
                goto out;
@@ -265,12 +265,16 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
        case BATADV_UNICAST:
                if (!batadv_send_skb_prepare_unicast(skb, orig_node))
                        goto out;
+
+               hdr_size = sizeof(*unicast_packet);
                break;
        case BATADV_UNICAST_4ADDR:
                if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb,
                                                           orig_node,
                                                           packet_subtype))
                        goto out;
+
+               hdr_size = sizeof(struct batadv_unicast_4addr_packet);
                break;
        default:
                /* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -279,6 +283,7 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
                goto out;
        }
 
+       ethhdr = (struct ethhdr *)(skb->data + hdr_size);
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* inform the destination node that we are still missing a correct route
index b6071f675a3e57e159a99dec0c24f88603af9042..959dde721c46d057e23c494ba0b55175338466dc 100644 (file)
@@ -1975,6 +1975,7 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
        struct hlist_head *head;
        uint32_t i, crc_tmp, crc = 0;
        uint8_t flags;
+       __be16 tmp_vid;
 
        for (i = 0; i < hash->size; i++) {
                head = &hash->table[i];
@@ -2011,8 +2012,11 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
                                                             orig_node))
                                continue;
 
-                       crc_tmp = crc32c(0, &tt_common->vid,
-                                        sizeof(tt_common->vid));
+                       /* use network order to read the VID: this ensures that
+                        * every node reads the bytes in the same order.
+                        */
+                       tmp_vid = htons(tt_common->vid);
+                       crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
 
                        /* compute the CRC on flags that have to be kept in sync
                         * among nodes
@@ -2046,6 +2050,7 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
        struct hlist_head *head;
        uint32_t i, crc_tmp, crc = 0;
        uint8_t flags;
+       __be16 tmp_vid;
 
        for (i = 0; i < hash->size; i++) {
                head = &hash->table[i];
@@ -2064,8 +2069,11 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
                        if (tt_common->flags & BATADV_TT_CLIENT_NEW)
                                continue;
 
-                       crc_tmp = crc32c(0, &tt_common->vid,
-                                        sizeof(tt_common->vid));
+                       /* use network order to read the VID: this ensures that
+                        * every node reads the bytes in the same order.
+                        */
+                       tmp_vid = htons(tt_common->vid);
+                       crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
 
                        /* compute the CRC on flags that have to be kept in sync
                         * among nodes
@@ -2262,6 +2270,7 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
 {
        struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
        struct batadv_orig_node_vlan *vlan;
+       uint32_t crc;
        int i;
 
        /* check if each received CRC matches the locally stored one */
@@ -2281,7 +2290,10 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
                if (!vlan)
                        return false;
 
-               if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc))
+               crc = vlan->tt.crc;
+               batadv_orig_node_vlan_free_ref(vlan);
+
+               if (crc != ntohl(tt_vlan_tmp->crc))
                        return false;
        }
 
@@ -3218,7 +3230,6 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
 
                spin_lock_bh(&orig_node->tt_lock);
 
-               tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
                batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
                                         ttvn, tt_change);
 
index 292e619db8961c82e7c3aa7f3280cb4236176ab8..d9fb9345144238f61372fdb21ca57c08b9471efd 100644 (file)
@@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session)
                del_timer(&session->timer);
 }
 
+static void hidp_process_report(struct hidp_session *session,
+                               int type, const u8 *data, int len, int intr)
+{
+       if (len > HID_MAX_BUFFER_SIZE)
+               len = HID_MAX_BUFFER_SIZE;
+
+       memcpy(session->input_buf, data, len);
+       hid_input_report(session->hid, type, session->input_buf, len, intr);
+}
+
 static void hidp_process_handshake(struct hidp_session *session,
                                        unsigned char param)
 {
@@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
                        hidp_input_report(session, skb);
 
                if (session->hid)
-                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
+                       hidp_process_report(session, HID_INPUT_REPORT,
+                                           skb->data, skb->len, 0);
                break;
 
        case HIDP_DATA_RTYPE_OTHER:
@@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session,
                        hidp_input_report(session, skb);
 
                if (session->hid) {
-                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
+                       hidp_process_report(session, HID_INPUT_REPORT,
+                                           skb->data, skb->len, 1);
                        BT_DBG("report len %d", skb->len);
                }
        } else {
index ab5241400cf78a9d7371d7a866d58aeba0d8043a..8798492a6e9971fff198344b580fa5ec3f17b8be 100644 (file)
@@ -24,6 +24,7 @@
 #define __HIDP_H
 
 #include <linux/types.h>
+#include <linux/hid.h>
 #include <linux/kref.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/l2cap.h>
@@ -179,6 +180,9 @@ struct hidp_session {
 
        /* Used in hidp_output_raw_report() */
        int output_report_success; /* boolean */
+
+       /* temporary input buffer */
+       u8 input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 /* HIDP init defines */
index 4ad1b78c9c7790a84d4e697da1e025213e3a0eae..b1b0c8d4d7df31d34a575ab326dab71f1a315e51 100644 (file)
@@ -2420,7 +2420,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault);
  * 2. No high memory really exists on this machine.
  */
 
-static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
+static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_HIGHMEM
        int i;
@@ -2495,34 +2495,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)
 }
 
 static netdev_features_t harmonize_features(struct sk_buff *skb,
-       netdev_features_t features)
+                                           const struct net_device *dev,
+                                           netdev_features_t features)
 {
        if (skb->ip_summed != CHECKSUM_NONE &&
            !can_checksum_protocol(features, skb_network_protocol(skb))) {
                features &= ~NETIF_F_ALL_CSUM;
-       } else if (illegal_highdma(skb->dev, skb)) {
+       } else if (illegal_highdma(dev, skb)) {
                features &= ~NETIF_F_SG;
        }
 
        return features;
 }
 
-netdev_features_t netif_skb_features(struct sk_buff *skb)
+netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+                                        const struct net_device *dev)
 {
        __be16 protocol = skb->protocol;
-       netdev_features_t features = skb->dev->features;
+       netdev_features_t features = dev->features;
 
-       if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
+       if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs)
                features &= ~NETIF_F_GSO_MASK;
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
                struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
                protocol = veh->h_vlan_encapsulated_proto;
        } else if (!vlan_tx_tag_present(skb)) {
-               return harmonize_features(skb, features);
+               return harmonize_features(skb, dev, features);
        }
 
-       features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
+       features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
                                               NETIF_F_HW_VLAN_STAG_TX);
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
@@ -2530,9 +2532,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
                                NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
                                NETIF_F_HW_VLAN_STAG_TX;
 
-       return harmonize_features(skb, features);
+       return harmonize_features(skb, dev, features);
 }
-EXPORT_SYMBOL(netif_skb_features);
+EXPORT_SYMBOL(netif_skb_dev_features);
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq)
index 87577d447554336b33067ab6e2373c6bdd25b93d..e29e810663d777ecee281b61fda8ec8dbdcbfb92 100644 (file)
@@ -323,17 +323,6 @@ u32 __skb_get_poff(const struct sk_buff *skb)
        return poff;
 }
 
-static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
-{
-       if (unlikely(queue_index >= dev->real_num_tx_queues)) {
-               net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
-                                    dev->name, queue_index,
-                                    dev->real_num_tx_queues);
-               return 0;
-       }
-       return queue_index;
-}
-
 static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_XPS
@@ -372,7 +361,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 #endif
 }
 
-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
+static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 {
        struct sock *sk = skb->sk;
        int queue_index = sk_tx_queue_get(sk);
@@ -392,7 +381,6 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 
        return queue_index;
 }
-EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
                                    struct sk_buff *skb,
@@ -403,13 +391,13 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev,
        if (dev->real_num_tx_queues != 1) {
                const struct net_device_ops *ops = dev->netdev_ops;
                if (ops->ndo_select_queue)
-                       queue_index = ops->ndo_select_queue(dev, skb,
-                                                           accel_priv);
+                       queue_index = ops->ndo_select_queue(dev, skb, accel_priv,
+                                                           __netdev_pick_tx);
                else
                        queue_index = __netdev_pick_tx(dev, skb);
 
                if (!accel_priv)
-                       queue_index = dev_cap_txqueue(dev, queue_index);
+                       queue_index = netdev_cap_txqueue(dev, queue_index);
        }
 
        skb_set_queue_mapping(skb, queue_index);
index 048dc8d183aa9f9f105c0d4615b03d8ebd75931b..1a0dac2ef9ada3ac331fdd31ce1b1548898cf310 100644 (file)
@@ -1963,16 +1963,21 @@ replay:
 
                dev->ifindex = ifm->ifi_index;
 
-               if (ops->newlink)
+               if (ops->newlink) {
                        err = ops->newlink(net, dev, tb, data);
-               else
+                       /* Drivers should call free_netdev() in ->destructor
+                        * and unregister it on failure so that device could be
+                        * finally freed in rtnl_unlock.
+                        */
+                       if (err < 0)
+                               goto out;
+               } else {
                        err = register_netdevice(dev);
-
-               if (err < 0) {
-                       free_netdev(dev);
-                       goto out;
+                       if (err < 0) {
+                               free_netdev(dev);
+                               goto out;
+                       }
                }
-
                err = rtnl_configure_link(dev, ifm);
                if (err < 0)
                        unregister_netdevice(dev);
index c073b81a1f3e74887783dbd6096b77629d12fbe0..62b5828acde0906b71fc39955c9f2b36582d395a 100644 (file)
@@ -8,7 +8,7 @@
 #include "tfrc.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
-static bool tfrc_debug;
+bool tfrc_debug;
 module_param(tfrc_debug, bool, 0644);
 MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages");
 #endif
index a3d8f7c76ae091ba92704a3e6a70186c53b3b0f5..40ee7d62b6520d7daf2a1a8f3b54bda9cfbedfc2 100644 (file)
@@ -21,6 +21,7 @@
 #include "packet_history.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
+extern bool tfrc_debug;
 #define tfrc_pr_debug(format, a...)    DCCP_PR_DEBUG(tfrc_debug, format, ##a)
 #else
 #define tfrc_pr_debug(format, a...)
index e9f1217a8afdaf2559ce3fd7d134489994faf440..f3869c186d975e5a0f80f067fb461069f9ba2689 100644 (file)
 #include <net/route.h>
 #include <net/xfrm.h>
 
+static bool ip_may_fragment(const struct sk_buff *skb)
+{
+       return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ||
+              !skb->local_df;
+}
+
+static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
+{
+       if (skb->len <= mtu || skb->local_df)
+               return false;
+
+       if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+               return false;
+
+       return true;
+}
+
+static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb)
+{
+       unsigned int mtu;
+
+       if (skb->local_df || !skb_is_gso(skb))
+               return false;
+
+       mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true);
+
+       /* if seglen > mtu, do software segmentation for IP fragmentation on
+        * output.  DF bit cannot be set since ip_forward would have sent
+        * icmp error.
+        */
+       return skb_gso_network_seglen(skb) > mtu;
+}
+
+/* called if GSO skb needs to be fragmented on forward */
+static int ip_forward_finish_gso(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb_dst(skb);
+       netdev_features_t features;
+       struct sk_buff *segs;
+       int ret = 0;
+
+       features = netif_skb_dev_features(skb, dst->dev);
+       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+       if (IS_ERR(segs)) {
+               kfree_skb(skb);
+               return -ENOMEM;
+       }
+
+       consume_skb(skb);
+
+       do {
+               struct sk_buff *nskb = segs->next;
+               int err;
+
+               segs->next = NULL;
+               err = dst_output(segs);
+
+               if (err && ret == 0)
+                       ret = err;
+               segs = nskb;
+       } while (segs);
+
+       return ret;
+}
+
 static int ip_forward_finish(struct sk_buff *skb)
 {
        struct ip_options *opt  = &(IPCB(skb)->opt);
@@ -49,6 +114,9 @@ static int ip_forward_finish(struct sk_buff *skb)
        if (unlikely(opt->optlen))
                ip_forward_options(skb);
 
+       if (ip_gso_exceeds_dst_mtu(skb))
+               return ip_forward_finish_gso(skb);
+
        return dst_output(skb);
 }
 
@@ -91,8 +159,7 @@ int ip_forward(struct sk_buff *skb)
 
        IPCB(skb)->flags |= IPSKB_FORWARDED;
        mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
-       if (unlikely(skb->len > mtu && !skb_is_gso(skb) &&
-                    (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
+       if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) {
                IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
                          htonl(mtu));
index efa1138fa523be1ed228b66accbfa9ed75920265..b3e86ea7b71b7e480ce64d243e3c1951484a7cbb 100644 (file)
@@ -273,7 +273,7 @@ static int __init ic_open_devs(void)
 
                msleep(1);
 
-               if time_before(jiffies, next_msg)
+               if (time_before(jiffies, next_msg))
                        continue;
 
                elapsed = jiffies_to_msecs(jiffies - start);
index 25071b48921cebc4788a1f4b0b5fa118832f5910..4c011ec69ed43efacdf692592a849d691ca93d2d 100644 (file)
@@ -1597,6 +1597,7 @@ static int __mkroute_input(struct sk_buff *skb,
        rth->rt_gateway = 0;
        rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
+       RT_CACHE_STAT_INC(in_slow_tot);
 
        rth->dst.input = ip_forward;
        rth->dst.output = ip_output;
@@ -1695,10 +1696,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        err = fib_lookup(net, &fl4, &res);
-       if (err != 0)
+       if (err != 0) {
+               if (!IN_DEV_FORWARD(in_dev))
+                       err = -EHOSTUNREACH;
                goto no_route;
-
-       RT_CACHE_STAT_INC(in_slow_tot);
+       }
 
        if (res.type == RTN_BROADCAST)
                goto brd_input;
@@ -1712,8 +1714,10 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                goto local_input;
        }
 
-       if (!IN_DEV_FORWARD(in_dev))
+       if (!IN_DEV_FORWARD(in_dev)) {
+               err = -EHOSTUNREACH;
                goto no_route;
+       }
        if (res.type != RTN_UNICAST)
                goto martian_destination;
 
@@ -1768,6 +1772,7 @@ local_input:
        rth->rt_gateway = 0;
        rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
+       RT_CACHE_STAT_INC(in_slow_tot);
        if (res.type == RTN_UNREACHABLE) {
                rth->dst.input= ip_error;
                rth->dst.error= -err;
index ad235690684c97f873e0c24b774d5184055fe7e2..fdbfeca36d6344c22db31886c3661796eb9e8f86 100644 (file)
@@ -2783,6 +2783,8 @@ static void addrconf_gre_config(struct net_device *dev)
        ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
        if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
                addrconf_add_linklocal(idev, &addr);
+       else
+               addrconf_prefix_route(&addr, 64, dev, 0, 0);
 }
 #endif
 
index ef02b26ccf812e57e794e9b151746600bcb9a8f0..070a2fae2375cd5f6c4ad8109887dc6236ee5b08 100644 (file)
@@ -342,6 +342,20 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
        return mtu;
 }
 
+static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
+{
+       if (skb->len <= mtu || skb->local_df)
+               return false;
+
+       if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)
+               return true;
+
+       if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+               return false;
+
+       return true;
+}
+
 int ip6_forward(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
@@ -466,8 +480,7 @@ int ip6_forward(struct sk_buff *skb)
        if (mtu < IPV6_MIN_MTU)
                mtu = IPV6_MIN_MTU;
 
-       if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) ||
-           (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) {
+       if (ip6_pkt_too_big(skb, mtu)) {
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
index d6d1f1df9119acf15d15f0f2571be04ae8e74cae..ce1c4437061049a8ebea8d5d08e77995217b2a0d 100644 (file)
@@ -1057,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev)
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
                                         struct sk_buff *skb,
-                                        void *accel_priv)
+                                        void *accel_priv,
+                                        select_queue_fallback_t fallback)
 {
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1075,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
                                          struct sk_buff *skb,
-                                         void *accel_priv)
+                                         void *accel_priv,
+                                         select_queue_fallback_t fallback)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
index 6a2bb37506c567c1f03de74bf51eb8aa357e318e..48a6a93db29602c032fe254d4a1d41cbc7b3f051 100644 (file)
@@ -308,11 +308,27 @@ static bool packet_use_direct_xmit(const struct packet_sock *po)
        return po->xmit == packet_direct_xmit;
 }
 
-static u16 packet_pick_tx_queue(struct net_device *dev)
+static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)
 {
        return (u16) raw_smp_processor_id() % dev->real_num_tx_queues;
 }
 
+static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+       u16 queue_index;
+
+       if (ops->ndo_select_queue) {
+               queue_index = ops->ndo_select_queue(dev, skb, NULL,
+                                                   __packet_pick_tx_queue);
+               queue_index = netdev_cap_txqueue(dev, queue_index);
+       } else {
+               queue_index = __packet_pick_tx_queue(dev, skb);
+       }
+
+       skb_set_queue_mapping(skb, queue_index);
+}
+
 /* register_prot_hook must be invoked with the po->bind_lock held,
  * or from a context in which asynchronous accesses to the packet
  * socket is not possible (packet_create()).
@@ -2285,7 +2301,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                        }
                }
 
-               skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
+               packet_pick_tx_queue(dev, skb);
+
                skb->destructor = tpacket_destruct_skb;
                __packet_set_status(po, ph, TP_STATUS_SENDING);
                packet_inc_pending(&po->tx_ring);
@@ -2499,7 +2516,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        skb->dev = dev;
        skb->priority = sk->sk_priority;
        skb->mark = sk->sk_mark;
-       skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
+
+       packet_pick_tx_queue(dev, skb);
 
        if (po->has_vnet_hdr) {
                if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
@@ -3786,7 +3804,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                 */
                        if (!tx_ring)
                                init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring);
-                               break;
+                       break;
                default:
                        break;
                }
index a255d0200a593a708a6f30f4e9dbb70fabb917c3..fefeeb73f15f18a84406ed686dc653ff3327ef45 100644 (file)
  *
  * ECN support is added by Naeem Khademi <naeemk@ifi.uio.no>
  * University of Oslo, Norway.
+ *
+ * References:
+ * IETF draft submission: http://tools.ietf.org/html/draft-pan-aqm-pie-00
+ * IEEE  Conference on High Performance Switching and Routing 2013 :
+ * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem"
  */
 
 #include <linux/module.h>
@@ -36,7 +41,7 @@ struct pie_params {
        psched_time_t target;   /* user specified target delay in pschedtime */
        u32 tupdate;            /* timer frequency (in jiffies) */
        u32 limit;              /* number of packets that can be enqueued */
-       u32 alpha;              /* alpha and beta are between -4 and 4 */
+       u32 alpha;              /* alpha and beta are between 0 and 32 */
        u32 beta;               /* and are used for shift relative to 1 */
        bool ecn;               /* true if ecn is enabled */
        bool bytemode;          /* to scale drop early prob based on pkt size */
@@ -326,10 +331,16 @@ static void calculate_probability(struct Qdisc *sch)
        if (qdelay == 0 && qlen != 0)
                update_prob = false;
 
-       /* Add ranges for alpha and beta, more aggressive for high dropping
-        * mode and gentle steps for light dropping mode
-        * In light dropping mode, take gentle steps; in medium dropping mode,
-        * take medium steps; in high dropping mode, take big steps.
+       /* In the algorithm, alpha and beta are between 0 and 2 with typical
+        * value for alpha as 0.125. In this implementation, we use values 0-32
+        * passed from user space to represent this. Also, alpha and beta have
+        * unit of HZ and need to be scaled before they can used to update
+        * probability. alpha/beta are updated locally below by 1) scaling them
+        * appropriately 2) scaling down by 16 to come to 0-2 range.
+        * Please see paper for details.
+        *
+        * We scale alpha and beta differently depending on whether we are in
+        * light, medium or high dropping mode.
         */
        if (q->vars.prob < MAX_PROB / 100) {
                alpha =
index 5ae60920067470463420f0b3aa879e7c0999f200..f558433537b8f829a3f6147256abb7c5d23e4b47 100644 (file)
@@ -1367,44 +1367,35 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
        return false;
 }
 
-/* Increase asoc's rwnd by len and send any window update SACK if needed. */
-void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
+/* Update asoc's rwnd for the approximated state in the buffer,
+ * and check whether SACK needs to be sent.
+ */
+void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
 {
+       int rx_count;
        struct sctp_chunk *sack;
        struct timer_list *timer;
 
-       if (asoc->rwnd_over) {
-               if (asoc->rwnd_over >= len) {
-                       asoc->rwnd_over -= len;
-               } else {
-                       asoc->rwnd += (len - asoc->rwnd_over);
-                       asoc->rwnd_over = 0;
-               }
-       } else {
-               asoc->rwnd += len;
-       }
+       if (asoc->ep->rcvbuf_policy)
+               rx_count = atomic_read(&asoc->rmem_alloc);
+       else
+               rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
 
-       /* If we had window pressure, start recovering it
-        * once our rwnd had reached the accumulated pressure
-        * threshold.  The idea is to recover slowly, but up
-        * to the initial advertised window.
-        */
-       if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
-               int change = min(asoc->pathmtu, asoc->rwnd_press);
-               asoc->rwnd += change;
-               asoc->rwnd_press -= change;
-       }
+       if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0)
+               asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1;
+       else
+               asoc->rwnd = 0;
 
-       pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n",
-                __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
-                asoc->a_rwnd);
+       pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n",
+                __func__, asoc, asoc->rwnd, rx_count,
+                asoc->base.sk->sk_rcvbuf);
 
        /* Send a window update SACK if the rwnd has increased by at least the
         * minimum of the association's PMTU and half of the receive buffer.
         * The algorithm used is similar to the one described in
         * Section 4.2.3.3 of RFC 1122.
         */
-       if (sctp_peer_needs_update(asoc)) {
+       if (update_peer && sctp_peer_needs_update(asoc)) {
                asoc->a_rwnd = asoc->rwnd;
 
                pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u "
@@ -1426,45 +1417,6 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
        }
 }
 
-/* Decrease asoc's rwnd by len. */
-void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
-{
-       int rx_count;
-       int over = 0;
-
-       if (unlikely(!asoc->rwnd || asoc->rwnd_over))
-               pr_debug("%s: association:%p has asoc->rwnd:%u, "
-                        "asoc->rwnd_over:%u!\n", __func__, asoc,
-                        asoc->rwnd, asoc->rwnd_over);
-
-       if (asoc->ep->rcvbuf_policy)
-               rx_count = atomic_read(&asoc->rmem_alloc);
-       else
-               rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
-
-       /* If we've reached or overflowed our receive buffer, announce
-        * a 0 rwnd if rwnd would still be positive.  Store the
-        * the potential pressure overflow so that the window can be restored
-        * back to original value.
-        */
-       if (rx_count >= asoc->base.sk->sk_rcvbuf)
-               over = 1;
-
-       if (asoc->rwnd >= len) {
-               asoc->rwnd -= len;
-               if (over) {
-                       asoc->rwnd_press += asoc->rwnd;
-                       asoc->rwnd = 0;
-               }
-       } else {
-               asoc->rwnd_over = len - asoc->rwnd;
-               asoc->rwnd = 0;
-       }
-
-       pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n",
-                __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
-                asoc->rwnd_press);
-}
 
 /* Build the bind address list for the association based on info from the
  * local endpoint and the remote peer.
index 483dcd71b3c5f76a17dc66aee156c0b6caf60bac..591b44d3b7de6bb39faa994cddc72851422ec08f 100644 (file)
@@ -6176,7 +6176,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
         * PMTU.  In cases, such as loopback, this might be a rather
         * large spill over.
         */
-       if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over ||
+       if ((!chunk->data_accepted) && (!asoc->rwnd ||
            (datalen > asoc->rwnd + asoc->frag_point))) {
 
                /* If this is the next TSN, consider reneging to make
index 9e91d6e5df63e4317eeeb367d55e734e5a62af2f..981aaf8b6ace45e55b80a235ebbb9dfcb693d64b 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/crypto.h>
 #include <linux/slab.h>
 #include <linux/file.h>
+#include <linux/compat.h>
 
 #include <net/ip.h>
 #include <net/icmp.h>
@@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk,
 /*
  * New (hopefully final) interface for the API.
  * We use the sctp_getaddrs_old structure so that use-space library
- * can avoid any unnecessary allocations.   The only defferent part
+ * can avoid any unnecessary allocations. The only different part
  * is that we store the actual length of the address buffer into the
- * addrs_num structure member.  That way we can re-use the existing
+ * addrs_num structure member. That way we can re-use the existing
  * code.
  */
+#ifdef CONFIG_COMPAT
+struct compat_sctp_getaddrs_old {
+       sctp_assoc_t    assoc_id;
+       s32             addr_num;
+       compat_uptr_t   addrs;          /* struct sockaddr * */
+};
+#endif
+
 static int sctp_getsockopt_connectx3(struct sock *sk, int len,
                                     char __user *optval,
                                     int __user *optlen)
@@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len,
        sctp_assoc_t assoc_id = 0;
        int err = 0;
 
-       if (len < sizeof(param))
-               return -EINVAL;
+#ifdef CONFIG_COMPAT
+       if (is_compat_task()) {
+               struct compat_sctp_getaddrs_old param32;
 
-       if (copy_from_user(&param, optval, sizeof(param)))
-               return -EFAULT;
+               if (len < sizeof(param32))
+                       return -EINVAL;
+               if (copy_from_user(&param32, optval, sizeof(param32)))
+                       return -EFAULT;
 
-       err = __sctp_setsockopt_connectx(sk,
-                       (struct sockaddr __user *)param.addrs,
-                       param.addr_num, &assoc_id);
+               param.assoc_id = param32.assoc_id;
+               param.addr_num = param32.addr_num;
+               param.addrs = compat_ptr(param32.addrs);
+       } else
+#endif
+       {
+               if (len < sizeof(param))
+                       return -EINVAL;
+               if (copy_from_user(&param, optval, sizeof(param)))
+                       return -EFAULT;
+       }
 
+       err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *)
+                                        param.addrs, param.addr_num,
+                                        &assoc_id);
        if (err == 0 || err == -EINPROGRESS) {
                if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
                        return -EFAULT;
@@ -2092,12 +2115,6 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
                sctp_skb_pull(skb, copied);
                skb_queue_head(&sk->sk_receive_queue, skb);
 
-               /* When only partial message is copied to the user, increase
-                * rwnd by that amount. If all the data in the skb is read,
-                * rwnd is updated when the event is freed.
-                */
-               if (!sctp_ulpevent_is_notification(event))
-                       sctp_assoc_rwnd_increase(event->asoc, copied);
                goto out;
        } else if ((event->msg_flags & MSG_NOTIFICATION) ||
                   (event->msg_flags & MSG_EOR))
index 7135e617ab0ffa7343a2d698e94c6a71d5334d9d..35c8923b5554aa33549eb872c8d2aaa292b34db1 100644 (file)
@@ -151,6 +151,7 @@ static struct ctl_table sctp_net_table[] = {
        },
        {
                .procname       = "cookie_hmac_alg",
+               .data           = &init_net.sctp.sctp_hmac_alg,
                .maxlen         = 8,
                .mode           = 0644,
                .proc_handler   = proc_sctp_do_hmac_alg,
@@ -401,15 +402,18 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
 
 int sctp_sysctl_net_register(struct net *net)
 {
-       struct ctl_table *table;
-       int i;
+       struct ctl_table *table = sctp_net_table;
+
+       if (!net_eq(net, &init_net)) {
+               int i;
 
-       table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
-       if (!table)
-               return -ENOMEM;
+               table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
+               if (!table)
+                       return -ENOMEM;
 
-       for (i = 0; table[i].data; i++)
-               table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+               for (i = 0; table[i].data; i++)
+                       table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+       }
 
        net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
        return 0;
index 85c64658bd0b183df5c7a7fd8394df757cb0b4b0..8d198ae0360634d25d3e4cff8a56cf73e389bd2d 100644 (file)
@@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
        skb = sctp_event2skb(event);
        /* Set the owner and charge rwnd for bytes received.  */
        sctp_ulpevent_set_owner(event, asoc);
-       sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
+       sctp_assoc_rwnd_update(asoc, false);
 
        if (!skb->data_len)
                return;
@@ -1011,6 +1011,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
        struct sk_buff *skb, *frag;
        unsigned int    len;
+       struct sctp_association *asoc;
 
        /* Current stack structures assume that the rcv buffer is
         * per socket.   For UDP style sockets this is not true as
@@ -1035,8 +1036,11 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
        }
 
 done:
-       sctp_assoc_rwnd_increase(event->asoc, len);
+       asoc = event->asoc;
+       sctp_association_hold(asoc);
        sctp_ulpevent_release_owner(event);
+       sctp_assoc_rwnd_update(asoc, true);
+       sctp_association_put(asoc);
 }
 
 static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
index 6c0513a7f99232280f78067d56c5c369cb79630d..36e431ee1c902ef1c6ed777331cf97ceda0bdee4 100644 (file)
@@ -108,6 +108,7 @@ struct gss_auth {
 static DEFINE_SPINLOCK(pipe_version_lock);
 static struct rpc_wait_queue pipe_version_rpc_waitqueue;
 static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
+static void gss_put_auth(struct gss_auth *gss_auth);
 
 static void gss_free_ctx(struct gss_cl_ctx *);
 static const struct rpc_pipe_ops gss_upcall_ops_v0;
@@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
        if (gss_msg->ctx != NULL)
                gss_put_ctx(gss_msg->ctx);
        rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
+       gss_put_auth(gss_msg->auth);
        kfree(gss_msg);
 }
 
@@ -498,9 +500,12 @@ gss_alloc_msg(struct gss_auth *gss_auth,
        default:
                err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
                if (err)
-                       goto err_free_msg;
+                       goto err_put_pipe_version;
        };
+       kref_get(&gss_auth->kref);
        return gss_msg;
+err_put_pipe_version:
+       put_pipe_version(gss_auth->net);
 err_free_msg:
        kfree(gss_msg);
 err:
@@ -991,6 +996,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
        gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
        if (gss_auth->service == 0)
                goto err_put_mech;
+       if (!gssd_running(gss_auth->net))
+               goto err_put_mech;
        auth = &gss_auth->rpc_auth;
        auth->au_cslack = GSS_CRED_SLACK >> 2;
        auth->au_rslack = GSS_VERF_SLACK >> 2;
@@ -1061,6 +1068,12 @@ gss_free_callback(struct kref *kref)
        gss_free(gss_auth);
 }
 
+static void
+gss_put_auth(struct gss_auth *gss_auth)
+{
+       kref_put(&gss_auth->kref, gss_free_callback);
+}
+
 static void
 gss_destroy(struct rpc_auth *auth)
 {
@@ -1082,7 +1095,7 @@ gss_destroy(struct rpc_auth *auth)
        gss_auth->gss_pipe[1] = NULL;
        rpcauth_destroy_credcache(auth);
 
-       kref_put(&gss_auth->kref, gss_free_callback);
+       gss_put_auth(gss_auth);
 }
 
 /*
@@ -1253,7 +1266,7 @@ gss_destroy_nullcred(struct rpc_cred *cred)
        call_rcu(&cred->cr_rcu, gss_free_cred_callback);
        if (ctx)
                gss_put_ctx(ctx);
-       kref_put(&gss_auth->kref, gss_free_callback);
+       gss_put_auth(gss_auth);
 }
 
 static void
index 890a29912d5ab3f39d156891d4844ede04d367e8..e860d4f7ed2accd100c9ae9f715018daaae469a1 100644 (file)
@@ -64,7 +64,6 @@ static void xprt_free_allocation(struct rpc_rqst *req)
        free_page((unsigned long)xbufp->head[0].iov_base);
        xbufp = &req->rq_snd_buf;
        free_page((unsigned long)xbufp->head[0].iov_base);
-       list_del(&req->rq_bc_pa_list);
        kfree(req);
 }
 
@@ -168,8 +167,10 @@ out_free:
        /*
         * Memory allocation failed, free the temporary list
         */
-       list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
+       list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) {
+               list_del(&req->rq_bc_pa_list);
                xprt_free_allocation(req);
+       }
 
        dprintk("RPC:       setup backchannel transport failed\n");
        return -ENOMEM;
@@ -198,6 +199,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
        xprt_dec_alloc_count(xprt, max_reqs);
        list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
                dprintk("RPC:        req=%p\n", req);
+               list_del(&req->rq_bc_pa_list);
                xprt_free_allocation(req);
                if (--max_reqs == 0)
                        break;
index 817a1e5239692e9fb3f5117f36eb0895d426ea5f..0addefca8e7757d78571928580d6f7473a1354ae 100644 (file)
@@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct sock *sk = transport->inet;
        int ret = -EAGAIN;
 
        dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
@@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task)
                         * window size
                         */
                        set_bit(SOCK_NOSPACE, &transport->sock->flags);
-                       transport->inet->sk_write_pending++;
+                       sk->sk_write_pending++;
                        /* ...and wait for more buffer space */
                        xprt_wait_for_buffer_space(task, xs_nospace_callback);
                }
@@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task)
        }
 
        spin_unlock_bh(&xprt->transport_lock);
+
+       /* Race breaker in case memory is freed before above code is called */
+       sk->sk_write_space(sk);
        return ret;
 }
 
index 1ff477b0450d78bacb9522105f638f6523d625f6..5569d96b4da3f3652bd418656a2f7e81822feda4 100644 (file)
@@ -192,6 +192,7 @@ static inline void k_term_timer(struct timer_list *timer)
 
 struct tipc_skb_cb {
        void *handle;
+       bool deferred;
 };
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
index d4b5de41b682188f1cf3bcffb08a44f38a9f84ae..da6018beb6ebc149b72efd816f4d7154bc6cdfd7 100644 (file)
@@ -1391,6 +1391,12 @@ static int link_recv_buf_validate(struct sk_buff *buf)
        u32 hdr_size;
        u32 min_hdr_size;
 
+       /* If this packet comes from the defer queue, the skb has already
+        * been validated
+        */
+       if (unlikely(TIPC_SKB_CB(buf)->deferred))
+               return 1;
+
        if (unlikely(buf->len < MIN_H_SIZE))
                return 0;
 
@@ -1703,6 +1709,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
                                &l_ptr->newest_deferred_in, buf)) {
                l_ptr->deferred_inqueue_sz++;
                l_ptr->stats.deferred_recv++;
+               TIPC_SKB_CB(buf)->deferred = true;
                if ((l_ptr->deferred_inqueue_sz % 16) == 1)
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
        } else
index 49392ecbef17baf113bb9e3771384d06413bbb25..79c059e708600b04b63f8bc27cca94b485684cc8 100644 (file)
@@ -152,6 +152,7 @@ ld_flags       = $(LDFLAGS) $(ldflags-y)
 dtc_cpp_flags  = -Wp,-MD,$(depfile).pre.tmp -nostdinc                    \
                 -I$(srctree)/arch/$(SRCARCH)/boot/dts                   \
                 -I$(srctree)/arch/$(SRCARCH)/boot/dts/include           \
+                -I$(srctree)/drivers/of/testcase-data                   \
                 -undef -D__DTS__
 
 # Finds the multi-part object the current object will be linked into
index c0f4988421292f0ab6610421704ee21381b59a0f..9c5cdc2caaef7637b4bf9178a8efcbe69558c6b9 100644 (file)
@@ -3338,10 +3338,10 @@ static int filename_write_helper(void *key, void *data, void *ptr)
        if (rc)
                return rc;
 
-       buf[0] = ft->stype;
-       buf[1] = ft->ttype;
-       buf[2] = ft->tclass;
-       buf[3] = otype->otype;
+       buf[0] = cpu_to_le32(ft->stype);
+       buf[1] = cpu_to_le32(ft->ttype);
+       buf[2] = cpu_to_le32(ft->tclass);
+       buf[3] = cpu_to_le32(otype->otype);
 
        rc = put_entry(buf, sizeof(u32), 4, fp);
        if (rc)
index 54d14793725a7dd93623083d29f72f41a5ddc4bd..46ecdbb9053f337ee6f1b199d9babdeb043d72d5 100644 (file)
@@ -2661,60 +2661,6 @@ static bool dspload_wait_loaded(struct hda_codec *codec)
        return false;
 }
 
-/*
- * PCM stuffs
- */
-static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-                                u32 stream_tag,
-                                int channel_id, int format)
-{
-       unsigned int oldval, newval;
-
-       if (!nid)
-               return;
-
-       snd_printdd(
-                  "ca0132_setup_stream: NID=0x%x, stream=0x%x, "
-                  "channel=%d, format=0x%x\n",
-                  nid, stream_tag, channel_id, format);
-
-       /* update the format-id if changed */
-       oldval = snd_hda_codec_read(codec, nid, 0,
-                                   AC_VERB_GET_STREAM_FORMAT,
-                                   0);
-       if (oldval != format) {
-               msleep(20);
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_STREAM_FORMAT,
-                                   format);
-       }
-
-       oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
-       newval = (stream_tag << 4) | channel_id;
-       if (oldval != newval) {
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CHANNEL_STREAMID,
-                                   newval);
-       }
-}
-
-static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
-{
-       unsigned int val;
-
-       if (!nid)
-               return;
-
-       snd_printdd(KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n", nid);
-
-       val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
-       if (!val)
-               return;
-
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
-}
-
 /*
  * PCM callbacks
  */
@@ -2726,7 +2672,7 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 {
        struct ca0132_spec *spec = codec->spec;
 
-       ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
+       snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
 
        return 0;
 }
@@ -2745,7 +2691,7 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
        if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
                msleep(50);
 
-       ca0132_cleanup_stream(codec, spec->dacs[0]);
+       snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
 
        return 0;
 }
@@ -2822,10 +2768,8 @@ static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
                                        unsigned int format,
                                        struct snd_pcm_substream *substream)
 {
-       struct ca0132_spec *spec = codec->spec;
-
-       ca0132_setup_stream(codec, spec->adcs[substream->number],
-                           stream_tag, 0, format);
+       snd_hda_codec_setup_stream(codec, hinfo->nid,
+                                  stream_tag, 0, format);
 
        return 0;
 }
@@ -2839,7 +2783,7 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
        if (spec->dsp_state == DSP_DOWNLOADING)
                return 0;
 
-       ca0132_cleanup_stream(codec, hinfo->nid);
+       snd_hda_codec_cleanup_stream(codec, hinfo->nid);
        return 0;
 }
 
@@ -4742,6 +4686,8 @@ static int patch_ca0132(struct hda_codec *codec)
                return err;
 
        codec->patch_ops = ca0132_patch_ops;
+       codec->pcm_format_first = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
index a9a83b85517aa0738bed1e2ee29b39ae945c37e4..ec304f3ae3b41d4a8a1295c448ff35e18eb58977 100644 (file)
@@ -4308,7 +4308,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4317,6 +4319,54 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
+       /* ALC282 */
+       SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22a0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c1, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22cd, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       /* ALC290 */
+       SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2280, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2281, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2289, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
index 7311badf6a946e3ef33fa5281ed5d5e4f165482e..3bc29c9b25296d6ed058eaf552bf71bdba356cab 100644 (file)
@@ -83,6 +83,7 @@ enum {
        STAC_DELL_M6_BOTH,
        STAC_DELL_EQ,
        STAC_ALIENWARE_M17X,
+       STAC_92HD89XX_HP_FRONT_JACK,
        STAC_92HD73XX_MODELS
 };
 
@@ -97,6 +98,7 @@ enum {
        STAC_92HD83XXX_HP_LED,
        STAC_92HD83XXX_HP_INV_LED,
        STAC_92HD83XXX_HP_MIC_LED,
+       STAC_HP_LED_GPIO10,
        STAC_92HD83XXX_HEADSET_JACK,
        STAC_92HD83XXX_HP,
        STAC_HP_ENVY_BASS,
@@ -1795,6 +1797,12 @@ static const struct hda_pintbl intel_dg45id_pin_configs[] = {
        {}
 };
 
+static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
+       { 0x0a, 0x02214030 },
+       { 0x0b, 0x02A19010 },
+       {}
+};
+
 static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
 {
@@ -1913,6 +1921,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
        [STAC_92HD73XX_NO_JD] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = stac92hd73xx_fixup_no_jd,
+       },
+       [STAC_92HD89XX_HP_FRONT_JACK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = stac92hd89xx_hp_front_jack_pin_configs,
        }
 };
 
@@ -1973,6 +1985,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
                      "Alienware M17x", STAC_ALIENWARE_M17X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
                      "Alienware M17x R3", STAC_DELL_EQ),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
+                               "unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
        {} /* terminator */
 };
 
@@ -2117,6 +2131,17 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
        }
 }
 
+static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec,
+                                  const struct hda_fixup *fix, int action)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->gpio_led = 0x10; /* GPIO4 */
+               spec->default_polarity = 0;
+       }
+}
+
 static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
 {
@@ -2611,6 +2636,12 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = {
                .chained = true,
                .chain_id = STAC_92HD83XXX_HP,
        },
+       [STAC_HP_LED_GPIO10] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = stac92hd83xxx_fixup_hp_led_gpio10,
+               .chained = true,
+               .chain_id = STAC_92HD83XXX_HP,
+       },
        [STAC_92HD83XXX_HEADSET_JACK] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = stac92hd83xxx_fixup_headset_jack,
@@ -2689,6 +2720,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
                          "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888,
                          "HP Envy Spectre", STAC_HP_ENVY_BASS),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899,
+                         "HP Folio 13", STAC_HP_LED_GPIO10),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df,
                          "HP Folio", STAC_HP_BNB13_EQ),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8,
index 54f74f8cbb754a0e66aecc3953fff0c8ba63966c..4544d8eb1452b24638c969ed15432a6f41e98ef8 100644 (file)
@@ -11,7 +11,7 @@ config SND_BF5XX_I2S
 
 config SND_BF5XX_SOC_SSM2602
        tristate "SoC SSM2602 Audio Codec Add-On Card support"
-       depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+       depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
        select SND_BF5XX_SOC_I2S if !BF60x
        select SND_BF6XX_SOC_I2S if BF60x
        select SND_SOC_SSM2602
@@ -21,10 +21,9 @@ config SND_BF5XX_SOC_SSM2602
 
 config SND_SOC_BFIN_EVAL_ADAU1701
        tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards"
-       depends on SND_BF5XX_I2S
+       depends on SND_BF5XX_I2S && I2C
        select SND_BF5XX_SOC_I2S
        select SND_SOC_ADAU1701
-       select I2C
        help
          Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ
          board connected to one of the Blackfin evaluation boards like the
@@ -45,7 +44,7 @@ config SND_SOC_BFIN_EVAL_ADAU1373
 
 config SND_SOC_BFIN_EVAL_ADAV80X
        tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
-       depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+       depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
        select SND_BF5XX_SOC_I2S
        select SND_SOC_ADAV80X
        help
@@ -58,7 +57,7 @@ config SND_SOC_BFIN_EVAL_ADAV80X
 
 config SND_BF5XX_SOC_AD1836
        tristate "SoC AD1836 Audio support for BF5xx"
-       depends on SND_BF5XX_I2S
+       depends on SND_BF5XX_I2S && SPI_MASTER
        select SND_BF5XX_SOC_I2S
        select SND_SOC_AD1836
        help
@@ -66,7 +65,7 @@ config SND_BF5XX_SOC_AD1836
 
 config SND_BF5XX_SOC_AD193X
        tristate "SoC AD193X Audio support for Blackfin"
-       depends on SND_BF5XX_I2S
+       depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
        select SND_BF5XX_SOC_I2S
        select SND_SOC_AD193X
        help
index 7257a8885f426d7cf05b017fbda1aa3f01abe236..34d965a4a040c91d861a8d2f8a3ef183b95bc5e8 100644 (file)
@@ -57,8 +57,8 @@ static const u16 ad1980_reg[] = {
 static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line",
                "Stereo Mix", "Mono Mix", "Phone"};
 
-static const struct soc_enum ad1980_cap_src =
-       SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel);
+static SOC_ENUM_DOUBLE_DECL(ad1980_cap_src,
+                           AC97_REC_SEL, 8, 0, ad1980_rec_sel);
 
 static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = {
 SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
index f295b65699105897743fad1ecbc4439a71e58f0e..f4d965ebc29e8320469becd09a3ac58a2668e8de 100644 (file)
@@ -1268,11 +1268,23 @@ static struct snd_soc_dai_driver da732x_dai[] = {
        },
 };
 
+static bool da732x_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case DA732X_REG_HPL_DAC_OFF_CNTL:
+       case DA732X_REG_HPR_DAC_OFF_CNTL:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static const struct regmap_config da732x_regmap = {
        .reg_bits               = 8,
        .val_bits               = 8,
 
        .max_register           = DA732X_MAX_REG,
+       .volatile_reg           = da732x_volatile,
        .reg_defaults           = da732x_reg_cache,
        .num_reg_defaults       = ARRAY_SIZE(da732x_reg_cache),
        .cache_type             = REGCACHE_RBTREE,
index 52b79a487ac7db318dd252fe30befd6a3c56b2ec..422812613a28b1cff117b1adfee2029b69e6049b 100644 (file)
@@ -1523,8 +1523,15 @@ static int da9055_remove(struct i2c_client *client)
        return 0;
 }
 
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the CODEC and PMIC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 Ids for CODEC
+ * and PMIC, which must be different to operate together.
+ */
 static const struct i2c_device_id da9055_i2c_id[] = {
-       { "da9055", 0 },
+       { "da9055-codec", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
@@ -1532,7 +1539,7 @@ MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
 /* I2C codec control layer */
 static struct i2c_driver da9055_i2c_driver = {
        .driver = {
-               .name = "da9055",
+               .name = "da9055-codec",
                .owner = THIS_MODULE,
        },
        .probe          = da9055_i2c_probe,
index 5839048ec4674e5d20cc5f06e206c2210977999e..cb736ddc446dc0bc5a387dc3ebc28e4bb0fee9aa 100644 (file)
@@ -140,13 +140,17 @@ static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"};
 static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"};
 
 static const struct soc_enum isabelle_rx1_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts),
-       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts),
+       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3,
+                       ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5,
+                       ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
 };
 
 static const struct soc_enum isabelle_rx2_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts),
-       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts),
+       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2,
+                       ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4,
+                       ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
 };
 
 /* Headset DAC playback switches */
@@ -161,13 +165,17 @@ static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"};
 static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"};
 
 static const struct soc_enum isabelle_atx_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts),
-       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+                       ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
 };
 
 static const struct soc_enum isabelle_vtx_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts),
-       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6,
+                       ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+                       ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
 };
 
 static const struct snd_kcontrol_new atx_mux_controls =
@@ -183,17 +191,13 @@ static const char *isabelle_amic1_texts[] = {
 /* Left analog microphone selection */
 static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"};
 
-static const struct soc_enum isabelle_amic1_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5,
-                       ARRAY_SIZE(isabelle_amic1_texts),
-                       isabelle_amic1_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic1_enum,
+                           ISABELLE_AMIC_CFG_REG, 5,
+                           isabelle_amic1_texts);
 
-static const struct soc_enum isabelle_amic2_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4,
-                       ARRAY_SIZE(isabelle_amic2_texts),
-                       isabelle_amic2_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic2_enum,
+                           ISABELLE_AMIC_CFG_REG, 4,
+                           isabelle_amic2_texts);
 
 static const struct snd_kcontrol_new amic1_control =
        SOC_DAPM_ENUM("Route", isabelle_amic1_enum);
@@ -206,16 +210,20 @@ static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"};
 static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"};
 
 static const struct soc_enum isabelle_st_audio_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_audio_texts),
                        isabelle_st_audio_texts),
-       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_audio_texts),
                        isabelle_st_audio_texts),
 };
 
 static const struct soc_enum isabelle_st_voice_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_voice_texts),
                        isabelle_st_voice_texts),
-       SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_voice_texts),
                        isabelle_st_voice_texts),
 };
 
index 51f9b3d16b41dbf4cc80dddc6d0a081ccb83fe90..9f714ea86613cc6939c62c3a420dc0c2ce07bb17 100644 (file)
@@ -336,6 +336,7 @@ static bool max98090_readable_register(struct device *dev, unsigned int reg)
        case M98090_REG_RECORD_TDM_SLOT:
        case M98090_REG_SAMPLE_RATE:
        case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E:
+       case M98090_REG_REVISION_ID:
                return true;
        default:
                return false;
@@ -1769,16 +1770,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = regcache_sync(max98090->regmap);
-
-                       if (ret != 0) {
-                               dev_err(codec->dev,
-                                       "Failed to sync cache: %d\n", ret);
-                               return ret;
-                       }
-               }
-
                if (max98090->jack_state == M98090_JACK_STATE_HEADSET) {
                        /*
                         * Set to normal bias level.
@@ -1792,6 +1783,16 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regcache_sync(max98090->regmap);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to sync cache: %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
        case SND_SOC_BIAS_OFF:
                /* Set internal pull-up to lowest power mode */
                snd_soc_update_bits(codec, M98090_REG_JACK_DETECT,
index a3fb411796364a683d554b6278ba9bda6b942326..886924934aa5c7db067f352aafc4113d5ab97c06 100644 (file)
@@ -2093,6 +2093,7 @@ MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
 #ifdef CONFIG_ACPI
 static struct acpi_device_id rt5640_acpi_match[] = {
        { "INT33CA", 0 },
+       { "10EC5640", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
index 06edb396e733f1ad2ef26698a41b4eb1fdc18ea6..2735361a4c3cfc5fbc652ee10d62ec2728626184 100644 (file)
@@ -187,42 +187,42 @@ static const unsigned int sta32x_limiter_drc_release_tlv[] = {
        13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
 };
 
-static const struct soc_enum sta32x_drc_ac_enum =
-       SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
-                       2, sta32x_drc_ac);
-static const struct soc_enum sta32x_auto_eq_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
-                       3, sta32x_auto_eq_mode);
-static const struct soc_enum sta32x_auto_gc_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
-                       4, sta32x_auto_gc_mode);
-static const struct soc_enum sta32x_auto_xo_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
-                       16, sta32x_auto_xo_mode);
-static const struct soc_enum sta32x_preset_eq_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
-                       32, sta32x_preset_eq_mode);
-static const struct soc_enum sta32x_limiter_ch1_enum =
-       SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
-                       3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch2_enum =
-       SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
-                       3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch3_enum =
-       SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
-                       3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter1_attack_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
-                       16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter2_attack_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
-                       16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter1_release_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
-                       16, sta32x_limiter_release_rate);
-static const struct soc_enum sta32x_limiter2_release_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
-                       16, sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum,
+                           STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
+                           sta32x_drc_ac);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum,
+                           STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
+                           sta32x_auto_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum,
+                           STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
+                           sta32x_auto_gc_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum,
+                           STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
+                           sta32x_auto_xo_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum,
+                           STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
+                           sta32x_preset_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum,
+                           STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
+                           sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum,
+                           STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
+                           sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum,
+                           STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
+                           sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum,
+                           STA32X_L1AR, STA32X_LxA_SHIFT,
+                           sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum,
+                           STA32X_L2AR, STA32X_LxA_SHIFT,
+                           sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum,
+                           STA32X_L1AR, STA32X_LxR_SHIFT,
+                           sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum,
+                           STA32X_L2AR, STA32X_LxR_SHIFT,
+                           sta32x_limiter_release_rate);
 
 /* byte array controls for setting biquad, mixer, scaling coefficients;
  * for biquads all five coefficients need to be set in one go,
@@ -331,7 +331,7 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
 
 static int sta32x_cache_sync(struct snd_soc_codec *codec)
 {
-       struct sta32x_priv *sta32x = codec->control_data;
+       struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
        unsigned int mute;
        int rc;
 
@@ -434,7 +434,7 @@ SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0,
 SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
 SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
 SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
-SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum),
 
 /* depending on mode, the attack/release thresholds have
  * two different enum definitions; provide both
index 48dc7d2fee36fc07c236f6e9a09ea74cdb38d824..6d684d934f4de1e2b2c43dfc18d5659ada570cf1 100644 (file)
@@ -117,19 +117,23 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
 static const char *wm8400_digital_sidetone[] =
        {"None", "Left ADC", "Right ADC", "Reserved"};
 
-static const struct soc_enum wm8400_left_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
-               WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum,
+                           WM8400_DIGITAL_SIDE_TONE,
+                           WM8400_ADC_TO_DACL_SHIFT,
+                           wm8400_digital_sidetone);
 
-static const struct soc_enum wm8400_right_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
-               WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum,
+                           WM8400_DIGITAL_SIDE_TONE,
+                           WM8400_ADC_TO_DACR_SHIFT,
+                           wm8400_digital_sidetone);
 
 static const char *wm8400_adcmode[] =
        {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
 
-static const struct soc_enum wm8400_right_adcmode_enum =
-SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum,
+                           WM8400_ADC_CTRL,
+                           WM8400_ADC_HPF_CUT_SHIFT,
+                           wm8400_adcmode);
 
 static const struct snd_kcontrol_new wm8400_snd_controls[] = {
 /* INMIXL */
@@ -422,9 +426,10 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
 static const char *wm8400_ainlmux[] =
        {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
 
-static const struct soc_enum wm8400_ainlmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT,
-       ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum,
+                           WM8400_INPUT_MIXER1,
+                           WM8400_AINLMODE_SHIFT,
+                           wm8400_ainlmux);
 
 static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls =
 SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
@@ -435,9 +440,10 @@ SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
 static const char *wm8400_ainrmux[] =
        {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
 
-static const struct soc_enum wm8400_ainrmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT,
-       ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum,
+                           WM8400_INPUT_MIXER1,
+                           WM8400_AINRMODE_SHIFT,
+                           wm8400_ainrmux);
 
 static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls =
 SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum);
index 89a18d82f303e168f874a418840a9d33a4923910..5bce2101348514aa6508dc9dac7f895d176ae0d9 100644 (file)
@@ -196,8 +196,8 @@ static const char *ain_text[] = {
        "AIN5", "AIN6", "AIN7", "AIN8"
 };
 
-static const struct soc_enum ain_enum =
-       SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text);
+static SOC_ENUM_DOUBLE_DECL(ain_enum,
+                           WM8770_ADCMUX, 0, 4, ain_text);
 
 static const struct snd_kcontrol_new ain_mux =
        SOC_DAPM_ENUM("Capture Mux", ain_enum);
index e98bc7038a086b39231ecbb5196fb7a40fc92d1e..43c2201cb90131ebdb66e2f10326f4c904700011 100644 (file)
@@ -304,53 +304,53 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
 
 static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
 
-static const struct soc_enum mic_bias_level =
-SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
+static SOC_ENUM_SINGLE_DECL(mic_bias_level,
+                           WM8900_REG_INCTL, 8, mic_bias_level_txt);
 
 static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
 
-static const struct soc_enum dac_mute_rate =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
+static SOC_ENUM_SINGLE_DECL(dac_mute_rate,
+                           WM8900_REG_DACCTRL, 7, dac_mute_rate_txt);
 
 static const char *dac_deemphasis_txt[] = {
        "Disabled", "32kHz", "44.1kHz", "48kHz"
 };
 
-static const struct soc_enum dac_deemphasis =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
+static SOC_ENUM_SINGLE_DECL(dac_deemphasis,
+                           WM8900_REG_DACCTRL, 4, dac_deemphasis_txt);
 
 static const char *adc_hpf_cut_txt[] = {
        "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
 };
 
-static const struct soc_enum adc_hpf_cut =
-SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
+static SOC_ENUM_SINGLE_DECL(adc_hpf_cut,
+                           WM8900_REG_ADCCTRL, 5, adc_hpf_cut_txt);
 
 static const char *lr_txt[] = {
        "Left", "Right"
 };
 
-static const struct soc_enum aifl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifl_src,
+                           WM8900_REG_AUDIO1, 15, lr_txt);
 
-static const struct soc_enum aifr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifr_src,
+                           WM8900_REG_AUDIO1, 14, lr_txt);
 
-static const struct soc_enum dacl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_src,
+                           WM8900_REG_AUDIO2, 15, lr_txt);
 
-static const struct soc_enum dacr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_src,
+                           WM8900_REG_AUDIO2, 14, lr_txt);
 
 static const char *sidetone_txt[] = {
        "Disabled", "Left ADC", "Right ADC"
 };
 
-static const struct soc_enum dacl_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_sidetone,
+                           WM8900_REG_SIDETONE, 2, sidetone_txt);
 
-static const struct soc_enum dacr_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_sidetone,
+                           WM8900_REG_SIDETONE, 0, sidetone_txt);
 
 static const struct snd_kcontrol_new wm8900_snd_controls[] = {
 SOC_ENUM("Mic Bias Level", mic_bias_level),
@@ -496,8 +496,8 @@ SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
 
 static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" };
 
-static const struct soc_enum wm8900_lineout2_lp_mux =
-SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux);
+static SOC_ENUM_SINGLE_DECL(wm8900_lineout2_lp_mux,
+                           WM8900_REG_LOUTMIXCTL1, 1, wm8900_lp_mux);
 
 static const struct snd_kcontrol_new wm8900_lineout2_lp =
 SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
index b7488f190d2bc9d5b86da537a560fc6be9f6ca0a..d4248e00160e35a0bede71fcfbd7db785d49de89 100644 (file)
@@ -153,7 +153,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
 
                        data32 &= 0xffffff;
 
-                       wm8994_bulk_write(codec->control_data,
+                       wm8994_bulk_write(wm8994->wm8994,
                                          data32 & 0xffffff,
                                          block_len / 2,
                                          (void *)(data + 8));
index 433d59a0f3efa025598cf5c63f42640120893f90..2ee23a39622c14f2cdbc072cdcdb496e8291e9c0 100644 (file)
@@ -1562,7 +1562,6 @@ static int wm8993_remove(struct snd_soc_codec *codec)
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 
        wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
        return 0;
 }
 
index b9be9cbc460391d4530e970e3c77a0521109c2a2..adb72063d44ef6a0a5c9da1e2a53bd0d16a67825 100644 (file)
@@ -265,21 +265,21 @@ static const char *sidetone_hpf_text[] = {
        "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz"
 };
 
-static const struct soc_enum sidetone_hpf =
-       SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text);
+static SOC_ENUM_SINGLE_DECL(sidetone_hpf,
+                           WM8994_SIDETONE, 7, sidetone_hpf_text);
 
 static const char *adc_hpf_text[] = {
        "HiFi", "Voice 1", "Voice 2", "Voice 3"
 };
 
-static const struct soc_enum aif1adc1_hpf =
-       SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf,
+                           WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text);
 
-static const struct soc_enum aif1adc2_hpf =
-       SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf,
+                           WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text);
 
-static const struct soc_enum aif2adc_hpf =
-       SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_hpf,
+                           WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text);
 
 static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0);
 static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
@@ -501,39 +501,39 @@ static const char *aif_chan_src_text[] = {
        "Left", "Right"
 };
 
-static const struct soc_enum aif1adcl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcl_src,
+                           WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text);
 
-static const struct soc_enum aif1adcr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcr_src,
+                           WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text);
 
-static const struct soc_enum aif2adcl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcl_src,
+                           WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text);
 
-static const struct soc_enum aif2adcr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcr_src,
+                           WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text);
 
-static const struct soc_enum aif1dacl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacl_src,
+                           WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text);
 
-static const struct soc_enum aif1dacr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacr_src,
+                           WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text);
 
-static const struct soc_enum aif2dacl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src,
+                           WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text);
 
-static const struct soc_enum aif2dacr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src,
+                           WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text);
 
 static const char *osr_text[] = {
        "Low Power", "High Performance",
 };
 
-static const struct soc_enum dac_osr =
-       SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(dac_osr,
+                           WM8994_OVERSAMPLING, 0, osr_text);
 
-static const struct soc_enum adc_osr =
-       SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(adc_osr,
+                           WM8994_OVERSAMPLING, 1, osr_text);
 
 static const struct snd_kcontrol_new wm8994_snd_controls[] = {
 SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
@@ -690,17 +690,20 @@ static const char *wm8958_ng_text[] = {
        "30ms", "125ms", "250ms", "500ms",
 };
 
-static const struct soc_enum wm8958_aif1dac1_ng_hold =
-       SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
-                       WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold,
+                           WM8958_AIF1_DAC1_NOISE_GATE,
+                           WM8958_AIF1DAC1_NG_THR_SHIFT,
+                           wm8958_ng_text);
 
-static const struct soc_enum wm8958_aif1dac2_ng_hold =
-       SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
-                       WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold,
+                           WM8958_AIF1_DAC2_NOISE_GATE,
+                           WM8958_AIF1DAC2_NG_THR_SHIFT,
+                           wm8958_ng_text);
 
-static const struct soc_enum wm8958_aif2dac_ng_hold =
-       SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
-                       WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold,
+                           WM8958_AIF2_DAC_NOISE_GATE,
+                           WM8958_AIF2DAC_NG_THR_SHIFT,
+                           wm8958_ng_text);
 
 static const struct snd_kcontrol_new wm8958_snd_controls[] = {
 SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
@@ -1341,8 +1344,8 @@ static const char *adc_mux_text[] = {
        "DMIC",
 };
 
-static const struct soc_enum adc_enum =
-       SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(adc_enum,
+                           0, 0, adc_mux_text);
 
 static const struct snd_kcontrol_new adcl_mux =
        SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
@@ -1478,14 +1481,14 @@ static const char *sidetone_text[] = {
        "ADC/DMIC1", "DMIC2",
 };
 
-static const struct soc_enum sidetone1_enum =
-       SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone1_enum,
+                           WM8994_SIDETONE, 0, sidetone_text);
 
 static const struct snd_kcontrol_new sidetone1_mux =
        SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum);
 
-static const struct soc_enum sidetone2_enum =
-       SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone2_enum,
+                           WM8994_SIDETONE, 1, sidetone_text);
 
 static const struct snd_kcontrol_new sidetone2_mux =
        SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum);
@@ -1498,22 +1501,24 @@ static const char *loopback_text[] = {
        "None", "ADCDAT",
 };
 
-static const struct soc_enum aif1_loopback_enum =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2,
-                       loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum,
+                           WM8994_AIF1_CONTROL_2,
+                           WM8994_AIF1_LOOPBACK_SHIFT,
+                           loopback_text);
 
 static const struct snd_kcontrol_new aif1_loopback =
        SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum);
 
-static const struct soc_enum aif2_loopback_enum =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2,
-                       loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum,
+                           WM8994_AIF2_CONTROL_2,
+                           WM8994_AIF2_LOOPBACK_SHIFT,
+                           loopback_text);
 
 static const struct snd_kcontrol_new aif2_loopback =
        SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum);
 
-static const struct soc_enum aif1dac_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text);
+static SOC_ENUM_SINGLE_DECL(aif1dac_enum,
+                           WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text);
 
 static const struct snd_kcontrol_new aif1dac_mux =
        SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum);
@@ -1522,8 +1527,8 @@ static const char *aif2dac_text[] = {
        "AIF2DACDAT", "AIF3DACDAT",
 };
 
-static const struct soc_enum aif2dac_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text);
+static SOC_ENUM_SINGLE_DECL(aif2dac_enum,
+                           WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text);
 
 static const struct snd_kcontrol_new aif2dac_mux =
        SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum);
@@ -1532,8 +1537,8 @@ static const char *aif2adc_text[] = {
        "AIF2ADCDAT", "AIF3DACDAT",
 };
 
-static const struct soc_enum aif2adc_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_enum,
+                           WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text);
 
 static const struct snd_kcontrol_new aif2adc_mux =
        SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum);
@@ -1542,14 +1547,14 @@ static const char *aif3adc_text[] = {
        "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM",
 };
 
-static const struct soc_enum wm8994_aif3adc_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum,
+                           WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
 
 static const struct snd_kcontrol_new wm8994_aif3adc_mux =
        SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum);
 
-static const struct soc_enum wm8958_aif3adc_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum,
+                           WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
 
 static const struct snd_kcontrol_new wm8958_aif3adc_mux =
        SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum);
@@ -1558,8 +1563,8 @@ static const char *mono_pcm_out_text[] = {
        "None", "AIF2ADCL", "AIF2ADCR",
 };
 
-static const struct soc_enum mono_pcm_out_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text);
+static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum,
+                           WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text);
 
 static const struct snd_kcontrol_new mono_pcm_out_mux =
        SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum);
@@ -1569,14 +1574,14 @@ static const char *aif2dac_src_text[] = {
 };
 
 /* Note that these two control shouldn't be simultaneously switched to AIF3 */
-static const struct soc_enum aif2dacl_src_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum,
+                           WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text);
 
 static const struct snd_kcontrol_new aif2dacl_src_mux =
        SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum);
 
-static const struct soc_enum aif2dacr_src_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum,
+                           WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text);
 
 static const struct snd_kcontrol_new aif2dacr_src_mux =
        SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum);
index 70ff3772079f2186cdf2967c1c050ff95f37350b..5e3bc3c6801a6bbf9512731f6cd094b2eb41511f 100644 (file)
@@ -399,6 +399,7 @@ static struct platform_driver davinci_evm_driver = {
        .driver         = {
                .name   = "davinci_evm",
                .owner  = THIS_MODULE,
+               .pm     = &snd_soc_pm_ops,
                .of_match_table = of_match_ptr(davinci_evm_dt_ids),
        },
 };
index b7858bfa0295357bc5d3ca6d1328932595167b9e..670afa29e30d0d5b97f7c60601d1e40793b5b499 100644 (file)
@@ -263,7 +263,9 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                         unsigned int fmt)
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret = 0;
 
+       pm_runtime_get_sync(mcasp->dev);
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
        case SND_SOC_DAIFMT_AC97:
@@ -317,7 +319,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                break;
 
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -354,10 +357,12 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                break;
 
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               break;
        }
-
-       return 0;
+out:
+       pm_runtime_put_sync(mcasp->dev);
+       return ret;
 }
 
 static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
@@ -448,7 +453,7 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
        return 0;
 }
 
-static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
+static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
                                    int channels)
 {
        int i;
@@ -524,12 +529,18 @@ static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
        return 0;
 }
 
-static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
+static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
 {
        int i, active_slots;
        u32 mask = 0;
        u32 busel = 0;
 
+       if ((mcasp->tdm_slots < 2) || (mcasp->tdm_slots > 32)) {
+               dev_err(mcasp->dev, "tdm slot %d not supported\n",
+                       mcasp->tdm_slots);
+               return -EINVAL;
+       }
+
        active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots;
        for (i = 0; i < active_slots; i++)
                mask |= (1 << i);
@@ -539,35 +550,21 @@ static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
        if (!mcasp->dat_port)
                busel = TXSEL;
 
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* bit stream is MSB first  with no delay */
-               /* DSP_B mode */
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
-               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
-
-               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
-                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
-                                      FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
-               else
-                       printk(KERN_ERR "playback tdm slot %d not supported\n",
-                               mcasp->tdm_slots);
-       } else {
-               /* bit stream is MSB first with no delay */
-               /* DSP_B mode */
-               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
-
-               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
-                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
-                                      FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
-               else
-                       printk(KERN_ERR "capture tdm slot %d not supported\n",
-                               mcasp->tdm_slots);
-       }
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
+       mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
+                      FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
+       mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
+                      FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
+
+       return 0;
 }
 
 /* S/PDIF */
-static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
+static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp)
 {
        /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
           and LSB first */
@@ -589,6 +586,8 @@ static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
 
        /* Enable the DIT */
        mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+
+       return 0;
 }
 
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
@@ -605,13 +604,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        u8 slots = mcasp->tdm_slots;
        u8 active_serializers;
        int channels;
+       int ret;
        struct snd_interval *pcm_channels = hw_param_interval(params,
                                        SNDRV_PCM_HW_PARAM_CHANNELS);
        channels = pcm_channels->min;
 
        active_serializers = (channels + slots - 1) / slots;
 
-       if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL)
+       if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL)
                return -EINVAL;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                fifo_level = mcasp->txnumevt * active_serializers;
@@ -619,9 +619,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                fifo_level = mcasp->rxnumevt * active_serializers;
 
        if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
-               davinci_hw_dit_param(mcasp);
+               ret = mcasp_dit_hw_param(mcasp);
        else
-               davinci_hw_param(mcasp, substream->stream);
+               ret = mcasp_i2s_hw_param(mcasp, substream->stream);
+
+       if (ret)
+               return ret;
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_U8:
@@ -678,19 +681,9 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ret = pm_runtime_get_sync(mcasp->dev);
-               if (IS_ERR_VALUE(ret))
-                       dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n");
                davinci_mcasp_start(mcasp, substream->stream);
                break;
-
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               davinci_mcasp_stop(mcasp, substream->stream);
-               ret = pm_runtime_put_sync(mcasp->dev);
-               if (IS_ERR_VALUE(ret))
-                       dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n");
-               break;
-
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                davinci_mcasp_stop(mcasp, substream->stream);
index d0c72ed261e74c37f9d2b7cde738b34aab303ad4..c84026c991347f99014dad7df74c57731b789e24 100644 (file)
@@ -326,7 +326,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
        regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
                           ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
        regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
-                          ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask));
+                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
 
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
                           ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
@@ -334,7 +334,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
                           ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
-                          ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask));
+                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
 
        esai_priv->slot_width = slot_width;
 
index 9c9f957fcae179c2d3d5525161fdbb0a0e338204..75e14033e8d8f0a7da6b1db6387d543c5a9a1acc 100644 (file)
 #define ESAI_xSMB_xS_SHIFT     0
 #define ESAI_xSMB_xS_WIDTH     16
 #define ESAI_xSMB_xS_MASK      (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT)
-#define ESAI_xSMB_xS(v)                (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK)
+#define ESAI_xSMB_xS(v)                (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMB_xS_MASK)
 
 /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */
 #define ESAI_PRRC_PDC_SHIFT    0
index 79cee782dbbf9184264e69383b6d5a5ff1ba0fd7..a2fd7321b5a9a1bbd321f756af14fd9f071a372f 100644 (file)
@@ -160,7 +160,6 @@ static struct platform_driver imx_mc13783_audio_driver = {
        .driver = {
                .name = "imx_mc13783",
                .owner = THIS_MODULE,
-               .pm = &snd_soc_pm_ops,
        },
        .probe = imx_mc13783_probe,
        .remove = imx_mc13783_remove
index f2beae78969f6dd8e03125f92e3f288a8776f411..1cb22dd034eb63e98ac7e60e6d3ce5f719227db4 100644 (file)
@@ -33,8 +33,7 @@ struct imx_sgtl5000_data {
 
 static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct imx_sgtl5000_data *data = container_of(rtd->card,
-                                       struct imx_sgtl5000_data, card);
+       struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(rtd->card);
        struct device *dev = rtd->card->dev;
        int ret;
 
@@ -159,13 +158,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
        data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
        data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
 
+       platform_set_drvdata(pdev, &data->card);
+       snd_soc_card_set_drvdata(&data->card, data);
+
        ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
                goto fail;
        }
 
-       platform_set_drvdata(pdev, data);
        of_node_put(ssi_np);
        of_node_put(codec_np);
 
@@ -184,7 +185,8 @@ fail:
 
 static int imx_sgtl5000_remove(struct platform_device *pdev)
 {
-       struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card);
 
        clk_put(data->codec_clk);
 
index 3fd76bc391de19a2431dd320d0abfbdcd9616cf5..3a3d17ce6ba40feea5dc6582693d7c1ee846ef13 100644 (file)
@@ -71,7 +71,7 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
 {
        struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
        struct imx_priv *priv = &card_priv;
-       struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
+       struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
        struct device *dev = &priv->pdev->dev;
        unsigned int pll_out;
        int ret;
@@ -137,7 +137,7 @@ static int imx_wm8962_late_probe(struct snd_soc_card *card)
 {
        struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
        struct imx_priv *priv = &card_priv;
-       struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
+       struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
        struct device *dev = &priv->pdev->dev;
        int ret;
 
@@ -264,13 +264,15 @@ static int imx_wm8962_probe(struct platform_device *pdev)
        data->card.late_probe = imx_wm8962_late_probe;
        data->card.set_bias_level = imx_wm8962_set_bias_level;
 
+       platform_set_drvdata(pdev, &data->card);
+       snd_soc_card_set_drvdata(&data->card, data);
+
        ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
                goto clk_fail;
        }
 
-       platform_set_drvdata(pdev, data);
        of_node_put(ssi_np);
        of_node_put(codec_np);
 
@@ -289,7 +291,8 @@ fail:
 
 static int imx_wm8962_remove(struct platform_device *pdev)
 {
-       struct imx_wm8962_data *data = platform_get_drvdata(pdev);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
 
        if (!IS_ERR(data->codec_clk))
                clk_disable_unprepare(data->codec_clk);
index 454f41cfc82847e98a6297b2db5822db35d717a6..3507574003913b5023f66853a50bec809d6187bf 100644 (file)
@@ -59,7 +59,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
        select SND_SOC_WM8750
        select SND_S3C2412_SOC_I2S
        help
-         Sat Y if you want to add support for SoC audio on the Jive.
+         Say Y if you want to add support for SoC audio on the Jive.
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
        tristate "SoC I2S Audio support for WM8580 on SMDK"
@@ -145,11 +145,11 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380
 
 config SND_SOC_SAMSUNG_SMDK_WM9713
        tristate "SoC AC97 Audio support for SMDK with WM9713"
-       depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 || MACH_SMDKV310 || MACH_SMDKC210)
+       depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
        select SND_SOC_WM9713
        select SND_SAMSUNG_AC97
        help
-         Sat Y if you want to add support for SoC audio on the SMDK.
+         Say Y if you want to add support for SoC audio on the SMDK.
 
 config SND_SOC_SMARTQ
        tristate "SoC I2S Audio support for SmartQ board"
index dc8ff13187f7ca91ef960312f48eac732c44d938..b9dc6acbba8c55661eb0cf423a02fb9b7dda1c87 100644 (file)
@@ -1218,7 +1218,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                        ret = regulator_allow_bypass(w->regulator, false);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "ASoC: Failed to bypass %s: %d\n",
+                                        "ASoC: Failed to unbypass %s: %d\n",
                                         w->name, ret);
                }
 
@@ -1228,7 +1228,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                        ret = regulator_allow_bypass(w->regulator, true);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "ASoC: Failed to unbypass %s: %d\n",
+                                        "ASoC: Failed to bypass %s: %d\n",
                                         w->name, ret);
                }
 
@@ -3210,15 +3210,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        const char *pin = (const char *)kcontrol->private_value;
 
-       mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
        if (ucontrol->value.integer.value[0])
                snd_soc_dapm_enable_pin(&card->dapm, pin);
        else
                snd_soc_dapm_disable_pin(&card->dapm, pin);
 
-       mutex_unlock(&card->dapm_mutex);
-
        snd_soc_dapm_sync(&card->dapm);
        return 0;
 }
@@ -3248,7 +3244,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                        ret = regulator_allow_bypass(w->regulator, true);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "ASoC: Failed to unbypass %s: %d\n",
+                                        "ASoC: Failed to bypass %s: %d\n",
                                         w->name, ret);
                }
                break;
@@ -3766,6 +3762,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
        mutex_unlock(&card->dapm_mutex);
 }
 
+/**
+ * snd_soc_dapm_enable_pin_unlocked - enable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Enables input/output pin and its parents or children widgets iff there is
+ * a valid audio route and active audio stream.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                  const char *pin)
+{
+       return snd_soc_dapm_set_pin(dapm, pin, 1);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
+
 /**
  * snd_soc_dapm_enable_pin - enable pin.
  * @dapm: DAPM context
@@ -3773,17 +3789,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
  *
  * Enables input/output pin and its parents or children widgets iff there is
  * a valid audio route and active audio stream.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
 {
-       return snd_soc_dapm_set_pin(dapm, pin, 1);
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_set_pin(dapm, pin, 1);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
 
 /**
- * snd_soc_dapm_force_enable_pin - force a pin to be enabled
+ * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
  * @dapm: DAPM context
  * @pin: pin name
  *
@@ -3791,11 +3816,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
  * intended for use with microphone bias supplies used in microphone
  * jack detection.
  *
+ * Requires external locking.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
-int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
-                                 const char *pin)
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                        const char *pin)
 {
        struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
 
@@ -3811,24 +3838,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
+
+/**
+ * snd_soc_dapm_force_enable_pin - force a pin to be enabled
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Enables input/output pin regardless of any other state.  This is
+ * intended for use with microphone bias supplies used in microphone
+ * jack detection.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
+                                 const char *pin)
+{
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
 
+/**
+ * snd_soc_dapm_disable_pin_unlocked - disable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Disables input/output pin and its parents or children widgets.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                   const char *pin)
+{
+       return snd_soc_dapm_set_pin(dapm, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
+
 /**
  * snd_soc_dapm_disable_pin - disable pin.
  * @dapm: DAPM context
  * @pin: pin name
  *
  * Disables input/output pin and its parents or children widgets.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
                             const char *pin)
 {
-       return snd_soc_dapm_set_pin(dapm, pin, 0);
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_set_pin(dapm, pin, 0);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
 
+/**
+ * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Marks the specified pin as being not connected, disabling it along
+ * any parent or child widgets.  At present this is identical to
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
+ * additional things such as disabling controls which only affect
+ * paths through the pin.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                              const char *pin)
+{
+       return snd_soc_dapm_set_pin(dapm, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
+
 /**
  * snd_soc_dapm_nc_pin - permanently disable pin.
  * @dapm: DAPM context
@@ -3845,7 +3950,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
  */
 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
 {
-       return snd_soc_dapm_set_pin(dapm, pin, 0);
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_set_pin(dapm, pin, 0);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
 
index e0305a1485680b18cbc85ba33a506bda799f47c1..9edd68db9f482e618e4e245a40dfbd0c94711e5d 100644 (file)
@@ -183,14 +183,16 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
+
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        drvdata->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(drvdata->base))
                return PTR_ERR(drvdata->base);
 
-       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
        platform_set_drvdata(pdev, drvdata);
        drvdata->physbase = r->start;
        if (sizeof(drvdata->physbase) > sizeof(r->start) &&
index 32af6b741ef5a8aff8581f90b0c5d583d151a6ee..d1d72ff50347a3118c2e90d5452457b8948ad0d6 100644 (file)
@@ -328,6 +328,11 @@ static struct usbmix_name_map gamecom780_map[] = {
        {}
 };
 
+static const struct usbmix_name_map kef_x300a_map[] = {
+       { 10, NULL }, /* firmware locks up (?) when we try to access this FU */
+       { 0 }
+};
+
 /*
  * Control map entries
  */
@@ -419,6 +424,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x200c, 0x1018),
                .map = ebox44_map,
        },
+       {
+               .id = USB_ID(0x27ac, 0x1000),
+               .map = kef_x300a_map,
+       },
        { 0 } /* terminator */
 };
 
index 3c53ec268fbc52a5298f390a83e3802eecd156a6..02f985f3a396916ff60e4fcd8123bc109fa0dab4 100644 (file)
@@ -113,14 +113,16 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati
        if (!he)
                return -ENOMEM;
 
-       err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
-       if (err)
-               goto out;
+       if (ui__has_annotation()) {
+               err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+               if (err)
+                       goto out;
 
-       mx = he->mem_info;
-       err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
-       if (err)
-               goto out;
+               mx = he->mem_info;
+               err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
+               if (err)
+                       goto out;
+       }
 
        evsel->hists.stats.total_period += cost;
        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
@@ -164,14 +166,18 @@ static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_loc
                he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
                                        1, 1, 0);
                if (he) {
-                       bx = he->branch_info;
-                       err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
-                       if (err)
-                               goto out;
-
-                       err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
-                       if (err)
-                               goto out;
+                       if (ui__has_annotation()) {
+                               bx = he->branch_info;
+                               err = addr_map_symbol__inc_samples(&bx->from,
+                                                                  evsel->idx);
+                               if (err)
+                                       goto out;
+
+                               err = addr_map_symbol__inc_samples(&bx->to,
+                                                                  evsel->idx);
+                               if (err)
+                                       goto out;
+                       }
 
                        evsel->hists.stats.total_period += 1;
                        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
@@ -205,7 +211,9 @@ static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evs
        if (err)
                goto out;
 
-       err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+       if (ui__has_annotation())
+               err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+
        evsel->hists.stats.total_period += sample->period;
        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
 out:
index 76cd510d34d023bf3c580ec2b3e2e217d8831cba..5f989a7d8bc2166e30d6bcbef710015f019ab252 100644 (file)
@@ -176,7 +176,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
 {
        struct annotation *notes;
        struct symbol *sym;
-       int err;
+       int err = 0;
 
        if (he == NULL || he->ms.sym == NULL ||
            ((top->sym_filter_entry == NULL ||
@@ -190,7 +190,9 @@ static void perf_top__record_precise_ip(struct perf_top *top,
                return;
 
        ip = he->ms.map->map_ip(he->ms.map, ip);
-       err = hist_entry__inc_addr_samples(he, counter, ip);
+
+       if (ui__has_annotation())
+               err = hist_entry__inc_addr_samples(he, counter, ip);
 
        pthread_mutex_unlock(&notes->lock);
 
index 896f27047ed6178fd6aed5566863fb4f4c251e84..6aa6fb6f7bd938b7ed7ccc2e7c07511b03a6cee6 100644 (file)
 # define MADV_UNMERGEABLE      13
 #endif
 
+#ifndef EFD_SEMAPHORE
+# define EFD_SEMAPHORE         1
+#endif
+
 struct tp_field {
        int offset;
        union {
@@ -279,6 +283,11 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
 
 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches as soon as the ioctl beautifier
+ *       gets rewritten to support all arches.
+ */
 static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
                                                 struct syscall_arg *arg)
 {
@@ -286,6 +295,7 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
 }
 
 #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
                                        struct syscall_arg *arg);
@@ -839,6 +849,10 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
 
 #define SCA_SIGNUM syscall_arg__scnprintf_signum
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches.
+ */
 #define TCGETS         0x5401
 
 static const char *tioctls[] = {
@@ -860,6 +874,7 @@ static const char *tioctls[] = {
 };
 
 static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 #define STRARRAY(arg, name, array) \
          .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
@@ -941,9 +956,16 @@ static struct syscall_fmt {
        { .name     = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
        { .name     = "ioctl",      .errmsg = true,
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches.
+ */
                             [1] = SCA_STRHEXARRAY, /* cmd */
                             [2] = SCA_HEX, /* arg */ },
          .arg_parm      = { [1] = &strarray__tioctls, /* cmd */ }, },
+#else
+                            [2] = SCA_HEX, /* arg */ }, },
+#endif
        { .name     = "kill",       .errmsg = true,
          .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "linkat",     .errmsg = true,
index c48d44958172b7dd8f75634ece4d909ae2d5b15b..0331ea2701a380c536facf82b8306729f23d9de3 100644 (file)
@@ -478,7 +478,7 @@ else
 endif
 
 ifeq ($(feature-libbfd), 1)
-  EXTLIBS += -lbfd
+  EXTLIBS += -lbfd -lz -liberty
 endif
 
 ifdef NO_DEMANGLE
index 12e551346fa6414d7b85c69fcee0b224283fdc0c..523b7bc1055321051d62562f1f490165ea2872b5 100644 (file)
@@ -121,7 +121,7 @@ test-libpython-version.bin:
        $(BUILD) $(FLAGS_PYTHON_EMBED)
 
 test-libbfd.bin:
-       $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
+       $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
 
 test-liberty.bin:
        $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
index 469eb679fb9d09d9e96e8687cc2051fa44f86565..3aa555ff9d89e5d7ede4c6af067170197b9ce0e8 100644 (file)
@@ -8,6 +8,8 @@
  */
 
 #include "util.h"
+#include "ui/ui.h"
+#include "sort.h"
 #include "build-id.h"
 #include "color.h"
 #include "cache.h"
@@ -489,7 +491,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 {
        struct annotation *notes;
 
-       if (sym == NULL || use_browser != 1 || !sort__has_sym)
+       if (sym == NULL)
                return 0;
 
        notes = symbol__annotation(sym);
@@ -1399,3 +1401,8 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize)
 {
        return symbol__annotate(he->ms.sym, he->ms.map, privsize);
 }
+
+bool ui__has_annotation(void)
+{
+       return use_browser == 1 && sort__has_sym;
+}
index b2aef59d6bb29741dff0dbee40fa0c1d04f1cf65..56ad4f5287dec04bf8e94fe15c814b6abc8b42ee 100644 (file)
@@ -151,6 +151,8 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
 void disasm__purge(struct list_head *head);
 
+bool ui__has_annotation(void);
+
 int symbol__tty_annotate(struct symbol *sym, struct map *map,
                         struct perf_evsel *evsel, bool print_lines,
                         bool full_paths, int min_pcnt, int max_lines);
index 45cf10a562bd7958c9edd160ab20a0725ecb0385..dadfa7e54287b9aaa46da7227d4b0f275717ddb2 100644 (file)
@@ -87,13 +87,15 @@ static __always_inline unsigned long __ffs(unsigned long word)
        return num;
 }
 
+typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
+
 /*
  * Find the first set bit in a memory region.
  */
 static inline unsigned long
 find_first_bit(const unsigned long *addr, unsigned long size)
 {
-       const unsigned long *p = addr;
+       long_alias_t *p = (long_alias_t *) addr;
        unsigned long result = 0;
        unsigned long tmp;
 
index d248fca6d7ed7302c77d5500a79c853d3073ea07..1e15df10a88c2c1ff7b62dbfbcc05f39ffbe4cd1 100644 (file)
@@ -1091,12 +1091,12 @@ int is_valid_tracepoint(const char *event_string)
 static bool is_event_supported(u8 type, unsigned config)
 {
        bool ret = true;
+       int open_return;
        struct perf_evsel *evsel;
        struct perf_event_attr attr = {
                .type = type,
                .config = config,
                .disabled = 1,
-               .exclude_kernel = 1,
        };
        struct {
                struct thread_map map;
@@ -1108,7 +1108,20 @@ static bool is_event_supported(u8 type, unsigned config)
 
        evsel = perf_evsel__new(&attr);
        if (evsel) {
-               ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
+               open_return = perf_evsel__open(evsel, NULL, &tmap.map);
+               ret = open_return >= 0;
+
+               if (open_return == -EACCES) {
+                       /*
+                        * This happens if the paranoid value
+                        * /proc/sys/kernel/perf_event_paranoid is set to 2
+                        * Re-run with exclude_kernel set; we don't do that
+                        * by default as some ARM machines do not support it.
+                        *
+                        */
+                       evsel->attr.exclude_kernel = 1;
+                       ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
+               }
                perf_evsel__delete(evsel);
        }
 
index a8a9b6cd93a8f080a968f1cd05e7f80bb0df0ca6..d8b048c20cdee51ac894b5394b15c70a1897c106 100644 (file)
@@ -336,8 +336,8 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
                return ret;
 
        for (i = 0; i < ntevs && ret >= 0; i++) {
+               /* point.address is the addres of point.symbol + point.offset */
                offset = tevs[i].point.address - stext;
-               offset += tevs[i].point.offset;
                tevs[i].point.offset = 0;
                zfree(&tevs[i].point.symbol);
                ret = e_snprintf(buf, 32, "0x%lx", offset);
index 0b39a48e5110a00dde5fa0408c725730ba5fe8ff..5da6ce74c676722ff13ae858c1bb579ba353edbf 100644 (file)
@@ -1008,6 +1008,12 @@ static int perf_session__process_user_event(struct perf_session *session, union
                if (err == 0)
                        perf_session__set_id_hdr_size(session);
                return err;
+       case PERF_RECORD_HEADER_EVENT_TYPE:
+               /*
+                * Depreceated, but we need to handle it for sake
+                * of old data files create in pipe mode.
+                */
+               return 0;
        case PERF_RECORD_HEADER_TRACING_DATA:
                /* setup for reading amidst mmap */
                lseek(fd, file_offset, SEEK_SET);
index a9d758a3b3719a0b8db5d7b5d239c7dea5ceb34e..e89afc097d8ad2d4b818f07e02321084110e6ddc 100644 (file)
@@ -1336,6 +1336,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
 
                        if (syms_ss && runtime_ss)
                                break;
+               } else {
+                       symsrc__destroy(ss);
                }
 
        }