aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-12-13 02:30:23 +0100
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-12-13 02:30:23 +0100
commit2ecd9abf516e5e4afc482eb0329f9304aed285b4 (patch)
treea2980c05f50df82d6d043e4e44ecaf2023220870
parent698f3e8de2f0104dc80402ea151aae73b946a2d9 (diff)
parenta04b065c010280ed1806c73cb234a2bf657a5ce9 (diff)
downloadkernel_samsung_smdk4412-2ecd9abf516e5e4afc482eb0329f9304aed285b4.zip
kernel_samsung_smdk4412-2ecd9abf516e5e4afc482eb0329f9304aed285b4.tar.gz
kernel_samsung_smdk4412-2ecd9abf516e5e4afc482eb0329f9304aed285b4.tar.bz2
Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_kernel_samsung_smdk4412 into replicant-6.0
-rw-r--r--Documentation/ABI/testing/sysfs-block-zram41
-rw-r--r--Documentation/blockdev/zram.txt119
-rw-r--r--Documentation/filesystems/proc.txt6
-rw-r--r--Documentation/sysctl/fs.txt23
-rw-r--r--Makefile4
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/configs/cyanogenmod_d710_defconfig4
-rw-r--r--arch/arm/configs/cyanogenmod_i777_defconfig87
-rw-r--r--arch/arm/configs/cyanogenmod_i9100_defconfig29
-rw-r--r--arch/arm/configs/cyanogenmod_i925_defconfig6
-rw-r--r--arch/arm/configs/cyanogenmod_i9300_defconfig58
-rw-r--r--[-rwxr-xr-x]arch/arm/configs/cyanogenmod_i9305_defconfig258
-rw-r--r--arch/arm/configs/cyanogenmod_n5100_defconfig223
-rw-r--r--arch/arm/configs/cyanogenmod_n5110_defconfig218
-rw-r--r--arch/arm/configs/cyanogenmod_n5120_defconfig310
-rw-r--r--arch/arm/configs/cyanogenmod_n7000_defconfig4
-rw-r--r--arch/arm/configs/cyanogenmod_n7100_defconfig8
-rw-r--r--arch/arm/configs/cyanogenmod_n8000_defconfig4
-rw-r--r--arch/arm/configs/cyanogenmod_n8013_defconfig4
-rwxr-xr-xarch/arm/configs/cyanogenmod_t0lte_defconfig6
-rwxr-xr-xarch/arm/configs/cyanogenmod_t0ltecdma_defconfig6
-rw-r--r--arch/arm/mach-exynos/board-m0-modems.c5
-rw-r--r--arch/arm/mach-exynos/board-trats.c72
-rw-r--r--arch/arm/mach-exynos/include/mach/busfreq_exynos4.h5
-rw-r--r--arch/arm/mach-exynos/mach-px.c72
-rw-r--r--arch/arm/mach-exynos/mach-smdk5210.c15
-rw-r--r--arch/arm/mach-exynos/mach-u1.c86
-rw-r--r--arch/arm/mach-exynos/reserve_mem-exynos4.c22
-rw-r--r--arch/arm/mach-exynos/sec_watchdog.c6
-rw-r--r--arch/arm/mvp/Kconfig24
-rw-r--r--arch/arm/mvp/Makefile3
-rw-r--r--arch/arm/mvp/commkm/COPYING341
-rw-r--r--arch/arm/mvp/commkm/Kbuild9
-rw-r--r--arch/arm/mvp/commkm/Makefile1
-rw-r--r--arch/arm/mvp/commkm/check_kconfig.c91
-rw-r--r--arch/arm/mvp/commkm/comm.c1457
-rw-r--r--arch/arm/mvp/commkm/comm.h171
-rw-r--r--arch/arm/mvp/commkm/comm_ev.h51
-rw-r--r--arch/arm/mvp/commkm/comm_ev_kernel.c136
-rw-r--r--arch/arm/mvp/commkm/comm_os.h150
-rw-r--r--arch/arm/mvp/commkm/comm_os_linux.c371
-rw-r--r--arch/arm/mvp/commkm/comm_os_linux.h699
-rw-r--r--arch/arm/mvp/commkm/comm_os_mod_linux.c105
-rw-r--r--arch/arm/mvp/commkm/comm_os_mod_ver.h38
-rw-r--r--arch/arm/mvp/commkm/comm_svc.c421
-rw-r--r--arch/arm/mvp/commkm/comm_svc.h71
-rw-r--r--arch/arm/mvp/commkm/comm_transp.h90
-rw-r--r--arch/arm/mvp/commkm/comm_transp_impl.h165
-rw-r--r--arch/arm/mvp/commkm/comm_transp_mvp.c944
-rw-r--r--arch/arm/mvp/commkm/fatalerror.h126
-rw-r--r--arch/arm/mvp/commkm/include_check.h18
-rw-r--r--arch/arm/mvp/commkm/mksck.h153
-rw-r--r--arch/arm/mvp/commkm/mksck_sockaddr.h50
-rw-r--r--arch/arm/mvp/commkm/mvp.h48
-rw-r--r--arch/arm/mvp/commkm/mvp_assert.h125
-rw-r--r--arch/arm/mvp/commkm/mvp_compiler.h56
-rw-r--r--arch/arm/mvp/commkm/mvp_compiler_gcc.h87
-rw-r--r--arch/arm/mvp/commkm/mvp_types.h94
-rw-r--r--arch/arm/mvp/commkm/mvpkm_comm_ev.h53
-rw-r--r--arch/arm/mvp/commkm/nottested.h54
-rw-r--r--arch/arm/mvp/commkm/platdefx.h67
-rw-r--r--arch/arm/mvp/commkm/qp.h332
-rw-r--r--arch/arm/mvp/commkm/utils.h172
-rw-r--r--arch/arm/mvp/commkm/vmid.h44
-rw-r--r--arch/arm/mvp/mvpkm/COPYING341
-rw-r--r--arch/arm/mvp/mvpkm/Kbuild32
-rw-r--r--arch/arm/mvp/mvpkm/Makefile1
-rw-r--r--arch/arm/mvp/mvpkm/actions.h57
-rw-r--r--arch/arm/mvp/mvpkm/arm_as_macros.h91
-rw-r--r--arch/arm/mvp/mvpkm/arm_defs.h54
-rw-r--r--arch/arm/mvp/mvpkm/arm_gcc_inline.h206
-rw-r--r--arch/arm/mvp/mvpkm/arm_inline.h179
-rw-r--r--arch/arm/mvp/mvpkm/arm_types.h42
-rw-r--r--arch/arm/mvp/mvpkm/atomic.h88
-rw-r--r--arch/arm/mvp/mvpkm/atomic_arm.h329
-rw-r--r--arch/arm/mvp/mvpkm/check_kconfig.c91
-rw-r--r--arch/arm/mvp/mvpkm/comm_os.h150
-rw-r--r--arch/arm/mvp/mvpkm/comm_os_linux.h699
-rw-r--r--arch/arm/mvp/mvpkm/comm_transp.h90
-rw-r--r--arch/arm/mvp/mvpkm/comm_transp_impl.h165
-rw-r--r--arch/arm/mvp/mvpkm/coproc_defs.h351
-rw-r--r--arch/arm/mvp/mvpkm/cpufreq_kernel.c308
-rw-r--r--arch/arm/mvp/mvpkm/cpufreq_kernel.h47
-rw-r--r--arch/arm/mvp/mvpkm/exc_defs.h67
-rw-r--r--arch/arm/mvp/mvpkm/exc_types.h53
-rw-r--r--arch/arm/mvp/mvpkm/exitstatus.h67
-rw-r--r--arch/arm/mvp/mvpkm/fatalerror.h126
-rw-r--r--arch/arm/mvp/mvpkm/include_check.h18
-rw-r--r--arch/arm/mvp/mvpkm/instr_defs.h426
-rw-r--r--arch/arm/mvp/mvpkm/lowmemkiller_variant.sh92
-rw-r--r--arch/arm/mvp/mvpkm/lpae_defs.h92
-rw-r--r--arch/arm/mvp/mvpkm/lpae_types.h124
-rw-r--r--arch/arm/mvp/mvpkm/mksck.h153
-rw-r--r--arch/arm/mvp/mvpkm/mksck_kernel.c2589
-rw-r--r--arch/arm/mvp/mvpkm/mksck_kernel.h68
-rw-r--r--arch/arm/mvp/mvpkm/mksck_shared.c343
-rw-r--r--arch/arm/mvp/mvpkm/mksck_shared.h189
-rw-r--r--arch/arm/mvp/mvpkm/mksck_sockaddr.h50
-rw-r--r--arch/arm/mvp/mvpkm/mmu_defs.h218
-rw-r--r--arch/arm/mvp/mvpkm/mmu_types.h226
-rw-r--r--arch/arm/mvp/mvpkm/montimer_kernel.c102
-rw-r--r--arch/arm/mvp/mvpkm/montimer_kernel.h47
-rw-r--r--arch/arm/mvp/mvpkm/monva_common.h106
-rw-r--r--arch/arm/mvp/mvpkm/mutex.h107
-rw-r--r--arch/arm/mvp/mvpkm/mutex_kernel.c480
-rw-r--r--arch/arm/mvp/mvpkm/mutex_kernel.h41
-rw-r--r--arch/arm/mvp/mvpkm/mvp.h48
-rw-r--r--arch/arm/mvp/mvpkm/mvp_assert.h125
-rw-r--r--arch/arm/mvp/mvpkm/mvp_balloon.h217
-rw-r--r--arch/arm/mvp/mvpkm/mvp_compiler.h56
-rw-r--r--arch/arm/mvp/mvpkm/mvp_compiler_gcc.h87
-rw-r--r--arch/arm/mvp/mvpkm/mvp_math.h133
-rw-r--r--arch/arm/mvp/mvpkm/mvp_timer.h72
-rw-r--r--arch/arm/mvp/mvpkm/mvp_types.h94
-rw-r--r--arch/arm/mvp/mvpkm/mvp_version.h116
-rw-r--r--arch/arm/mvp/mvpkm/mvpkm_comm_ev.c60
-rw-r--r--arch/arm/mvp/mvpkm/mvpkm_comm_ev.h53
-rw-r--r--arch/arm/mvp/mvpkm/mvpkm_kernel.h83
-rw-r--r--arch/arm/mvp/mvpkm/mvpkm_main.c2691
-rw-r--r--arch/arm/mvp/mvpkm/mvpkm_private.h97
-rw-r--r--arch/arm/mvp/mvpkm/mvpkm_types.h49
-rw-r--r--arch/arm/mvp/mvpkm/nottested.h54
-rw-r--r--arch/arm/mvp/mvpkm/platdefx.h67
-rw-r--r--arch/arm/mvp/mvpkm/psr_defs.h117
-rw-r--r--arch/arm/mvp/mvpkm/qp.h332
-rw-r--r--arch/arm/mvp/mvpkm/qp_common.c337
-rw-r--r--arch/arm/mvp/mvpkm/qp_host_kernel.c574
-rw-r--r--arch/arm/mvp/mvpkm/qp_host_kernel.h44
-rw-r--r--arch/arm/mvp/mvpkm/tsc.h49
-rw-r--r--arch/arm/mvp/mvpkm/utils.h172
-rw-r--r--arch/arm/mvp/mvpkm/ve_defs.h72
-rw-r--r--arch/arm/mvp/mvpkm/vfp_switch.S216
-rw-r--r--arch/arm/mvp/mvpkm/vmid.h44
-rw-r--r--arch/arm/mvp/mvpkm/worldswitch.h381
-rw-r--r--arch/arm/mvp/mvpkm/wscalls.h165
-rw-r--r--arch/arm/mvp/pvtcpkm/COPYING341
-rw-r--r--arch/arm/mvp/pvtcpkm/Kbuild9
-rw-r--r--arch/arm/mvp/pvtcpkm/Makefile1
-rw-r--r--arch/arm/mvp/pvtcpkm/check_kconfig.c91
-rw-r--r--arch/arm/mvp/pvtcpkm/comm.h171
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_os.h150
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_os_linux.c371
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_os_linux.h699
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_os_mod_linux.c105
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_os_mod_ver.h38
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_svc.h71
-rw-r--r--arch/arm/mvp/pvtcpkm/comm_transp.h90
-rw-r--r--arch/arm/mvp/pvtcpkm/include_check.h18
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp.c587
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp.h458
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp_off.c81
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp_off.h219
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp_off_io_linux.c831
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp_off_linux.c2858
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp_off_linux.h226
-rw-r--r--arch/arm/mvp/pvtcpkm/pvtcp_off_linux_shim.S70
-rw-r--r--block/genhd.c1
-rw-r--r--crypto/Kconfig16
-rw-r--r--crypto/Makefile2
-rw-r--r--crypto/lz4.c106
-rw-r--r--crypto/lz4hc.c106
-rw-r--r--drivers/block/Kconfig2
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/zram/Kconfig (renamed from drivers/staging/zram/Kconfig)26
-rw-r--r--drivers/block/zram/Makefile5
-rw-r--r--drivers/block/zram/zcomp.c355
-rw-r--r--drivers/block/zram/zcomp.h68
-rw-r--r--drivers/block/zram/zcomp_lz4.c47
-rw-r--r--drivers/block/zram/zcomp_lz4.h17
-rw-r--r--drivers/block/zram/zcomp_lzo.c47
-rw-r--r--drivers/block/zram/zcomp_lzo.h17
-rw-r--r--drivers/block/zram/zram_drv.c1081
-rw-r--r--drivers/block/zram/zram_drv.h118
-rw-r--r--drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c2
-rw-r--r--drivers/hid/hid-core.c3
-rw-r--r--drivers/hid/usbhid/hiddev.c10
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/cypressbln/Kconfig16
-rw-r--r--drivers/input/keyboard/cypressbln/Makefile5
-rw-r--r--drivers/input/keyboard/cypressbln/cypress-touchkey.c2466
-rw-r--r--drivers/input/keyboard/cypressbln/issp_defs.h101
-rw-r--r--drivers/input/keyboard/cypressbln/issp_delays.h87
-rw-r--r--drivers/input/keyboard/cypressbln/issp_directives.h474
-rw-r--r--drivers/input/keyboard/cypressbln/issp_driver_routines.c498
-rw-r--r--drivers/input/keyboard/cypressbln/issp_errors.h65
-rw-r--r--drivers/input/keyboard/cypressbln/issp_extern.h99
-rw-r--r--drivers/input/keyboard/cypressbln/issp_main.c931
-rw-r--r--drivers/input/keyboard/cypressbln/issp_revision.h65
-rw-r--r--drivers/input/keyboard/cypressbln/issp_routines.c1044
-rw-r--r--drivers/input/keyboard/cypressbln/issp_vectors.h1146
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_M0.h747
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_NA.h747
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_NAATT.h747
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_NTT.h685
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_Q1.h747
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_T0.h770
-rw-r--r--drivers/input/keyboard/cypressbln/touchkey_fw_U1.h747
-rw-r--r--drivers/input/keyboard/cypressbln/u1-cypress-gpio.h28
-rw-r--r--drivers/input/tablet/aiptek.c11
-rw-r--r--drivers/input/touchscreen/mxt224_u1.c7
-rw-r--r--drivers/media/video/s5c73m3.c81
-rw-r--r--drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h4
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_buf.h5
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_cmd.c2
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dec.c129
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dev.c79
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dev.h4
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_enc.c32
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_inst.c59
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_inst.h4
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_mem.c56
-rw-r--r--drivers/misc/Kconfig21
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/modem_if/Kconfig21
-rw-r--r--drivers/misc/modem_if/Makefile32
-rw-r--r--drivers/misc/modem_if/lte_modem_bootloader.c2
-rw-r--r--drivers/misc/modem_if/modem.h435
-rw-r--r--drivers/misc/modem_if/modem_boot_device_spi.c279
-rw-r--r--drivers/misc/modem_if/modem_link_device_c2c.c2277
-rw-r--r--drivers/misc/modem_if/modem_link_device_c2c.h202
-rw-r--r--drivers/misc/modem_if/modem_link_device_dpram.c3184
-rw-r--r--drivers/misc/modem_if/modem_link_device_dpram.h455
-rw-r--r--drivers/misc/modem_if/modem_link_device_dpram_ext_op.c1619
-rw-r--r--drivers/misc/modem_if/modem_link_device_hsic.c33
-rw-r--r--drivers/misc/modem_if/modem_link_device_memory.c496
-rw-r--r--drivers/misc/modem_if/modem_link_device_memory.h409
-rw-r--r--drivers/misc/modem_if/modem_link_device_mipi.c2
-rw-r--r--drivers/misc/modem_if/modem_link_device_pld.c1464
-rw-r--r--drivers/misc/modem_if/modem_link_device_pld.h578
-rw-r--r--drivers/misc/modem_if/modem_link_device_pld_ext_op.c277
-rw-r--r--drivers/misc/modem_if/modem_link_device_shmem.h700
-rw-r--r--drivers/misc/modem_if/modem_link_device_spi.c246
-rw-r--r--drivers/misc/modem_if/modem_link_device_spi.h24
-rw-r--r--drivers/misc/modem_if/modem_link_device_usb.c16
-rw-r--r--drivers/misc/modem_if/modem_link_pm_usb.c29
-rw-r--r--drivers/misc/modem_if/modem_link_pm_usb.h2
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_cbp71.c2
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_cbp72.c45
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_cbp82.c288
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_cmc221.c105
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_esc6270.c18
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_mdm6600.c43
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_qsc6085.c218
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_sprd8803.c60
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_ss222.c312
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_xmm6260.c12
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_xmm6262.c92
-rw-r--r--drivers/misc/modem_if/modem_net_flowcontrol_device.c2
-rw-r--r--drivers/misc/modem_if/modem_prj.h514
-rw-r--r--drivers/misc/modem_if/modem_sim_slot_switch.c11
-rw-r--r--drivers/misc/modem_if/modem_utils.c671
-rw-r--r--drivers/misc/modem_if/modem_utils.h56
-rw-r--r--drivers/misc/modem_if/modem_variation.h106
-rw-r--r--drivers/misc/modem_if/sipc4_io_device.c311
-rw-r--r--drivers/misc/modem_if/sipc4_modem.c15
-rw-r--r--drivers/misc/modem_if/sipc5_common.c239
-rw-r--r--drivers/misc/modem_if/sipc5_io_device.c1561
-rw-r--r--drivers/misc/modem_if/sipc5_modem.c87
-rw-r--r--drivers/misc/pmem.c1386
-rw-r--r--drivers/misc/tzic.c1
-rw-r--r--drivers/motor/max77693_haptic.c58
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/usb/usbnet.c7
-rw-r--r--drivers/net/wireless/bcmdhd/Kconfig6
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c4
-rw-r--r--drivers/power/max17042_fuelgauge_u1.c2
-rw-r--r--drivers/scsi/sg.c8
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/android/Kconfig17
-rw-r--r--drivers/staging/android/binder.c2
-rw-r--r--drivers/staging/android/lowmemorykiller.c616
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c32
-rw-r--r--drivers/staging/zcache/Kconfig10
-rw-r--r--drivers/staging/zcache/Makefile2
-rw-r--r--drivers/staging/zcache/tmem.c102
-rw-r--r--drivers/staging/zcache/tmem.h25
-rw-r--r--drivers/staging/zcache/zcache-main.c (renamed from drivers/staging/zcache/zcache.c)802
-rw-r--r--drivers/staging/zram/Makefile4
-rw-r--r--drivers/staging/zram/xvmalloc.c510
-rw-r--r--drivers/staging/zram/xvmalloc.h30
-rw-r--r--drivers/staging/zram/xvmalloc_int.h95
-rw-r--r--drivers/staging/zram/zram.txt76
-rw-r--r--drivers/staging/zram/zram_drv.c769
-rw-r--r--drivers/staging/zram/zram_drv.h132
-rw-r--r--drivers/staging/zram/zram_sysfs.c257
-rw-r--r--drivers/tty/tty_ldisc.c7
-rw-r--r--drivers/usb/class/cdc-acm.c3
-rw-r--r--drivers/usb/core/devio.c9
-rw-r--r--drivers/video/fbcmap.c34
-rw-r--r--drivers/video/fbmem.c4
-rw-r--r--drivers/xen/tmem.c6
-rw-r--r--fs/exec.c11
-rw-r--r--fs/ext4/inode.c7
-rw-r--r--fs/ioprio.c2
-rw-r--r--fs/namespace.c8
-rw-r--r--fs/pipe.c52
-rw-r--r--fs/proc/base.c4
-rw-r--r--fs/proc/task_mmu.c63
-rw-r--r--include/linux/android_pmem.h93
-rw-r--r--include/linux/blkdev.h2
-rw-r--r--include/linux/cleancache.h6
-rw-r--r--include/linux/decompress/unlz4.h10
-rw-r--r--include/linux/lockdep.h2
-rw-r--r--include/linux/lz4.h87
-rw-r--r--include/linux/mm.h3
-rw-r--r--include/linux/mm_types.h21
-rw-r--r--include/linux/page-flags.h10
-rw-r--r--include/linux/perf_event.h8
-rw-r--r--include/linux/pipe_fs_i.h4
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--include/linux/prctl.h3
-rw-r--r--include/linux/sched.h21
-rw-r--r--include/linux/swap.h21
-rw-r--r--include/linux/zsmalloc.h51
-rw-r--r--include/net/tcp.h2
-rw-r--r--init/Kconfig17
-rw-r--r--kernel/events/core.c300
-rw-r--r--kernel/exit.c1
-rw-r--r--kernel/fork.c7
-rw-r--r--kernel/futex.c213
-rw-r--r--kernel/power/earlysuspend.c13
-rw-r--r--kernel/sys.c146
-rw-r--r--kernel/sysctl.c14
-rw-r--r--lib/Kconfig13
-rw-r--r--lib/Makefile4
-rw-r--r--lib/decompress.c5
-rw-r--r--lib/decompress_unlz4.c187
-rw-r--r--lib/lz4/Makefile3
-rw-r--r--lib/lz4/lz4_compress.c443
-rw-r--r--lib/lz4/lz4_decompress.c334
-rw-r--r--lib/lz4/lz4defs.h157
-rw-r--r--lib/lz4/lz4hc_compress.c539
-rw-r--r--lib/lzo/Makefile2
-rw-r--r--lib/lzo/lzo1x_compress.c335
-rw-r--r--lib/lzo/lzo1x_decompress.c255
-rw-r--r--lib/lzo/lzo1x_decompress_safe.c261
-rw-r--r--lib/lzo/lzodefs.h44
-rw-r--r--mm/Kconfig25
-rw-r--r--mm/Makefile2
-rw-r--r--mm/cleancache.c7
-rw-r--r--mm/madvise.c3
-rw-r--r--mm/memory.c17
-rw-r--r--mm/mempolicy.c5
-rw-r--r--mm/mlock.c3
-rw-r--r--mm/mmap.c44
-rw-r--r--mm/mprotect.c3
-rw-r--r--mm/oom_kill.c22
-rw-r--r--mm/page_io.c46
-rw-r--r--mm/shmem.c9
-rw-r--r--mm/swapfile.c193
-rw-r--r--mm/vmscan.c90
-rw-r--r--mm/zsmalloc.c1148
-rw-r--r--net/core/rtnetlink.c16
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/fib_frontend.c4
-rw-r--r--net/ipv4/netfilter/arp_tables.c24
-rw-r--r--net/ipv4/netfilter/ip_tables.c29
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c12
-rw-r--r--net/ipv4/ping.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c29
-rw-r--r--net/netfilter/nf_conntrack_core.c20
-rw-r--r--net/netfilter/x_tables.c4
-rw-r--r--net/netfilter/xt_qtaguid.c2
-rw-r--r--net/socket.c42
-rw-r--r--scripts/Makefile.lib5
-rw-r--r--security/keys/key.c2
-rw-r--r--security/keys/proc.c2
-rw-r--r--sound/core/control.c27
-rw-r--r--sound/core/hrtimer.c3
-rw-r--r--sound/core/timer.c55
-rw-r--r--sound/usb/endpoint.c2
-rw-r--r--sound/usb/midi.c1
-rw-r--r--sound/usb/quirks.c26
-rw-r--r--usr/Kconfig9
377 files changed, 33584 insertions, 41171 deletions
diff --git a/Documentation/ABI/testing/sysfs-block-zram b/Documentation/ABI/testing/sysfs-block-zram
index c8b3b48..4cba43c 100644
--- a/Documentation/ABI/testing/sysfs-block-zram
+++ b/Documentation/ABI/testing/sysfs-block-zram
@@ -42,6 +42,36 @@ Description:
The invalid_io file is read-only and specifies the number of
non-page-size-aligned I/O requests issued to this device.
+What: /sys/block/zram<id>/failed_reads
+Date: February 2014
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ The failed_reads file is read-only and specifies the number of
+ failed reads happened on this device.
+
+What: /sys/block/zram<id>/failed_writes
+Date: February 2014
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ The failed_writes file is read-only and specifies the number of
+ failed writes happened on this device.
+
+What: /sys/block/zram<id>/max_comp_streams
+Date: February 2014
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ The max_comp_streams file is read-write and specifies the
+ number of backend's zcomp_strm compression streams (number of
+ concurrent compress operations).
+
+What: /sys/block/zram<id>/comp_algorithm
+Date: February 2014
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ The comp_algorithm file is read-write and lets to show
+ available and selected compression algorithms, change
+ compression algorithm selection.
+
What: /sys/block/zram<id>/notify_free
Date: August 2010
Contact: Nitin Gupta <ngupta@vflare.org>
@@ -52,15 +82,6 @@ Description:
is freed. This statistic is applicable only when this disk is
being used as a swap disk.
-What: /sys/block/zram<id>/discard
-Date: August 2010
-Contact: Nitin Gupta <ngupta@vflare.org>
-Description:
- The discard file is read-only and specifies the number of
- discard requests received by this device. These requests
- provide information to block device regarding blocks which are
- no longer used by filesystem.
-
What: /sys/block/zram<id>/zero_pages
Date: August 2010
Contact: Nitin Gupta <ngupta@vflare.org>
@@ -96,4 +117,4 @@ Description:
overhead, allocated for this disk. So, allocator space
efficiency can be calculated using compr_data_size and this
statistic.
- Unit: bytes \ No newline at end of file
+ Unit: bytes
diff --git a/Documentation/blockdev/zram.txt b/Documentation/blockdev/zram.txt
new file mode 100644
index 0000000..986b923
--- /dev/null
+++ b/Documentation/blockdev/zram.txt
@@ -0,0 +1,119 @@
+zram: Compressed RAM based block devices
+----------------------------------------
+
+Project home: http://compcache.googlecode.com/
+
+* Introduction
+
+The zram module creates RAM based block devices named /dev/zram<id>
+(<id> = 0, 1, ...). Pages written to these disks are compressed and stored
+in memory itself. These disks allow very fast I/O and compression provides
+good amounts of memory savings. Some of the usecases include /tmp storage,
+use as swap disks, various caches under /var and maybe many more :)
+
+Statistics for individual zram devices are exported through sysfs nodes at
+/sys/block/zram<id>/
+
+* Usage
+
+Following shows a typical sequence of steps for using zram.
+
+1) Load Module:
+ modprobe zram num_devices=4
+ This creates 4 devices: /dev/zram{0,1,2,3}
+ (num_devices parameter is optional. Default: 1)
+
+2) Set max number of compression streams
+ Compression backend may use up to max_comp_streams compression streams,
+ thus allowing up to max_comp_streams concurrent compression operations.
+ By default, compression backend uses single compression stream.
+
+ Examples:
+ #show max compression streams number
+ cat /sys/block/zram0/max_comp_streams
+
+ #set max compression streams number to 3
+ echo 3 > /sys/block/zram0/max_comp_streams
+
+Note:
+In order to enable compression backend's multi stream support max_comp_streams
+must be initially set to desired concurrency level before ZRAM device
+initialisation. Once the device initialised as a single stream compression
+backend (max_comp_streams equals to 1), you will see error if you try to change
+the value of max_comp_streams because single stream compression backend
+implemented as a special case by lock overhead issue and does not support
+dynamic max_comp_streams. Only multi stream backend supports dynamic
+max_comp_streams adjustment.
+
+3) Select compression algorithm
+ Using comp_algorithm device attribute one can see available and
+ currently selected (shown in square brackets) compression algortithms,
+ change selected compression algorithm (once the device is initialised
+ there is no way to change compression algorithm).
+
+ Examples:
+ #show supported compression algorithms
+ cat /sys/block/zram0/comp_algorithm
+ lzo [lz4]
+
+ #select lzo compression algorithm
+ echo lzo > /sys/block/zram0/comp_algorithm
+
+4) Set Disksize
+ Set disk size by writing the value to sysfs node 'disksize'.
+ The value can be either in bytes or you can use mem suffixes.
+ Examples:
+ # Initialize /dev/zram0 with 50MB disksize
+ echo $((50*1024*1024)) > /sys/block/zram0/disksize
+
+ # Using mem suffixes
+ echo 256K > /sys/block/zram0/disksize
+ echo 512M > /sys/block/zram0/disksize
+ echo 1G > /sys/block/zram0/disksize
+
+Note:
+There is little point creating a zram of greater than twice the size of memory
+since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
+size of the disk when not in use so a huge zram is wasteful.
+
+5) Activate:
+ mkswap /dev/zram0
+ swapon /dev/zram0
+
+ mkfs.ext4 /dev/zram1
+ mount /dev/zram1 /tmp
+
+6) Stats:
+ Per-device statistics are exported as various nodes under
+ /sys/block/zram<id>/
+ disksize
+ num_reads
+ num_writes
+ failed_reads
+ failed_writes
+ invalid_io
+ notify_free
+ zero_pages
+ orig_data_size
+ compr_data_size
+ mem_used_total
+
+7) Deactivate:
+ swapoff /dev/zram0
+ umount /dev/zram1
+
+8) Reset:
+ Write any positive value to 'reset' sysfs node
+ echo 1 > /sys/block/zram0/reset
+ echo 1 > /sys/block/zram1/reset
+
+ This frees all the memory allocated for the given device and
+ resets the disksize to zero. You must set the disksize again
+ before reusing the device.
+
+Please report any problems at:
+ - Mailing list: linux-mm-cc at laptop dot org
+ - Issue tracker: http://code.google.com/p/compcache/issues/list
+
+Nitin Gupta
+ngupta@vflare.org
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index db3b1ab..6b0d098 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -354,6 +354,8 @@ is not associated with a file:
[stack] = the stack of the main process
[vdso] = the "virtual dynamic shared object",
the kernel system call handler
+ [anon:<name>] = an anonymous mapping that has been
+ named by userspace
or if empty, the mapping is anonymous.
@@ -376,6 +378,7 @@ Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 374 kB
+Name: name from userspace
The first of these lines shows the same information as is displayed for the
mapping in /proc/PID/maps. The remaining lines show the size of the mapping
@@ -391,6 +394,9 @@ and a page is modified, the file page is replaced by a private anonymous copy.
"Swap" shows how much would-be-anonymous memory is also used, but out on
swap.
+The "Name" field will only be present on a mapping that has been named by
+userspace, and will show the name passed in by userspace.
+
This file is only present if the CONFIG_MMU kernel configuration option is
enabled.
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 88fd7f5..9330fba 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs:
- nr_open
- overflowuid
- overflowgid
+- pipe-user-pages-hard
+- pipe-user-pages-soft
- suid_dumpable
- super-max
- super-nr
@@ -157,6 +159,27 @@ The default is 65534.
==============================================================
+pipe-user-pages-hard:
+
+Maximum total number of pages a non-privileged user may allocate for pipes.
+Once this limit is reached, no new pipes may be allocated until usage goes
+below the limit again. When set to 0, no limit is applied, which is the default
+setting.
+
+==============================================================
+
+pipe-user-pages-soft:
+
+Maximum total number of pages a non-privileged user may allocate for pipes
+before the pipe size gets limited to a single page. Once this limit is reached,
+new pipes will be limited to a single page in size for this user in order to
+limit total memory usage, and trying to increase them using fcntl() will be
+denied until usage goes below the limit again. The default value allows to
+allocate up to 1024 pipes at their default size. When set to 0, no limit is
+applied.
+
+==============================================================
+
suid_dumpable:
This value can be used to query and set the core dump mode for setuid
diff --git a/Makefile b/Makefile
index c6f64a6..a6116bd 100644
--- a/Makefile
+++ b/Makefile
@@ -193,8 +193,8 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
export KBUILD_BUILDHOST := $(SUBARCH)
-ARCH ?= arm
-CROSS_COMPILE ?= ../../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
+ARCH ?= $(SUBARCH)
+CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6799d57..a6725f1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1777,8 +1777,6 @@ config ARM_FLUSH_CONSOLE_ON_RESTART
released if it failed to be acquired, which will cause all the
pending messages to be flushed.
-source "arch/arm/mvp/Kconfig"
-
endmenu
menu "Boot options"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 32d0cc3..f05679a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -249,7 +249,6 @@ endif
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP) += arch/arm/vfp/
-core-$(CONFIG_VMWARE_MVP) += arch/arm/mvp/
# If we have a machine-specific directory, then include it in the build.
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
diff --git a/arch/arm/configs/cyanogenmod_d710_defconfig b/arch/arm/configs/cyanogenmod_d710_defconfig
index e5945d3..ecc7052 100644
--- a/arch/arm/configs/cyanogenmod_d710_defconfig
+++ b/arch/arm/configs/cyanogenmod_d710_defconfig
@@ -660,7 +660,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
-# CONFIG_VMWARE_MVP is not set
#
# Boot options
@@ -1206,7 +1205,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_SENSORS_LIS3LV02D is not set
CONFIG_MISC_DEVICES=y
# CONFIG_AD525X_DPOT is not set
-# CONFIG_ANDROID_PMEM is not set
# CONFIG_INTEL_MID_PTI is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
@@ -2328,7 +2326,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
diff --git a/arch/arm/configs/cyanogenmod_i777_defconfig b/arch/arm/configs/cyanogenmod_i777_defconfig
index 49d5e4d..12a6419 100644
--- a/arch/arm/configs/cyanogenmod_i777_defconfig
+++ b/arch/arm/configs/cyanogenmod_i777_defconfig
@@ -86,12 +86,14 @@ CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
+CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
# CONFIG_BLK_CGROUP is not set
# CONFIG_NAMESPACES is not set
# CONFIG_SCHED_AUTOGROUP is not set
+CONFIG_MM_OWNER=y
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -103,6 +105,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -144,6 +147,7 @@ CONFIG_COMPAT_BRK=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
@@ -452,12 +456,15 @@ CONFIG_PANEL_U1=y
# CONFIG_GC1_00_BD is not set
# CONFIG_T0_00_BD is not set
# CONFIG_T0_04_BD is not set
+# CONFIG_KONA_00_BD is not set
+# CONFIG_KONA_01_BD is not set
# CONFIG_IRON_BD is not set
# CONFIG_GRANDE_BD is not set
# CONFIG_WRITEBACK_ENABLED is not set
# CONFIG_EXYNOS_SOUND_PLATFORM_DATA is not set
# CONFIG_JACK_FET is not set
# CONFIG_JACK_GROUND_DET is not set
+# CONFIG_USE_ADC_DET is not set
CONFIG_SAMSUNG_ANALOG_UART_SWITCH=1
# CONFIG_EXYNOS5_DEV_BTS is not set
@@ -508,6 +515,7 @@ CONFIG_SEC_LOG=y
CONFIG_SEC_LOG_NONCACHED=y
CONFIG_SEC_LOG_LAST_KMSG=y
CONFIG_EHCI_IRQ_DISTRIBUTION=y
+CONFIG_EHCI_MODEM_PORTNUM=2
#
# Samsung Modem Feature
@@ -531,6 +539,11 @@ CONFIG_SEC_MODEM_U1=y
# CONFIG_SEC_MODEM_P8LTE is not set
# CONFIG_SEC_MODEM_T0_TD_DUAL is not set
# CONFIG_SEC_MODEM_U1_SPR is not set
+
+#
+# Connectivity Feature
+#
+# CONFIG_GPS_BRCM_475X is not set
# CONFIG_BT_CSR8811 is not set
CONFIG_BT_BCM4330=y
# CONFIG_BT_BCM4334 is not set
@@ -549,6 +562,7 @@ CONFIG_BT_MGMT=y
CONFIG_USB_CDFS_SUPPORT=y
CONFIG_SAMSUNG_PRODUCT_SHIP=y
# CONFIG_CORESIGHT_ETM is not set
+# CONFIG_MACH_KONA_SENSOR is not set
#
# Processor Type
@@ -662,6 +676,8 @@ CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+CONFIG_ZSMALLOC=y
+# CONFIG_PGTABLE_MAPPING is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
@@ -673,7 +689,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
-# CONFIG_VMWARE_MVP is not set
#
# Boot options
@@ -719,6 +734,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND_FLEXRATE_MAX_DURATION=100
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+# CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST is not set
# CONFIG_CPU_FREQ_GOV_SLP is not set
# CONFIG_CPU_FREQ_DVFS_MONITOR is not set
CONFIG_CPU_IDLE=y
@@ -763,6 +779,7 @@ CONFIG_EARLYSUSPEND=y
# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set
# CONFIG_CONSOLE_EARLYSUSPEND is not set
CONFIG_FB_EARLYSUSPEND=y
+# CONFIG_HIBERNATION is not set
CONFIG_PM_SLEEP=y
CONFIG_PM_SLEEP_SMP=y
CONFIG_PM_RUNTIME=y
@@ -773,6 +790,7 @@ CONFIG_ARCH_HAS_OPP=y
CONFIG_PM_OPP=y
CONFIG_PM_RUNTIME_CLK=y
# CONFIG_SUSPEND_TIME is not set
+CONFIG_CPU_PM=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -1173,6 +1191,14 @@ CONFIG_RFKILL_PM=y
#
# Device Drivers
#
+CONFIG_MALI400=y
+CONFIG_MALI_VER_R3P2=y
+# CONFIG_MALI400_DEBUG is not set
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_DVFS=y
+CONFIG_MALI400_UMP=y
+# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_UMP_DEBUG is not set
#
# Generic Driver Options
@@ -1196,6 +1222,9 @@ CONFIG_SW_SYNC_USER=y
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
+CONFIG_ZRAM=y
+# CONFIG_ZRAM_LZ4_COMPRESS is not set
+# CONFIG_ZRAM_DEBUG is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -1216,7 +1245,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_SENSORS_LIS3LV02D is not set
CONFIG_MISC_DEVICES=y
# CONFIG_AD525X_DPOT is not set
-# CONFIG_ANDROID_PMEM is not set
# CONFIG_INTEL_MID_PTI is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
@@ -1253,6 +1281,7 @@ CONFIG_PN544=y
# CONFIG_STMPE811_ADC is not set
# CONFIG_MPU_SENSORS_MPU3050 is not set
# CONFIG_MPU_SENSORS_MPU6050 is not set
+CONFIG_UID_CPUTIME=y
# CONFIG_C2PORT is not set
#
@@ -1276,10 +1305,13 @@ CONFIG_UMTS_MODEM_XMM6260=y
# CONFIG_UMTS_MODEM_XMM6262 is not set
# CONFIG_CDMA_MODEM_CBP71 is not set
# CONFIG_CDMA_MODEM_CBP72 is not set
+# CONFIG_CDMA_MODEM_CBP82 is not set
# CONFIG_LTE_MODEM_CMC221 is not set
+# CONFIG_UMTS_MODEM_SS222 is not set
# CONFIG_CDMA_MODEM_MDM6600 is not set
# CONFIG_TDSCDMA_MODEM_SPRD8803 is not set
# CONFIG_GSM_MODEM_ESC6270 is not set
+# CONFIG_CDMA_MODEM_QSC6085 is not set
# CONFIG_LINK_DEVICE_MIPI is not set
# CONFIG_LINK_DEVICE_DPRAM is not set
# CONFIG_LINK_DEVICE_PLD is not set
@@ -1287,6 +1319,7 @@ CONFIG_UMTS_MODEM_XMM6260=y
CONFIG_LINK_DEVICE_HSIC=y
# CONFIG_LINK_DEVICE_C2C is not set
# CONFIG_LINK_DEVICE_SPI is not set
+# CONFIG_BOOT_DEVICE_SPI is not set
# CONFIG_WORKQUEUE_FRONT is not set
# CONFIG_IPC_CMC22x_OLD_RFS is not set
# CONFIG_SIPC_VER_5 is not set
@@ -1375,6 +1408,8 @@ CONFIG_WIFI_CONTROL_FUNC=y
CONFIG_BCM4330=m
# CONFIG_BCM4334 is not set
# CONFIG_BCM4335 is not set
+# CONFIG_BCM4339 is not set
+# CONFIG_BCM4354 is not set
# CONFIG_BCM43241 is not set
CONFIG_BROADCOM_WIFI=y
CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
@@ -1465,7 +1500,10 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
-CONFIG_KEYBOARD_CYPRESS_TOUCH=y
+# CONFIG_SENSORS_HALL is not set
+# CONFIG_KEYBOARD_CYPRESS_TOUCH is not set
+CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN=y
+CONFIG_TOUCHKEY_BLN=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -1521,8 +1559,12 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT224_U1=y
# CONFIG_TOUCHSCREEN_MXT1386 is not set
# CONFIG_TOUCHSCREEN_MXT768E is not set
# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED is not set
# CONFIG_TOUCHSCREEN_CYTTSP4 is not set
# CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK is not set
+# CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH is not set
# CONFIG_KEYPAD_MELFAS_TOUCH is not set
# CONFIG_TOUCHSCREEN_ATMEL_MXT540S is not set
# CONFIG_INPUT_WACOM is not set
@@ -1760,6 +1802,7 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17043_FUELGAUGE is not set
# CONFIG_BATTERY_MAX17042_FUELGAUGE is not set
# CONFIG_BATTERY_MAX17047_FUELGAUGE is not set
+# CONFIG_BATTERY_MAX17047_C_FUELGAUGE is not set
# CONFIG_BATTERY_SMB136_CHARGER is not set
# CONFIG_BATTERY_SAMSUNG_P1X is not set
# CONFIG_CHARGER_MAX8903 is not set
@@ -1983,6 +2026,7 @@ CONFIG_VIDEO_S5K5BAFX=y
# CONFIG_VIDEO_S5K4EA is not set
# CONFIG_VIDEO_S5C73M3 is not set
# CONFIG_VIDEO_SLP_S5C73M3 is not set
+# CONFIG_VIDEO_SR130PC20 is not set
CONFIG_VIDEO_IMPROVE_STREAMOFF=y
CONFIG_CSI_C=y
# CONFIG_CSI_D is not set
@@ -2049,7 +2093,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
-CONFIG_MALI_400MP_UMP=y
CONFIG_VIDEO_SAMSUNG=y
CONFIG_VIDEO_SAMSUNG_V4L2=y
CONFIG_VIDEO_FIMC=y
@@ -2078,6 +2121,8 @@ CONFIG_VIDEO_MFC5X=y
CONFIG_VIDEO_MFC_MAX_INSTANCE=4
CONFIG_VIDEO_MFC_MEM_PORT_COUNT=2
# CONFIG_VIDEO_MFC5X_DEBUG is not set
+# CONFIG_VIDEO_MALI400MP is not set
+# CONFIG_VIDEO_UMP is not set
CONFIG_VIDEO_FIMG2D=y
# CONFIG_VIDEO_FIMG2D_DEBUG is not set
CONFIG_VIDEO_FIMG2D3X=y
@@ -2114,19 +2159,12 @@ CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE=y
#
# Graphics support
#
-# CONFIG_MALI_VER_BEFORE_R3P2 is not set
# CONFIG_DRM is not set
CONFIG_ION=y
CONFIG_ION_EXYNOS=y
CONFIG_ION_EXYNOS_CONTIGHEAP_SIZE=71680
# CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG is not set
-CONFIG_MALI400=y
-CONFIG_MALI_VER_R3P2=y
-# CONFIG_MALI400_DEBUG is not set
-# CONFIG_MALI400_PROFILING is not set
-CONFIG_MALI_DVFS=y
-CONFIG_MALI400_UMP=y
-# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
@@ -2201,6 +2239,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_PWM is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
+# CONFIG_BACKLIGHT_LP855X is not set
#
# Display device support
@@ -2357,7 +2396,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2663,8 +2702,6 @@ CONFIG_ANDROID_LOW_MEMORY_KILLER=y
# CONFIG_LINE6_USB is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-# CONFIG_XVMALLOC is not set
-CONFIG_ZRAM=y
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -2706,10 +2743,15 @@ CONFIG_SENSORS_CM3663=y
# CONFIG_SENSORS_CM36651 is not set
# CONFIG_SENSORS_BH1721 is not set
# CONFIG_SENSORS_AL3201 is not set
+# CONFIG_SENSORS_K2DH is not set
CONFIG_SENSORS_K3DH=y
+# CONFIG_SENSOR_K3DH_INPUTDEV is not set
CONFIG_SENSORS_K3G=y
# CONFIG_SENSORS_LSM330DLC is not set
# CONFIG_SENSORS_LPS331 is not set
+# CONFIG_SENSORS_YAS532 is not set
+# CONFIG_SENSORS_YAS_ORI is not set
+CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=0
# CONFIG_SENSORS_SYSFS is not set
# CONFIG_SENSORS_SSP is not set
# CONFIG_SENSORS_SSP_LSM330 is not set
@@ -2824,6 +2866,12 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+CONFIG_F2FS_FS=y
+# CONFIG_F2FS_STAT_FS is not set
+CONFIG_F2FS_FS_XATTR=y
+# CONFIG_F2FS_FS_POSIX_ACL is not set
+CONFIG_F2FS_FS_SECURITY=y
+# CONFIG_F2FS_CHECK_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -2922,7 +2970,6 @@ CONFIG_NLS_UTF8=y
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CPU_ID=y
-CONFIG_UID_CPUTIME=y
# CONFIG_PRINTK_PID is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
@@ -3139,7 +3186,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
#
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=y
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
@@ -3165,6 +3214,10 @@ CONFIG_LIBCRC32C=y
CONFIG_AUDIT_GENERIC=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
diff --git a/arch/arm/configs/cyanogenmod_i9100_defconfig b/arch/arm/configs/cyanogenmod_i9100_defconfig
index 56c3eff..16ec98c 100644
--- a/arch/arm/configs/cyanogenmod_i9100_defconfig
+++ b/arch/arm/configs/cyanogenmod_i9100_defconfig
@@ -105,6 +105,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -675,6 +676,8 @@ CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+CONFIG_ZSMALLOC=y
+# CONFIG_PGTABLE_MAPPING is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
@@ -686,7 +689,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
-# CONFIG_VMWARE_MVP is not set
#
# Boot options
@@ -732,6 +734,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND_FLEXRATE_MAX_DURATION=100
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+# CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST is not set
# CONFIG_CPU_FREQ_GOV_SLP is not set
# CONFIG_CPU_FREQ_DVFS_MONITOR is not set
CONFIG_CPU_IDLE=y
@@ -1219,6 +1222,9 @@ CONFIG_SW_SYNC_USER=y
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
+CONFIG_ZRAM=y
+# CONFIG_ZRAM_LZ4_COMPRESS is not set
+# CONFIG_ZRAM_DEBUG is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -1239,7 +1245,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_SENSORS_LIS3LV02D is not set
CONFIG_MISC_DEVICES=y
# CONFIG_AD525X_DPOT is not set
-# CONFIG_ANDROID_PMEM is not set
# CONFIG_INTEL_MID_PTI is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
@@ -1300,10 +1305,13 @@ CONFIG_UMTS_MODEM_XMM6260=y
# CONFIG_UMTS_MODEM_XMM6262 is not set
# CONFIG_CDMA_MODEM_CBP71 is not set
# CONFIG_CDMA_MODEM_CBP72 is not set
+# CONFIG_CDMA_MODEM_CBP82 is not set
# CONFIG_LTE_MODEM_CMC221 is not set
+# CONFIG_UMTS_MODEM_SS222 is not set
# CONFIG_CDMA_MODEM_MDM6600 is not set
# CONFIG_TDSCDMA_MODEM_SPRD8803 is not set
# CONFIG_GSM_MODEM_ESC6270 is not set
+# CONFIG_CDMA_MODEM_QSC6085 is not set
# CONFIG_LINK_DEVICE_MIPI is not set
# CONFIG_LINK_DEVICE_DPRAM is not set
# CONFIG_LINK_DEVICE_PLD is not set
@@ -1311,6 +1319,7 @@ CONFIG_UMTS_MODEM_XMM6260=y
CONFIG_LINK_DEVICE_HSIC=y
# CONFIG_LINK_DEVICE_C2C is not set
# CONFIG_LINK_DEVICE_SPI is not set
+# CONFIG_BOOT_DEVICE_SPI is not set
# CONFIG_WORKQUEUE_FRONT is not set
# CONFIG_IPC_CMC22x_OLD_RFS is not set
# CONFIG_SIPC_VER_5 is not set
@@ -1492,7 +1501,9 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_SENSORS_HALL is not set
-CONFIG_KEYBOARD_CYPRESS_TOUCH=y
+# CONFIG_KEYBOARD_CYPRESS_TOUCH is not set
+CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN=y
+CONFIG_TOUCHKEY_BLN=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -2384,7 +2395,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2690,10 +2701,6 @@ CONFIG_ANDROID_LOW_MEMORY_KILLER=y
# CONFIG_LINE6_USB is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-CONFIG_XVMALLOC=y
-CONFIG_ZRAM=y
-# CONFIG_ZRAM_DEBUG is not set
-# CONFIG_ZRAM_FOR_ANDROID is not set
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -3178,7 +3185,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
#
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=y
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
@@ -3206,6 +3215,8 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
diff --git a/arch/arm/configs/cyanogenmod_i925_defconfig b/arch/arm/configs/cyanogenmod_i925_defconfig
index 4737aab..08b4ef3 100644
--- a/arch/arm/configs/cyanogenmod_i925_defconfig
+++ b/arch/arm/configs/cyanogenmod_i925_defconfig
@@ -681,8 +681,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -2429,7 +2427,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2896,7 +2894,7 @@ CONFIG_MOBICORE_SUPPORT=y
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
-CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR=m
+# CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR is not set
#
# File systems
diff --git a/arch/arm/configs/cyanogenmod_i9300_defconfig b/arch/arm/configs/cyanogenmod_i9300_defconfig
index e243ac4..e4d7e46 100644
--- a/arch/arm/configs/cyanogenmod_i9300_defconfig
+++ b/arch/arm/configs/cyanogenmod_i9300_defconfig
@@ -108,6 +108,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_CHECK_WARNING_STRICTLY is not set
CONFIG_SYSCTL=y
@@ -688,9 +689,11 @@ CONFIG_MIGRATION=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
-# CONFIG_KSM is not set
+CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+CONFIG_ZSMALLOC=y
+# CONFIG_PGTABLE_MAPPING is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
@@ -702,7 +705,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-# CONFIG_VMWARE_MVP is not set
#
# Boot options
@@ -1244,6 +1246,9 @@ CONFIG_CMA_AREAS=7
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
+CONFIG_ZRAM=y
+CONFIG_ZRAM_LZ4_COMPRESS=y
+# CONFIG_ZRAM_DEBUG is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -1327,10 +1332,13 @@ CONFIG_SEC_MODEM=y
CONFIG_UMTS_MODEM_XMM6262=y
# CONFIG_CDMA_MODEM_CBP71 is not set
# CONFIG_CDMA_MODEM_CBP72 is not set
+# CONFIG_CDMA_MODEM_CBP82 is not set
# CONFIG_LTE_MODEM_CMC221 is not set
+# CONFIG_UMTS_MODEM_SS222 is not set
# CONFIG_CDMA_MODEM_MDM6600 is not set
# CONFIG_TDSCDMA_MODEM_SPRD8803 is not set
# CONFIG_GSM_MODEM_ESC6270 is not set
+# CONFIG_CDMA_MODEM_QSC6085 is not set
# CONFIG_LINK_DEVICE_MIPI is not set
# CONFIG_LINK_DEVICE_DPRAM is not set
# CONFIG_LINK_DEVICE_PLD is not set
@@ -1338,6 +1346,7 @@ CONFIG_UMTS_MODEM_XMM6262=y
CONFIG_LINK_DEVICE_HSIC=y
# CONFIG_LINK_DEVICE_C2C is not set
# CONFIG_LINK_DEVICE_SPI is not set
+# CONFIG_BOOT_DEVICE_SPI is not set
# CONFIG_WORKQUEUE_FRONT is not set
# CONFIG_IPC_CMC22x_OLD_RFS is not set
# CONFIG_SIPC_VER_5 is not set
@@ -1525,6 +1534,7 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_SENSORS_HALL is not set
CONFIG_KEYBOARD_CYPRESS_TOUCH=y
+# CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -2478,7 +2488,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2866,16 +2876,14 @@ CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
CONFIG_ANDROID_TIMED_OUTPUT=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
+CONFIG_ANDROID_LMK_ADJ_RBTREE=y
# CONFIG_POHMELFS is not set
# CONFIG_LINE6_USB is not set
# CONFIG_USB_SERIAL_QUATECH2 is not set
# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-CONFIG_XVMALLOC=y
-CONFIG_ZRAM=y
-# CONFIG_ZRAM_DEBUG is not set
-CONFIG_ZRAM_FOR_ANDROID=y
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -3042,35 +3050,7 @@ CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
# CONFIG_F2FS_CHECK_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-# CONFIG_NFS_V4_1 is not set
-# CONFIG_NFS_USE_LEGACY_DNS is not set
-CONFIG_NFS_USE_KERNEL_DNS=y
-# CONFIG_NFS_USE_NEW_IDMAPPER is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-CONFIG_SUNRPC_GSS=m
-# CONFIG_CEPH_FS is not set
-CONFIG_CIFS=m
-CONFIG_CIFS_STATS=y
-CONFIG_CIFS_STATS2=y
-CONFIG_CIFS_WEAK_PW_HASH=y
-CONFIG_CIFS_UPCALL=y
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-# CONFIG_CIFS_DEBUG2 is not set
-CONFIG_CIFS_DFS_UPCALL=y
-CONFIG_CIFS_ACL=y
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
#
# Partition Types
@@ -3358,7 +3338,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
#
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=y
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
@@ -3386,6 +3368,8 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
diff --git a/arch/arm/configs/cyanogenmod_i9305_defconfig b/arch/arm/configs/cyanogenmod_i9305_defconfig
index 5c640cc..75b99a1 100755..100644
--- a/arch/arm/configs/cyanogenmod_i9305_defconfig
+++ b/arch/arm/configs/cyanogenmod_i9305_defconfig
@@ -30,7 +30,6 @@ CONFIG_ARM_PATCH_PHYS_VIRT=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_HAVE_IRQ_WORK=y
-CONFIG_IRQ_WORK=y
#
# General setup
@@ -70,6 +69,7 @@ CONFIG_GENERIC_IRQ_CHIP=y
# RCU Subsystem
#
CONFIG_TREE_PREEMPT_RCU=y
+# CONFIG_TINY_RCU is not set
CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_FANOUT=32
@@ -106,6 +106,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_CHECK_WARNING_STRICTLY is not set
CONFIG_SYSCTL=y
@@ -145,6 +146,7 @@ CONFIG_COMPAT_BRK=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
@@ -154,7 +156,6 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_DMA_API_DEBUG=y
-CONFIG_HAVE_HW_BREAKPOINT=y
#
# GCOV-based kernel profiling
@@ -185,6 +186,8 @@ CONFIG_IOSCHED_ROW=y
CONFIG_IOSCHED_SIO=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_ROW is not set
+# CONFIG_DEFAULT_SIO is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_SPIN_TRYLOCK is not set
@@ -422,7 +425,6 @@ CONFIG_SEC_THERMISTOR=y
# CONFIG_EXYNOS_SYSREG_PM is not set
CONFIG_ANDROID_WIP=y
# CONFIG_COMPACTION_RETRY is not set
-# CONFIG_COMPACTION_RETRY_DEBUG is not set
#
# EXYNOS4 Machines
@@ -435,11 +437,11 @@ CONFIG_ANDROID_WIP=y
# CONFIG_MACH_U1_NA_SPR is not set
# CONFIG_MACH_U1_NA_USCC is not set
# CONFIG_MACH_U1 is not set
+# CONFIG_TARGET_LOCALE_NAATT_TEMP is not set
# CONFIG_MACH_PX is not set
CONFIG_TARGET_LOCALE_EUR=y
# CONFIG_TARGET_LOCALE_LTN is not set
# CONFIG_TARGET_LOCALE_KOR is not set
-# CONFIG_TARGET_LOCALE_NAATT_TEMP is not set
# CONFIG_TARGET_LOCALE_P2EUR_TEMP is not set
# CONFIG_TARGET_LOCALE_P2TMO_TEMP is not set
# CONFIG_TARGET_LOCALE_NA is not set
@@ -456,6 +458,7 @@ CONFIG_MACH_M3=y
# CONFIG_MACH_P4NOTE is not set
# CONFIG_MACH_GC1 is not set
# CONFIG_MACH_T0 is not set
+# CONFIG_MACH_KONA is not set
# CONFIG_MACH_IRON is not set
# CONFIG_MACH_GRANDE is not set
# CONFIG_MACH_BAFFIN is not set
@@ -464,12 +467,15 @@ CONFIG_MIDAS_COMMON_BD=y
# CONFIG_GC1_00_BD is not set
# CONFIG_T0_00_BD is not set
# CONFIG_T0_04_BD is not set
+# CONFIG_KONA_00_BD is not set
+# CONFIG_KONA_01_BD is not set
# CONFIG_IRON_BD is not set
# CONFIG_GRANDE_BD is not set
# CONFIG_WRITEBACK_ENABLED is not set
# CONFIG_EXYNOS_SOUND_PLATFORM_DATA is not set
# CONFIG_JACK_FET is not set
# CONFIG_JACK_GROUND_DET is not set
+# CONFIG_USE_ADC_DET is not set
CONFIG_SAMSUNG_ANALOG_UART_SWITCH=1
# CONFIG_EXYNOS5_DEV_BTS is not set
@@ -522,6 +528,11 @@ CONFIG_SEC_LOG=y
CONFIG_SEC_LOG_NONCACHED=y
CONFIG_SEC_LOG_LAST_KMSG=y
# CONFIG_EHCI_IRQ_DISTRIBUTION is not set
+
+#
+# Connectivity Feature
+#
+# CONFIG_GPS_BRCM_475X is not set
# CONFIG_BT_CSR8811 is not set
# CONFIG_BT_BCM4330 is not set
CONFIG_BT_BCM4334=y
@@ -536,10 +547,12 @@ CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_QC_MODEM_MDM9X15=y
CONFIG_MDM_HSIC_PM=y
# CONFIG_EMI_ERROR_RECOVERY is not set
+# CONFIG_SIM_DETECT is not set
CONFIG_QC_MODEM_M3=y
CONFIG_USB_CDFS_SUPPORT=y
CONFIG_SAMSUNG_PRODUCT_SHIP=y
# CONFIG_CORESIGHT_ETM is not set
+# CONFIG_MACH_KONA_SENSOR is not set
#
# Processor Type
@@ -594,6 +607,9 @@ CONFIG_ARM_ERRATA_761320=y
# CONFIG_ARM_ERRATA_761171 is not set
# CONFIG_ARM_ERRATA_762974 is not set
# CONFIG_ARM_ERRATA_763722 is not set
+CONFIG_ARM_ERRATA_764369=y
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
CONFIG_ARM_GIC=y
CONFIG_PL330=y
# CONFIG_FIQ_DEBUGGER is not set
@@ -604,8 +620,6 @@ CONFIG_PL330=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
-CONFIG_ARM_ERRATA_764369=y
-# CONFIG_PL310_ERRATA_769419 is not set
#
# Kernel Features
@@ -637,14 +651,13 @@ CONFIG_HAVE_ARCH_PFN_VALID=y
CONFIG_ARCH_SKIP_SECONDARY_CALIBRATE=y
CONFIG_HIGHMEM=y
# CONFIG_HIGHPTE is not set
-CONFIG_HW_PERF_EVENTS=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_SPLIT_PTLOCK_CPUS=999999
CONFIG_COMPACTION=y
CONFIG_MIGRATION=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
@@ -654,6 +667,7 @@ CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+# CONFIG_ZSMALLOC is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
@@ -665,8 +679,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -711,8 +723,9 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+# CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST is not set
# CONFIG_CPU_FREQ_GOV_SLP is not set
-# CONFIG_CPU_FREQ_DVFS_MONITOR is not set
+CONFIG_CPU_FREQ_DVFS_MONITOR=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
@@ -762,6 +775,7 @@ CONFIG_ARCH_HAS_OPP=y
CONFIG_PM_OPP=y
CONFIG_PM_RUNTIME_CLK=y
# CONFIG_SUSPEND_TIME is not set
+CONFIG_CPU_PM=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -1096,7 +1110,6 @@ CONFIG_XPS=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
-# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
@@ -1150,6 +1163,7 @@ CONFIG_WIRELESS_EXT_SYSFS=y
# CONFIG_LIB80211 is not set
# CONFIG_CFG80211_ALLOW_RECONNECT is not set
# CONFIG_MAC80211 is not set
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
CONFIG_RFKILL_PM=y
@@ -1163,6 +1177,14 @@ CONFIG_RFKILL_PM=y
#
# Device Drivers
#
+CONFIG_MALI400=y
+CONFIG_MALI_VER_R3P2=y
+# CONFIG_MALI400_DEBUG is not set
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_DVFS=y
+CONFIG_MALI400_UMP=y
+# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_UMP_DEBUG is not set
#
# Generic Driver Options
@@ -1244,6 +1266,7 @@ CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK=y
# CONFIG_STMPE811_ADC is not set
# CONFIG_MPU_SENSORS_MPU3050 is not set
# CONFIG_MPU_SENSORS_MPU6050 is not set
+CONFIG_UID_CPUTIME=y
# CONFIG_C2PORT is not set
#
@@ -1344,11 +1367,19 @@ CONFIG_WLAN=y
# CONFIG_USB_NET_RNDIS_WLAN is not set
CONFIG_WIFI_CONTROL_FUNC=y
# CONFIG_ATH_COMMON is not set
-CONFIG_BCM4334=m
+# CONFIG_B43LEGACY_DMA_AND_PIO_MODE is not set
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
# CONFIG_BCM4330 is not set
+CONFIG_BCM4334=m
+# CONFIG_BCM4335 is not set
+# CONFIG_BCM4339 is not set
+# CONFIG_BCM4354 is not set
# CONFIG_BCM43241 is not set
+CONFIG_BROADCOM_WIFI=y
+CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
+CONFIG_BCMDHD_NVRAM_PATH="/system/etc/wifi/bcmdhd.cal"
CONFIG_BROADCOM_WIFI_RESERVED_MEM=y
-# CONFIG_WLAN_COUNTRY_CODE is not set
CONFIG_WLAN_REGION_CODE=100
# CONFIG_HOSTAP is not set
# CONFIG_IWM is not set
@@ -1418,7 +1449,7 @@ CONFIG_SLHC=y
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
+CONFIG_PHONE=y
#
# Input device support
@@ -1464,7 +1495,9 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_SENSORS_HALL is not set
CONFIG_KEYBOARD_CYPRESS_TOUCH=y
+# CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -1519,8 +1552,12 @@ CONFIG_TOUCHSCREEN_MELFAS=y
# CONFIG_TOUCHSCREEN_MXT1386 is not set
# CONFIG_TOUCHSCREEN_MXT768E is not set
# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED is not set
# CONFIG_TOUCHSCREEN_CYTTSP4 is not set
# CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK is not set
+# CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH is not set
# CONFIG_KEYPAD_MELFAS_TOUCH is not set
# CONFIG_TOUCHSCREEN_ATMEL_MXT540S is not set
# CONFIG_INPUT_WACOM is not set
@@ -1760,6 +1797,7 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17043_FUELGAUGE is not set
# CONFIG_BATTERY_MAX17042_FUELGAUGE is not set
CONFIG_BATTERY_MAX17047_FUELGAUGE=y
+# CONFIG_BATTERY_MAX17047_C_FUELGAUGE is not set
# CONFIG_BATTERY_SMB136_CHARGER is not set
CONFIG_BATTERY_MAX77693_CHARGER=y
CONFIG_BATTERY_WPC_CHARGER=y
@@ -1791,10 +1829,103 @@ CONFIG_BATTERY_SAMSUNG=y
# CONFIG_SMB328_CHARGER is not set
# CONFIG_SMB347_CHARGER is not set
# CONFIG_CHARGER_MANAGER is not set
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_S3C is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
CONFIG_THERMAL=y
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_CPU_THERMAL is not set
-# CONFIG_SENSORS_EXYNOS4_TMU is not set
+CONFIG_SENSORS_EXYNOS4_TMU=y
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -2012,6 +2143,7 @@ CONFIG_S5K6A3_CSI_D=y
CONFIG_VIDEO_S5C73M3=y
CONFIG_VIDEO_S5C73M3_SPI=y
# CONFIG_VIDEO_SLP_S5C73M3 is not set
+# CONFIG_VIDEO_SR130PC20 is not set
# CONFIG_VIDEO_IMPROVE_STREAMOFF is not set
#
@@ -2078,7 +2210,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
-CONFIG_MALI_400MP_UMP=y
CONFIG_VIDEO_SAMSUNG=y
CONFIG_VIDEO_SAMSUNG_V4L2=y
CONFIG_VIDEO_FIMC=y
@@ -2107,6 +2238,8 @@ CONFIG_LSI_HDMI_AUDIO_CH_EVENT=y
CONFIG_VIDEO_MFC5X=y
CONFIG_VIDEO_MFC_MAX_INSTANCE=4
# CONFIG_VIDEO_MFC5X_DEBUG is not set
+# CONFIG_VIDEO_MALI400MP is not set
+# CONFIG_VIDEO_UMP is not set
CONFIG_VIDEO_FIMG2D=y
# CONFIG_VIDEO_FIMG2D_DEBUG is not set
CONFIG_VIDEO_FIMG2D4X=y
@@ -2160,19 +2293,12 @@ CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE=y
#
# Graphics support
#
-# CONFIG_MALI_VER_BEFORE_R3P2 is not set
# CONFIG_DRM is not set
CONFIG_ION=y
CONFIG_ION_EXYNOS=y
CONFIG_ION_EXYNOS_CONTIGHEAP_SIZE=71680
# CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG is not set
-CONFIG_MALI400=y
-CONFIG_MALI_VER_R3P2=y
-# CONFIG_MALI400_DEBUG is not set
-# CONFIG_MALI400_PROFILING is not set
-CONFIG_MALI_DVFS=y
-CONFIG_MALI400_UMP=y
-# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
@@ -2224,6 +2350,7 @@ CONFIG_FB_S5P_S6E8AA0=y
# CONFIG_FB_S5P_S6EVR02 is not set
# CONFIG_FB_S5P_S6D6AA1 is not set
# CONFIG_FB_S5P_S6E63M0 is not set
+# CONFIG_FB_S5P_NT71391 is not set
# CONFIG_S6E8AA0_AMS529HA01 is not set
CONFIG_S6E8AA0_AMS480GYXX=y
CONFIG_AID_DIMMING=y
@@ -2233,10 +2360,13 @@ CONFIG_FB_S5P_EXTDSP=y
CONFIG_FB_S5P_EXTDSP_NR_BUFFERS=3
# CONFIG_S5P_DSIM_SWITCHABLE_DUAL_LCD is not set
# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_CARMINE_DRAM_EVAL is not set
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
# CONFIG_FB_TMIO is not set
# CONFIG_FB_UDL is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX_PCI_GDC is not set
# CONFIG_FB_BROADSHEET is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
@@ -2258,6 +2388,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_PWM is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
+# CONFIG_BACKLIGHT_LP855X is not set
#
# Display device support
@@ -2419,7 +2550,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2457,6 +2588,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_HWA_HCD is not set
# CONFIG_USB_S3C_OTG_HOST is not set
# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
#
# USB Device Class drivers
@@ -2488,7 +2621,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_STORAGE_ENE_UB6250 is not set
-# CONFIG_USB_UAS is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -2592,6 +2724,12 @@ CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_GADGET_S3C_OTGD=y
# CONFIG_USB_GADGET_PXA_U2O is not set
# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_CI13XXX_PCI is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_EG20T is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
#
@@ -2621,6 +2759,8 @@ CONFIG_USB_DUN_SUPPORT=y
# CONFIG_USB_G_MULTI is not set
# CONFIG_USB_G_HID is not set
# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_DBGP_PRINTK is not set
+# CONFIG_USB_G_DBGP_SERIAL is not set
# CONFIG_USB_G_WEBCAM is not set
#
@@ -2649,6 +2789,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y
# CONFIG_SDIO_UART is not set
# CONFIG_MMC_TEST is not set
CONFIG_MMC_SELECTIVE_PACKED_CMD_POLICY=y
+# CONFIG_MMC_CPRM is not set
#
# MMC/SD/SDIO Host Controller Drivers
@@ -2694,6 +2835,7 @@ CONFIG_LEDS_AAT1290A=y
#
# LED Triggers
#
+# CONFIG_LEDS_TRIGGER_NOTIFICATION is not set
CONFIG_NFC_DEVICES=y
# CONFIG_PN544_NFC is not set
CONFIG_PN65N_NFC=y
@@ -2808,14 +2950,19 @@ CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
CONFIG_ANDROID_TIMED_OUTPUT=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
+CONFIG_ANDROID_LMK_ADJ_RBTREE=y
# CONFIG_POHMELFS is not set
# CONFIG_LINE6_USB is not set
# CONFIG_USB_SERIAL_QUATECH2 is not set
# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-# CONFIG_XVMALLOC is not set
-# CONFIG_ZRAM is not set
+# CONFIG_LIS3L02DQ_BUF_KFIFO is not set
+# CONFIG_LIS3L02DQ_BUF_RING_SW is not set
+# CONFIG_AD2S1210_GPIO_INPUT is not set
+# CONFIG_AD2S1210_GPIO_OUTPUT is not set
+# CONFIG_AD2S1210_GPIO_NONE is not set
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -2855,10 +3002,15 @@ CONFIG_SENSORS_AK8975C=y
CONFIG_SENSORS_CM36651=y
# CONFIG_SENSORS_BH1721 is not set
# CONFIG_SENSORS_AL3201 is not set
+# CONFIG_SENSORS_K2DH is not set
# CONFIG_SENSORS_K3DH is not set
# CONFIG_SENSORS_K3G is not set
CONFIG_SENSORS_LSM330DLC=y
+CONFIG_SENSORS_LSM330DLC_USE_INPUT_DEV=y
CONFIG_SENSORS_LPS331=y
+# CONFIG_SENSORS_YAS532 is not set
+# CONFIG_SENSORS_YAS_ORI is not set
+CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=0
# CONFIG_SENSORS_SYSFS is not set
# CONFIG_SENSORS_SSP is not set
# CONFIG_SENSORS_SSP_LSM330 is not set
@@ -2868,6 +3020,20 @@ CONFIG_SENSORS_LPS331=y
# CONFIG_SENSORS_SSP_AT32UC3L0128 is not set
# CONFIG_SENSORS_SSP_SENSORHUB is not set
# CONFIG_PM_DEVFREQ is not set
+
+#
+# DEVFREQ Governors
+#
+# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set
+# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set
+# CONFIG_DEVFREQ_GOV_POWERSAVE is not set
+# CONFIG_DEVFREQ_GOV_USERSPACE is not set
+
+#
+# DEVFREQ Drivers
+#
+# CONFIG_ARM_EXYNOS4_BUS_DEVFREQ is not set
+# CONFIG_ARM_EXYNOS4_DISPLAY_DEVFREQ is not set
# CONFIG_SAMSUNG_PHONE_SVNET is not set
CONFIG_ACCESSORY=y
# CONFIG_30PIN_CONN is not set
@@ -2878,8 +3044,12 @@ CONFIG_ACCESSORY=y
# CONFIG_IR_REMOCON is not set
# CONFIG_EXTCON is not set
# CONFIG_BARCODE_EMUL is not set
+# CONFIG_SAMSUNG_PHONE_TTY is not set
+# CONFIG_SAMSUNG_PHONE_TTY_RAFFAELLO is not set
+# CONFIG_SAMSUNG_PHONE_TTY_RAFFAELLO_RECOVERY is not set
CONFIG_MOBICORE_SUPPORT=y
-# CONFIG_MOBICORE_DEBUG is not set
+CONFIG_MOBICORE_DEBUG=y
+CONFIG_MOBICORE_VERBOSE=y
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
@@ -2963,6 +3133,10 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
# CONFIG_LOGFS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
@@ -2972,9 +3146,13 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -3072,7 +3250,6 @@ CONFIG_NLS_UTF8=y
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CPU_ID=y
-CONFIG_UID_CPUTIME=y
# CONFIG_PRINTK_PID is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
@@ -3102,11 +3279,12 @@ CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_KMEMLEAK is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_SPARSE_RCU_POINTER is not set
@@ -3155,6 +3333,9 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
+# CONFIG_BRANCH_PROFILE_NONE is not set
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_ATOMIC64_SELFTEST is not set
@@ -3193,6 +3374,9 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_IMA is not set
CONFIG_DEFAULT_SECURITY_SELINUX=y
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_DEFAULT_SECURITY="selinux"
CONFIG_CRYPTO=y
@@ -3293,6 +3477,8 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
diff --git a/arch/arm/configs/cyanogenmod_n5100_defconfig b/arch/arm/configs/cyanogenmod_n5100_defconfig
index c8fa884..98e0b72 100644
--- a/arch/arm/configs/cyanogenmod_n5100_defconfig
+++ b/arch/arm/configs/cyanogenmod_n5100_defconfig
@@ -70,6 +70,7 @@ CONFIG_GENERIC_IRQ_CHIP=y
# RCU Subsystem
#
CONFIG_TREE_PREEMPT_RCU=y
+# CONFIG_TINY_RCU is not set
CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_FANOUT=32
@@ -107,6 +108,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_CHECK_WARNING_STRICTLY is not set
CONFIG_SYSCTL=y
@@ -189,6 +191,8 @@ CONFIG_IOSCHED_ROW=y
CONFIG_IOSCHED_SIO=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_ROW is not set
+# CONFIG_DEFAULT_SIO is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_SPIN_TRYLOCK is not set
@@ -219,7 +223,7 @@ CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
-CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
CONFIG_FREEZER=y
#
@@ -355,6 +359,7 @@ CONFIG_S5P_DEV_USB_EHCI=y
CONFIG_S5P_DEV_FIMD_S5P=y
CONFIG_S5P_DEV_USBGADGET=y
CONFIG_S5P_MEM_CMA=y
+CONFIG_S5P_DEV_MIPI_DSI=y
# CONFIG_S5P_BTS is not set
# CONFIG_S3C_DEV_TSI is not set
CONFIG_ARCH_EXYNOS4=y
@@ -369,7 +374,6 @@ CONFIG_EXYNOS4_LOWPWR_IDLE=y
CONFIG_EXYNOS_MCT=y
CONFIG_EXYNOS_DEV_PD=y
CONFIG_EXYNOS4_DEV_FIMC_LITE=y
-CONFIG_EXYNOS4_DEV_FIMC_IS=y
CONFIG_EXYNOS4_SETUP_I2C1=y
CONFIG_EXYNOS4_SETUP_I2C3=y
CONFIG_EXYNOS4_SETUP_I2C4=y
@@ -385,13 +389,13 @@ CONFIG_EXYNOS4_SETUP_FIMC0=y
CONFIG_EXYNOS4_SETUP_FIMC1=y
CONFIG_EXYNOS4_SETUP_FIMC2=y
CONFIG_EXYNOS4_SETUP_FIMC3=y
-CONFIG_EXYNOS4_SETUP_FIMC_IS=y
CONFIG_EXYNOS4_SETUP_USB_PHY=y
CONFIG_EXYNOS4_SETUP_CSIS=y
CONFIG_EXYNOS4_SETUP_FB_S5P=y
CONFIG_EXYNOS4_SETUP_TVOUT=y
CONFIG_EXYNOS4_SETUP_THERMAL=y
# CONFIG_EXYNOS_SETUP_THERMAL is not set
+CONFIG_EXYNOS4_SETUP_MIPI_DSI=y
CONFIG_EXYNOS4_SETUP_JPEG=y
CONFIG_EXYNOS4_ENABLE_CLOCK_DOWN=y
CONFIG_EXYNOS4_CPUFREQ=y
@@ -420,7 +424,6 @@ CONFIG_BUSFREQ_QOS_1280X800=y
# CONFIG_BUSFREQ_DEBUG is not set
# CONFIG_BUSFREQ_L2_160M is not set
CONFIG_SEC_THERMISTOR=y
-# CONFIG_SEC_SUBTHERMISTOR is not set
# CONFIG_EXYNOS_SYSREG_PM is not set
CONFIG_ANDROID_WIP=y
# CONFIG_COMPACTION_RETRY is not set
@@ -449,6 +452,11 @@ CONFIG_TARGET_LOCALE_EUR=y
# CONFIG_TARGET_LOCALE_JPN is not set
# CONFIG_TARGET_LOCALE_CHN is not set
# CONFIG_TARGET_LOCALE_USA is not set
+CONFIG_MACH_KONA_EUR_OPEN=y
+# CONFIG_MACH_KONA_EUR_WIFI is not set
+# CONFIG_MACH_KONA_EUR_LTE is not set
+# CONFIG_MACH_KONALTE_USA_ATT is not set
+# CONFIG_MACH_KONA_KOR_WIFI is not set
# CONFIG_MACH_SMDK4X12 is not set
CONFIG_MACH_MIDAS=y
# CONFIG_MACH_M0 is not set
@@ -458,7 +466,6 @@ CONFIG_MACH_MIDAS=y
# CONFIG_MACH_GC1 is not set
# CONFIG_MACH_T0 is not set
CONFIG_MACH_KONA=y
-CONFIG_MACH_KONA_SENSOR=y
# CONFIG_MACH_IRON is not set
# CONFIG_MACH_GRANDE is not set
# CONFIG_MACH_BAFFIN is not set
@@ -471,21 +478,12 @@ CONFIG_MACH_KONA_SENSOR=y
CONFIG_KONA_01_BD=y
# CONFIG_IRON_BD is not set
# CONFIG_GRANDE_BD is not set
-# CONFIG_SLP is not set
-# CONFIG_MACH_REDWOOD is not set
-# CONFIG_GPS_BCM47511 is not set
-# CONFIG_GPS_BCM4752 is not set
-# CONFIG_GPS_GSD4T is not set
-# CONFIG_GPIO_NAPLES_00_BD is not set
-# CONFIG_SLP_DISP_DEBUG is not set
-# CONFIG_EXYNOS4_DEV_TMU is not set
-# CONFIG_BT_TIZEN is not set
# CONFIG_WRITEBACK_ENABLED is not set
CONFIG_EXYNOS_SOUND_PLATFORM_DATA=y
-CONFIG_USE_ADC_DET=y
# CONFIG_JACK_FET is not set
# CONFIG_JACK_GROUND_DET is not set
-# CONFIG_SAMSUNG_ANALOG_UART_SWITCH is not set
+CONFIG_USE_ADC_DET=y
+CONFIG_SAMSUNG_ANALOG_UART_SWITCH=1
# CONFIG_EXYNOS5_DEV_BTS is not set
#
@@ -522,6 +520,7 @@ CONFIG_EXYNOS4_MSHC_DDR=y
#
CONFIG_SEC_DEBUG=y
CONFIG_SEC_DEBUG_SCHED_LOG=y
+# CONFIG_SEC_DEBUG_HRTIMER_LOG is not set
# CONFIG_SEC_DEBUG_SOFTIRQ_LOG is not set
CONFIG_SEC_DEBUG_SCHED_LOG_NONCACHED=y
# CONFIG_SEC_DEBUG_SEMAPHORE_LOG is not set
@@ -538,6 +537,7 @@ CONFIG_SEC_LOG=y
CONFIG_SEC_LOG_NONCACHED=y
CONFIG_SEC_LOG_LAST_KMSG=y
CONFIG_EHCI_IRQ_DISTRIBUTION=y
+CONFIG_EHCI_MODEM_PORTNUM=2
#
# Samsung Modem Feature
@@ -565,7 +565,7 @@ CONFIG_SEC_MODEM_M0=y
#
# Connectivity Feature
#
-# CONFIG_GPS_BRCM_475X is not set
+CONFIG_GPS_BRCM_475X=y
# CONFIG_BT_CSR8811 is not set
# CONFIG_BT_BCM4330 is not set
CONFIG_BT_BCM4334=y
@@ -576,14 +576,15 @@ CONFIG_BT_MGMT=y
# Qualcomm Modem Feature
#
# CONFIG_QC_MODEM is not set
-# CONFIG_CPU_FREQ_TETHERING is not set
# CONFIG_MSM_SUBSYSTEM_RESTART is not set
# CONFIG_QC_MODEM_MDM9X15 is not set
# CONFIG_MDM_HSIC_PM is not set
# CONFIG_EMI_ERROR_RECOVERY is not set
+# CONFIG_SIM_DETECT is not set
CONFIG_USB_CDFS_SUPPORT=y
# CONFIG_SAMSUNG_PRODUCT_SHIP is not set
# CONFIG_CORESIGHT_ETM is not set
+CONFIG_MACH_KONA_SENSOR=y
#
# Processor Type
@@ -638,6 +639,9 @@ CONFIG_ARM_ERRATA_761320=y
# CONFIG_ARM_ERRATA_761171 is not set
# CONFIG_ARM_ERRATA_762974 is not set
# CONFIG_ARM_ERRATA_763722 is not set
+CONFIG_ARM_ERRATA_764369=y
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
CONFIG_ARM_GIC=y
CONFIG_PL330=y
# CONFIG_FIQ_DEBUGGER is not set
@@ -648,8 +652,6 @@ CONFIG_PL330=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
-CONFIG_ARM_ERRATA_764369=y
-# CONFIG_PL310_ERRATA_769419 is not set
#
# Kernel Features
@@ -698,20 +700,18 @@ CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+# CONFIG_ZSMALLOC is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
# CONFIG_DEBUG_VMALLOC is not set
-# CONFIG_LOWMEM_CHECK is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_UACCESS_WITH_MEMCPY is not set
# CONFIG_SECCOMP is not set
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -756,6 +756,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+# CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST is not set
# CONFIG_CPU_FREQ_GOV_SLP is not set
CONFIG_CPU_FREQ_DVFS_MONITOR=y
CONFIG_CPU_IDLE=y
@@ -807,6 +808,7 @@ CONFIG_ARCH_HAS_OPP=y
CONFIG_PM_OPP=y
CONFIG_PM_RUNTIME_CLK=y
# CONFIG_SUSPEND_TIME is not set
+CONFIG_CPU_PM=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -849,6 +851,8 @@ CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
@@ -1195,6 +1199,7 @@ CONFIG_WIRELESS_EXT_SYSFS=y
# CONFIG_LIB80211 is not set
# CONFIG_CFG80211_ALLOW_RECONNECT is not set
# CONFIG_MAC80211 is not set
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
CONFIG_RFKILL_PM=y
@@ -1208,6 +1213,14 @@ CONFIG_RFKILL_PM=y
#
# Device Drivers
#
+CONFIG_MALI400=y
+CONFIG_MALI_VER_R3P2=y
+# CONFIG_MALI400_DEBUG is not set
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_DVFS=y
+CONFIG_MALI400_UMP=y
+# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_UMP_DEBUG is not set
#
# Generic Driver Options
@@ -1263,7 +1276,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_SENSORS_APDS990X is not set
# CONFIG_HMC6352 is not set
# CONFIG_SENSORS_AK8975 is not set
-# CONFIG_SENSORS_AK8963 is not set
# CONFIG_DS1682 is not set
# CONFIG_TI_DAC7512 is not set
CONFIG_UID_STAT=y
@@ -1273,19 +1285,24 @@ CONFIG_UID_STAT=y
# CONFIG_JACK_MON is not set
# CONFIG_UART_SELECT is not set
# CONFIG_SWITCH_DUAL_MODEM is not set
-# CONFIG_SWITCH_USB_PATH_AUTO is not set
# CONFIG_WIMAX_CMC is not set
# CONFIG_SEC_DEV_JACK is not set
# CONFIG_MUIC_DET_JACK is not set
# CONFIG_FM34_WE395 is not set
# CONFIG_AUDIENCE_ES305 is not set
# CONFIG_2MIC_FM34_WE395 is not set
+# CONFIG_MUIC_MAX77693_SEPARATE_MHL_PORT is not set
+CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK=y
+CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK=y
+# CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK is not set
# CONFIG_USBHUB_USB3503 is not set
# CONFIG_USBHUB_USB3503_OTG_CONN is not set
# CONFIG_USBHUB_USB3803 is not set
# CONFIG_PN544 is not set
+# CONFIG_STMPE811_ADC is not set
# CONFIG_MPU_SENSORS_MPU3050 is not set
# CONFIG_MPU_SENSORS_MPU6050 is not set
+CONFIG_UID_CPUTIME=y
# CONFIG_C2PORT is not set
#
@@ -1310,10 +1327,13 @@ CONFIG_SEC_MODEM=y
CONFIG_UMTS_MODEM_XMM6262=y
# CONFIG_CDMA_MODEM_CBP71 is not set
# CONFIG_CDMA_MODEM_CBP72 is not set
+# CONFIG_CDMA_MODEM_CBP82 is not set
# CONFIG_LTE_MODEM_CMC221 is not set
+# CONFIG_UMTS_MODEM_SS222 is not set
# CONFIG_CDMA_MODEM_MDM6600 is not set
# CONFIG_TDSCDMA_MODEM_SPRD8803 is not set
# CONFIG_GSM_MODEM_ESC6270 is not set
+# CONFIG_CDMA_MODEM_QSC6085 is not set
# CONFIG_LINK_DEVICE_MIPI is not set
# CONFIG_LINK_DEVICE_DPRAM is not set
# CONFIG_LINK_DEVICE_PLD is not set
@@ -1321,13 +1341,13 @@ CONFIG_UMTS_MODEM_XMM6262=y
CONFIG_LINK_DEVICE_HSIC=y
# CONFIG_LINK_DEVICE_C2C is not set
# CONFIG_LINK_DEVICE_SPI is not set
+# CONFIG_BOOT_DEVICE_SPI is not set
# CONFIG_WORKQUEUE_FRONT is not set
# CONFIG_IPC_CMC22x_OLD_RFS is not set
# CONFIG_SIPC_VER_5 is not set
# CONFIG_SIM_SLOT_SWITCH is not set
# CONFIG_LTE_MODEM_CMC220 is not set
# CONFIG_INTERNAL_MODEM_IF is not set
-# CONFIG_CDMA_MODEM_QSC6085 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -1408,18 +1428,25 @@ CONFIG_WLAN=y
# CONFIG_USB_NET_RNDIS_WLAN is not set
CONFIG_WIFI_CONTROL_FUNC=y
# CONFIG_ATH_COMMON is not set
+# CONFIG_B43LEGACY_DMA_AND_PIO_MODE is not set
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
# CONFIG_BCM4330 is not set
CONFIG_BCM4334=m
+# CONFIG_BCM4335 is not set
+# CONFIG_BCM4339 is not set
+# CONFIG_BCM4354 is not set
# CONFIG_BCM43241 is not set
+CONFIG_BROADCOM_WIFI=y
CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
CONFIG_BCMDHD_NVRAM_PATH="/system/etc/wifi/bcmdhd.cal"
CONFIG_BROADCOM_WIFI_RESERVED_MEM=y
CONFIG_WLAN_REGION_CODE=100
+CONFIG_WIFI_BROADCOM_COB=y
# CONFIG_HOSTAP is not set
# CONFIG_IWM is not set
# CONFIG_LIBERTAS is not set
# CONFIG_MWIFIEX is not set
-# CONFIG_LGUIWLAN is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -1481,8 +1508,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_SECBRIDGE is not set
CONFIG_INPUT_KEYRESET=y
# CONFIG_INPUT_FBSUSPEND is not set
-# CONFIG_INPUT_MPU6050 is not set
-# CONFIG_INPUT_MPU6050_POLLING is not set
#
# Input Device Drivers
@@ -1506,7 +1531,9 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_SENSORS_HALL=y
# CONFIG_KEYBOARD_CYPRESS_TOUCH is not set
+# CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -1564,7 +1591,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_S7301=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED=y
-# CONFIG_TOUCHSCREEN_CYPRESS_TMA46X is not set
+# CONFIG_TOUCHSCREEN_CYTTSP4 is not set
CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK=y
CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH=y
# CONFIG_KEYPAD_MELFAS_TOUCH is not set
@@ -1572,27 +1599,6 @@ CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH=y
CONFIG_INPUT_WACOM=y
# CONFIG_EPEN_WACOM_G5SP is not set
# CONFIG_EPEN_WACOM_G9PM is not set
-CONFIG_EPEN_WACOM_G9PL=y
-# CONFIG_RMI4_DEBUG is not set
-# CONFIG_RMI4_BUS is not set
-# CONFIG_RMI4_GENERIC is not set
-# CONFIG_RMI4_F09 is not set
-# CONFIG_RMI4_F1A is not set
-# CONFIG_RMI4_F11 is not set
-# CONFIG_RMI4_VIRTUAL_BUTTONS is not set
-# CONFIG_RMI4_F17 is not set
-# CONFIG_RMI4_F19 is not set
-# CONFIG_RMI4_F21 is not set
-# CONFIG_RMI4_F30 is not set
-# CONFIG_RMI4_F31 is not set
-# CONFIG_RMI4_F34 is not set
-# CONFIG_RMI4_F41 is not set
-# CONFIG_RMI4_F54 is not set
-# CONFIG_RMI4_SMB is not set
-# CONFIG_RMI4_I2C is not set
-# CONFIG_RMI4_SPI is not set
-# CONFIG_RMI4_DEV is not set
-# CONFIG_RMI4_FWLIB is not set
CONFIG_INPUT_MISC=y
# CONFIG_SENSORS_BH1721FVC is not set
# CONFIG_INPUT_AD714X is not set
@@ -1615,7 +1621,6 @@ CONFIG_INPUT_GPIO=y
# CONFIG_INPUT_FLIP is not set
# CONFIG_INPUT_KR3DH is not set
-
#
# Hardware I/O ports
#
@@ -1827,10 +1832,15 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17042_FUELGAUGE is not set
# CONFIG_BATTERY_MAX17047_FUELGAUGE is not set
CONFIG_BATTERY_MAX17047_C_FUELGAUGE=y
-CONFIG_BATTERY_MAX77693_CHARGER=y
# CONFIG_BATTERY_SMB136_CHARGER is not set
+CONFIG_BATTERY_MAX77693_CHARGER=y
+# CONFIG_BATTERY_WPC_CHARGER is not set
# CONFIG_BATTERY_SAMSUNG_P1X is not set
+# CONFIG_FUELGAUGE_DUMMY is not set
+# CONFIG_FUELGAUGE_MAX17048 is not set
+# CONFIG_CHARGER_DUMMY is not set
# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_SMB328 is not set
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
# CONFIG_TEST_POWER is not set
@@ -1853,16 +1863,13 @@ CONFIG_BATTERY_SAMSUNG=y
# CONFIG_SMB328_CHARGER is not set
# CONFIG_SMB347_CHARGER is not set
# CONFIG_CHARGER_MANAGER is not set
-CONFIG_SAMSUNG_LPM_MODE=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_CPU_THERMAL is not set
# CONFIG_SENSORS_EXYNOS4_TMU is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_CHARGER_NCP1851 is not set
-# CONFIG_FUELGAUGE_MAX17050 is not set
-# CONFIG_FUELGAUGE_MAX17050_COULOMB_COUNTING is not set
+
#
# Watchdog Device Drivers
#
@@ -2058,12 +2065,6 @@ CONFIG_VIDEO_IR_I2C=y
# CONFIG_VIDEO_TVP5150 is not set
# CONFIG_VIDEO_TVP7002 is not set
# CONFIG_VIDEO_VPX3220 is not set
-# CONFIG_VIDEO_S5K3H2 is not set
-# CONFIG_VIDEO_S5K3H7 is not set
-# CONFIG_VIDEO_S5K4E5 is not set
-# CONFIG_VIDEO_S5K6A3 is not set
-# CONFIG_S5K6A3_CSI_C is not set
-# CONFIG_S5K6A3_CSI_D is not set
# CONFIG_VIDEO_M5MO is not set
# CONFIG_VIDEO_M9MO is not set
# CONFIG_VIDEO_S5K5BAFX is not set
@@ -2071,12 +2072,12 @@ CONFIG_VIDEO_IR_I2C=y
# CONFIG_VIDEO_SR200PC20 is not set
# CONFIG_VIDEO_SR200PC20M is not set
CONFIG_VIDEO_ISX012=y
-CONFIG_VIDEO_SR130PC20=y
# CONFIG_VIDEO_SLP_S5K4ECGX is not set
# CONFIG_VIDEO_SLP_DB8131M is not set
# CONFIG_VIDEO_S5K4EA is not set
# CONFIG_VIDEO_S5C73M3 is not set
# CONFIG_VIDEO_SLP_S5C73M3 is not set
+CONFIG_VIDEO_SR130PC20=y
CONFIG_VIDEO_IMPROVE_STREAMOFF=y
#
@@ -2143,7 +2144,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
-CONFIG_MALI_400MP_UMP=y
CONFIG_VIDEO_SAMSUNG=y
CONFIG_VIDEO_SAMSUNG_V4L2=y
CONFIG_VIDEO_FIMC=y
@@ -2172,6 +2172,8 @@ CONFIG_LSI_HDMI_AUDIO_CH_EVENT=y
CONFIG_VIDEO_MFC5X=y
CONFIG_VIDEO_MFC_MAX_INSTANCE=4
# CONFIG_VIDEO_MFC5X_DEBUG is not set
+# CONFIG_VIDEO_MALI400MP is not set
+# CONFIG_VIDEO_UMP is not set
CONFIG_VIDEO_FIMG2D=y
# CONFIG_VIDEO_FIMG2D_DEBUG is not set
CONFIG_VIDEO_FIMG2D4X=y
@@ -2193,20 +2195,10 @@ CONFIG_VIDEO_SAMSUNG_MEMSIZE_JPEG=0
CONFIG_VIDEO_SAMSUNG_MEMSIZE_TVOUT=0
CONFIG_VIDEO_EXYNOS=y
CONFIG_VIDEO_EXYNOS_MEMSIZE_FIMC_IS=12288
-CONFIG_EXYNOS_MEDIA_DEVICE=y
-# CONFIG_VIDEO_EXYNOS_FIMC_LITE is not set
-
-#
-# Reserved memory configurations
-#
-CONFIG_VIDEO_SAMSUNG_MEMSIZE_FLITE0=10240
-CONFIG_VIDEO_SAMSUNG_MEMSIZE_FLITE1=10240
-# CONFIG_VIDEO_EXYNOS_MIPI_CSIS is not set
+# CONFIG_VIDEO_EXYNOS_FIMC_LITE is not set
# CONFIG_VIDEO_EXYNOS_TV is not set
# CONFIG_VIDEO_EXYNOS_ROTATOR is not set
-# CONFIG_VIDEO_EXYNOS_FIMC_IS is not set
-# CONFIG_VIDEO_EXYNOS_FIMC_IS_BAYER is not set
-CONFIG_MEDIA_EXYNOS=y
+# CONFIG_VIDEO_EXYNOS_FIMC_IS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
@@ -2223,29 +2215,14 @@ CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE=y
# CONFIG_ISDBT is not set
#
-# MUIC device
-#
-# CONFIG_STMPE811_ADC is not set
-CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK=y
-CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK=y
-
-#
# Graphics support
#
-# CONFIG_MALI_VER_BEFORE_R3P2 is not set
# CONFIG_DRM is not set
CONFIG_ION=y
CONFIG_ION_EXYNOS=y
CONFIG_ION_EXYNOS_CONTIGHEAP_SIZE=81920
# CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG is not set
-# CONFIG_VITHAR is not set
-CONFIG_MALI400=y
-CONFIG_MALI_VER_R3P2=y
-# CONFIG_MALI400_DEBUG is not set
-# CONFIG_MALI400_PROFILING is not set
-CONFIG_MALI_DVFS=y
-CONFIG_MALI400_UMP=y
-# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
@@ -2276,6 +2253,7 @@ CONFIG_FB_S5P_SPLASH_SCREEN=y
# CONFIG_FB_S5P_LCD_INIT is not set
# CONFIG_FB_S5P_DEBUG is not set
CONFIG_FB_S5P_VSYNC_THREAD=y
+# CONFIG_FB_S5P_VSYNC_SEND_UEVENTS is not set
CONFIG_FB_S5P_VSYNC_SYSFS=y
# CONFIG_FB_S5P_TRACE_UNDERRUN is not set
CONFIG_FB_S5P_DEFAULT_WINDOW=3
@@ -2284,12 +2262,18 @@ CONFIG_FB_S5P_NR_BUFFERS=2
CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMD=8192
CONFIG_FB_S5P_MDNIE=y
CONFIG_FB_MDNIE_PWM=y
-CONFIG_FB_EBOOK_PANEL_SCENARIO=y
CONFIG_FB_S5P_MIPI_DSIM=y
CONFIG_FB_BGRA_ORDER=y
# CONFIG_FB_RGBA_ORDER is not set
# CONFIG_FB_S5P_S6C1372 is not set
# CONFIG_FB_S5P_LD9040 is not set
+# CONFIG_FB_S5P_LMS501XX is not set
+# CONFIG_FB_S5P_DUMMY_MIPI_LCD is not set
+# CONFIG_FB_S5P_S6E8AA0 is not set
+# CONFIG_FB_S5P_EA8061 is not set
+# CONFIG_FB_S5P_S6EVR02 is not set
+# CONFIG_FB_S5P_S6D6AA1 is not set
+# CONFIG_FB_S5P_S6E63M0 is not set
CONFIG_FB_S5P_NT71391=y
# CONFIG_LCD_FREQ_SWITCH is not set
CONFIG_FB_S5P_EXTDSP=y
@@ -2298,10 +2282,10 @@ CONFIG_FB_S5P_EXTDSP_NR_BUFFERS=3
# CONFIG_S5P_DSIM_SWITCHABLE_DUAL_LCD is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_TMIO is not set
-# CONFIG_S5P_MIPI_DSI2 is not set
# CONFIG_FB_UDL is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX_PCI_GDC is not set
# CONFIG_FB_BROADSHEET is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
@@ -2353,7 +2337,6 @@ CONFIG_SND_JACK=y
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-# CONFIG_SND_DEBUG_VERBOSE is not set
# CONFIG_SND_RAWMIDI_SEQ is not set
# CONFIG_SND_OPL3_LIB_SEQ is not set
# CONFIG_SND_OPL4_LIB_SEQ is not set
@@ -2371,6 +2354,7 @@ CONFIG_SND_SOC=y
# CONFIG_SND_SOC_CACHE_LZO is not set
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SAMSUNG_I2S=y
+# CONFIG_SND_SOC_SAMSUNG_MIDAS_WM1811 is not set
CONFIG_SND_SOC_SAMSUNG_KONA_WM1811=y
# CONFIG_SND_SOC_SAMSUNG_USE_DMA_WRAPPER is not set
CONFIG_SND_SOC_SAMSUNG_I2S_SEC=y
@@ -2408,7 +2392,6 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
# CONFIG_HID_ACRUX_FF is not set
@@ -2485,7 +2468,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2554,7 +2537,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_STORAGE_ENE_UB6250 is not set
-# CONFIG_USB_UAS is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -2656,6 +2638,12 @@ CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_GADGET_S3C_OTGD=y
# CONFIG_USB_GADGET_PXA_U2O is not set
# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_CI13XXX_PCI is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_EG20T is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
#
@@ -2752,12 +2740,14 @@ CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_LT3593 is not set
# CONFIG_LEDS_SWITCH is not set
+# CONFIG_LEDS_MAX77693 is not set
# CONFIG_LEDS_AAT1290A is not set
# CONFIG_LEDS_TRIGGERS is not set
#
# LED Triggers
#
+# CONFIG_LEDS_TRIGGER_NOTIFICATION is not set
# CONFIG_NFC_DEVICES is not set
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
@@ -2870,14 +2860,14 @@ CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
CONFIG_ANDROID_TIMED_OUTPUT=y
# CONFIG_ANDROID_TIMED_GPIO is not set
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
+CONFIG_ANDROID_LMK_ADJ_RBTREE=y
# CONFIG_POHMELFS is not set
# CONFIG_LINE6_USB is not set
# CONFIG_USB_SERIAL_QUATECH2 is not set
# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-# CONFIG_XVMALLOC is not set
-# CONFIG_ZRAM is not set
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -2903,7 +2893,6 @@ CONFIG_CLKDEV_LOOKUP=y
CONFIG_VIBETONZ=y
CONFIG_MOTOR_DRV_MAX77693=y
# CONFIG_MOTOR_DRV_ISA1200 is not set
-# CONFIG_MOTOR_DRV_DRV2603 is not set
# CONFIG_FM_RADIO is not set
CONFIG_SENSORS_CORE=y
# CONFIG_SENSORS_AK8975C is not set
@@ -2911,10 +2900,7 @@ CONFIG_SENSORS_CORE=y
# CONFIG_SENSORS_BMP180 is not set
# CONFIG_SENSORS_CM3663 is not set
# CONFIG_SENSORS_PAS2M110 is not set
-CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=2
# CONFIG_SENSORS_BMA254 is not set
-CONFIG_SENSORS_YAS532=y
-CONFIG_SENSORS_YAS_ORI=y
# CONFIG_SENSORS_TAOS is not set
CONFIG_SENSORS_GP2A=y
# CONFIG_SENSORS_GP2A_ANALOG is not set
@@ -2927,6 +2913,9 @@ CONFIG_SENSOR_K3DH_INPUTDEV=y
# CONFIG_SENSORS_K3G is not set
# CONFIG_SENSORS_LSM330DLC is not set
# CONFIG_SENSORS_LPS331 is not set
+CONFIG_SENSORS_YAS532=y
+CONFIG_SENSORS_YAS_ORI=y
+CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=2
# CONFIG_SENSORS_SYSFS is not set
# CONFIG_SENSORS_SSP is not set
# CONFIG_SENSORS_SSP_LSM330 is not set
@@ -2948,13 +2937,13 @@ CONFIG_IR_REMOCON=y
CONFIG_IR_REMOCON_MC96=y
# CONFIG_EXTCON is not set
# CONFIG_BARCODE_EMUL is not set
+# CONFIG_SAMSUNG_PHONE_TTY is not set
CONFIG_MOBICORE_SUPPORT=y
# CONFIG_MOBICORE_DEBUG is not set
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
# CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR is not set
-# CONFIG_J4FS is not set
#
# File systems
@@ -2971,6 +2960,7 @@ CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_JBD2=y
# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
@@ -3033,6 +3023,10 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
# CONFIG_LOGFS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
@@ -3042,9 +3036,13 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -3142,7 +3140,6 @@ CONFIG_NLS_UTF8=y
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CPU_ID=y
-CONFIG_UID_CPUTIME=y
# CONFIG_PRINTK_PID is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
@@ -3288,6 +3285,9 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_IMA is not set
CONFIG_DEFAULT_SECURITY_SELINUX=y
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_DEFAULT_SECURITY="selinux"
CONFIG_CRYPTO=y
@@ -3388,6 +3388,8 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
@@ -3417,6 +3419,9 @@ CONFIG_ZLIB_DEFLATE=y
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=y
CONFIG_TEXTSEARCH_BM=y
@@ -3426,5 +3431,3 @@ CONFIG_HAS_DMA=y
CONFIG_CPU_RMAP=y
CONFIG_NLATTR=y
# CONFIG_AVERAGE is not set
-
-CONFIG_SENSORS_HALL=y
diff --git a/arch/arm/configs/cyanogenmod_n5110_defconfig b/arch/arm/configs/cyanogenmod_n5110_defconfig
index 64c01c7..800b023 100644
--- a/arch/arm/configs/cyanogenmod_n5110_defconfig
+++ b/arch/arm/configs/cyanogenmod_n5110_defconfig
@@ -70,6 +70,7 @@ CONFIG_GENERIC_IRQ_CHIP=y
# RCU Subsystem
#
CONFIG_TREE_PREEMPT_RCU=y
+# CONFIG_TINY_RCU is not set
CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_FANOUT=32
@@ -107,6 +108,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_CHECK_WARNING_STRICTLY is not set
CONFIG_SYSCTL=y
@@ -189,6 +191,8 @@ CONFIG_IOSCHED_ROW=y
CONFIG_IOSCHED_SIO=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_ROW is not set
+# CONFIG_DEFAULT_SIO is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_SPIN_TRYLOCK is not set
@@ -219,7 +223,7 @@ CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
-CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
CONFIG_FREEZER=y
#
@@ -355,6 +359,7 @@ CONFIG_S5P_DEV_USB_EHCI=y
CONFIG_S5P_DEV_FIMD_S5P=y
CONFIG_S5P_DEV_USBGADGET=y
CONFIG_S5P_MEM_CMA=y
+CONFIG_S5P_DEV_MIPI_DSI=y
# CONFIG_S5P_BTS is not set
# CONFIG_S3C_DEV_TSI is not set
CONFIG_ARCH_EXYNOS4=y
@@ -369,7 +374,6 @@ CONFIG_EXYNOS4_LOWPWR_IDLE=y
CONFIG_EXYNOS_MCT=y
CONFIG_EXYNOS_DEV_PD=y
CONFIG_EXYNOS4_DEV_FIMC_LITE=y
-CONFIG_EXYNOS4_DEV_FIMC_IS=y
CONFIG_EXYNOS4_SETUP_I2C1=y
CONFIG_EXYNOS4_SETUP_I2C3=y
CONFIG_EXYNOS4_SETUP_I2C4=y
@@ -385,13 +389,13 @@ CONFIG_EXYNOS4_SETUP_FIMC0=y
CONFIG_EXYNOS4_SETUP_FIMC1=y
CONFIG_EXYNOS4_SETUP_FIMC2=y
CONFIG_EXYNOS4_SETUP_FIMC3=y
-CONFIG_EXYNOS4_SETUP_FIMC_IS=y
CONFIG_EXYNOS4_SETUP_USB_PHY=y
CONFIG_EXYNOS4_SETUP_CSIS=y
CONFIG_EXYNOS4_SETUP_FB_S5P=y
CONFIG_EXYNOS4_SETUP_TVOUT=y
CONFIG_EXYNOS4_SETUP_THERMAL=y
# CONFIG_EXYNOS_SETUP_THERMAL is not set
+CONFIG_EXYNOS4_SETUP_MIPI_DSI=y
CONFIG_EXYNOS4_SETUP_JPEG=y
CONFIG_EXYNOS4_ENABLE_CLOCK_DOWN=y
CONFIG_EXYNOS4_CPUFREQ=y
@@ -420,7 +424,6 @@ CONFIG_BUSFREQ_QOS_1280X800=y
# CONFIG_BUSFREQ_DEBUG is not set
# CONFIG_BUSFREQ_L2_160M is not set
CONFIG_SEC_THERMISTOR=y
-# CONFIG_SEC_SUBTHERMISTOR is not set
# CONFIG_EXYNOS_SYSREG_PM is not set
CONFIG_ANDROID_WIP=y
# CONFIG_COMPACTION_RETRY is not set
@@ -449,6 +452,11 @@ CONFIG_TARGET_LOCALE_EUR=y
# CONFIG_TARGET_LOCALE_JPN is not set
# CONFIG_TARGET_LOCALE_CHN is not set
# CONFIG_TARGET_LOCALE_USA is not set
+CONFIG_MACH_KONA_EUR_OPEN=y
+# CONFIG_MACH_KONA_EUR_WIFI is not set
+# CONFIG_MACH_KONA_EUR_LTE is not set
+# CONFIG_MACH_KONALTE_USA_ATT is not set
+# CONFIG_MACH_KONA_KOR_WIFI is not set
# CONFIG_MACH_SMDK4X12 is not set
CONFIG_MACH_MIDAS=y
# CONFIG_MACH_M0 is not set
@@ -458,7 +466,6 @@ CONFIG_MACH_MIDAS=y
# CONFIG_MACH_GC1 is not set
# CONFIG_MACH_T0 is not set
CONFIG_MACH_KONA=y
-CONFIG_MACH_KONA_SENSOR=y
# CONFIG_MACH_IRON is not set
# CONFIG_MACH_GRANDE is not set
# CONFIG_MACH_BAFFIN is not set
@@ -471,21 +478,12 @@ CONFIG_MACH_KONA_SENSOR=y
CONFIG_KONA_01_BD=y
# CONFIG_IRON_BD is not set
# CONFIG_GRANDE_BD is not set
-# CONFIG_SLP is not set
-# CONFIG_MACH_REDWOOD is not set
-# CONFIG_GPS_BCM47511 is not set
-# CONFIG_GPS_BCM4752 is not set
-# CONFIG_GPS_GSD4T is not set
-# CONFIG_GPIO_NAPLES_00_BD is not set
-# CONFIG_SLP_DISP_DEBUG is not set
-# CONFIG_EXYNOS4_DEV_TMU is not set
-# CONFIG_BT_TIZEN is not set
# CONFIG_WRITEBACK_ENABLED is not set
CONFIG_EXYNOS_SOUND_PLATFORM_DATA=y
-CONFIG_USE_ADC_DET=y
# CONFIG_JACK_FET is not set
# CONFIG_JACK_GROUND_DET is not set
-# CONFIG_SAMSUNG_ANALOG_UART_SWITCH is not set
+CONFIG_USE_ADC_DET=y
+CONFIG_SAMSUNG_ANALOG_UART_SWITCH=1
# CONFIG_EXYNOS5_DEV_BTS is not set
#
@@ -539,6 +537,7 @@ CONFIG_SEC_LOG=y
CONFIG_SEC_LOG_NONCACHED=y
CONFIG_SEC_LOG_LAST_KMSG=y
CONFIG_EHCI_IRQ_DISTRIBUTION=y
+CONFIG_EHCI_MODEM_PORTNUM=2
#
# Samsung Modem Feature
@@ -566,7 +565,7 @@ CONFIG_SEC_MODEM_M0=y
#
# Connectivity Feature
#
-# CONFIG_GPS_BRCM_475X is not set
+CONFIG_GPS_BRCM_475X=y
# CONFIG_BT_CSR8811 is not set
# CONFIG_BT_BCM4330 is not set
CONFIG_BT_BCM4334=y
@@ -577,7 +576,6 @@ CONFIG_BT_MGMT=y
# Qualcomm Modem Feature
#
# CONFIG_QC_MODEM is not set
-# CONFIG_CPU_FREQ_TETHERING is not set
# CONFIG_MSM_SUBSYSTEM_RESTART is not set
# CONFIG_QC_MODEM_MDM9X15 is not set
# CONFIG_MDM_HSIC_PM is not set
@@ -586,6 +584,7 @@ CONFIG_SIM_DETECT=y
CONFIG_USB_CDFS_SUPPORT=y
# CONFIG_SAMSUNG_PRODUCT_SHIP is not set
# CONFIG_CORESIGHT_ETM is not set
+CONFIG_MACH_KONA_SENSOR=y
#
# Processor Type
@@ -640,6 +639,9 @@ CONFIG_ARM_ERRATA_761320=y
# CONFIG_ARM_ERRATA_761171 is not set
# CONFIG_ARM_ERRATA_762974 is not set
# CONFIG_ARM_ERRATA_763722 is not set
+CONFIG_ARM_ERRATA_764369=y
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
CONFIG_ARM_GIC=y
CONFIG_PL330=y
# CONFIG_FIQ_DEBUGGER is not set
@@ -650,8 +652,6 @@ CONFIG_PL330=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
-CONFIG_ARM_ERRATA_764369=y
-# CONFIG_PL310_ERRATA_769419 is not set
#
# Kernel Features
@@ -700,20 +700,18 @@ CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+# CONFIG_ZSMALLOC is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
# CONFIG_DEBUG_VMALLOC is not set
-# CONFIG_LOWMEM_CHECK is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_UACCESS_WITH_MEMCPY is not set
# CONFIG_SECCOMP is not set
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -758,6 +756,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+# CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST is not set
# CONFIG_CPU_FREQ_GOV_SLP is not set
CONFIG_CPU_FREQ_DVFS_MONITOR=y
CONFIG_CPU_IDLE=y
@@ -809,6 +808,7 @@ CONFIG_ARCH_HAS_OPP=y
CONFIG_PM_OPP=y
CONFIG_PM_RUNTIME_CLK=y
# CONFIG_SUSPEND_TIME is not set
+CONFIG_CPU_PM=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -851,6 +851,8 @@ CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
@@ -1197,6 +1199,7 @@ CONFIG_WIRELESS_EXT_SYSFS=y
# CONFIG_LIB80211 is not set
# CONFIG_CFG80211_ALLOW_RECONNECT is not set
# CONFIG_MAC80211 is not set
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
CONFIG_RFKILL_PM=y
@@ -1210,6 +1213,14 @@ CONFIG_RFKILL_PM=y
#
# Device Drivers
#
+CONFIG_MALI400=y
+CONFIG_MALI_VER_R3P2=y
+# CONFIG_MALI400_DEBUG is not set
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_DVFS=y
+CONFIG_MALI400_UMP=y
+# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_UMP_DEBUG is not set
#
# Generic Driver Options
@@ -1265,7 +1276,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_SENSORS_APDS990X is not set
# CONFIG_HMC6352 is not set
# CONFIG_SENSORS_AK8975 is not set
-# CONFIG_SENSORS_AK8963 is not set
# CONFIG_DS1682 is not set
# CONFIG_TI_DAC7512 is not set
CONFIG_UID_STAT=y
@@ -1275,19 +1285,24 @@ CONFIG_UID_STAT=y
# CONFIG_JACK_MON is not set
# CONFIG_UART_SELECT is not set
# CONFIG_SWITCH_DUAL_MODEM is not set
-# CONFIG_SWITCH_USB_PATH_AUTO is not set
# CONFIG_WIMAX_CMC is not set
# CONFIG_SEC_DEV_JACK is not set
# CONFIG_MUIC_DET_JACK is not set
# CONFIG_FM34_WE395 is not set
# CONFIG_AUDIENCE_ES305 is not set
# CONFIG_2MIC_FM34_WE395 is not set
+# CONFIG_MUIC_MAX77693_SEPARATE_MHL_PORT is not set
+CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK=y
+CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK=y
+# CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK is not set
# CONFIG_USBHUB_USB3503 is not set
# CONFIG_USBHUB_USB3503_OTG_CONN is not set
# CONFIG_USBHUB_USB3803 is not set
# CONFIG_PN544 is not set
+# CONFIG_STMPE811_ADC is not set
# CONFIG_MPU_SENSORS_MPU3050 is not set
# CONFIG_MPU_SENSORS_MPU6050 is not set
+CONFIG_UID_CPUTIME=y
# CONFIG_C2PORT is not set
#
@@ -1312,10 +1327,13 @@ CONFIG_SEC_MODEM=y
CONFIG_UMTS_MODEM_XMM6262=y
# CONFIG_CDMA_MODEM_CBP71 is not set
# CONFIG_CDMA_MODEM_CBP72 is not set
+# CONFIG_CDMA_MODEM_CBP82 is not set
# CONFIG_LTE_MODEM_CMC221 is not set
+# CONFIG_UMTS_MODEM_SS222 is not set
# CONFIG_CDMA_MODEM_MDM6600 is not set
# CONFIG_TDSCDMA_MODEM_SPRD8803 is not set
# CONFIG_GSM_MODEM_ESC6270 is not set
+# CONFIG_CDMA_MODEM_QSC6085 is not set
# CONFIG_LINK_DEVICE_MIPI is not set
# CONFIG_LINK_DEVICE_DPRAM is not set
# CONFIG_LINK_DEVICE_PLD is not set
@@ -1323,13 +1341,13 @@ CONFIG_UMTS_MODEM_XMM6262=y
CONFIG_LINK_DEVICE_HSIC=y
# CONFIG_LINK_DEVICE_C2C is not set
# CONFIG_LINK_DEVICE_SPI is not set
+# CONFIG_BOOT_DEVICE_SPI is not set
# CONFIG_WORKQUEUE_FRONT is not set
# CONFIG_IPC_CMC22x_OLD_RFS is not set
# CONFIG_SIPC_VER_5 is not set
# CONFIG_SIM_SLOT_SWITCH is not set
# CONFIG_LTE_MODEM_CMC220 is not set
# CONFIG_INTERNAL_MODEM_IF is not set
-# CONFIG_CDMA_MODEM_QSC6085 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -1410,18 +1428,25 @@ CONFIG_WLAN=y
# CONFIG_USB_NET_RNDIS_WLAN is not set
CONFIG_WIFI_CONTROL_FUNC=y
# CONFIG_ATH_COMMON is not set
+# CONFIG_B43LEGACY_DMA_AND_PIO_MODE is not set
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
# CONFIG_BCM4330 is not set
CONFIG_BCM4334=m
+# CONFIG_BCM4335 is not set
+# CONFIG_BCM4339 is not set
+# CONFIG_BCM4354 is not set
# CONFIG_BCM43241 is not set
+CONFIG_BROADCOM_WIFI=y
CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
CONFIG_BCMDHD_NVRAM_PATH="/system/etc/wifi/bcmdhd.cal"
CONFIG_BROADCOM_WIFI_RESERVED_MEM=y
CONFIG_WLAN_REGION_CODE=100
+CONFIG_WIFI_BROADCOM_COB=y
# CONFIG_HOSTAP is not set
# CONFIG_IWM is not set
# CONFIG_LIBERTAS is not set
# CONFIG_MWIFIEX is not set
-# CONFIG_LGUIWLAN is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -1483,8 +1508,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_SECBRIDGE is not set
CONFIG_INPUT_KEYRESET=y
# CONFIG_INPUT_FBSUSPEND is not set
-# CONFIG_INPUT_MPU6050 is not set
-# CONFIG_INPUT_MPU6050_POLLING is not set
#
# Input Device Drivers
@@ -1508,7 +1531,9 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_SENSORS_HALL=y
# CONFIG_KEYBOARD_CYPRESS_TOUCH is not set
+# CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -1566,7 +1591,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_S7301=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED=y
-# CONFIG_TOUCHSCREEN_CYPRESS_TMA46X is not set
+# CONFIG_TOUCHSCREEN_CYTTSP4 is not set
CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK=y
CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH=y
# CONFIG_KEYPAD_MELFAS_TOUCH is not set
@@ -1574,27 +1599,6 @@ CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH=y
CONFIG_INPUT_WACOM=y
# CONFIG_EPEN_WACOM_G5SP is not set
# CONFIG_EPEN_WACOM_G9PM is not set
-CONFIG_EPEN_WACOM_G9PL=y
-# CONFIG_RMI4_DEBUG is not set
-# CONFIG_RMI4_BUS is not set
-# CONFIG_RMI4_GENERIC is not set
-# CONFIG_RMI4_F09 is not set
-# CONFIG_RMI4_F1A is not set
-# CONFIG_RMI4_F11 is not set
-# CONFIG_RMI4_VIRTUAL_BUTTONS is not set
-# CONFIG_RMI4_F17 is not set
-# CONFIG_RMI4_F19 is not set
-# CONFIG_RMI4_F21 is not set
-# CONFIG_RMI4_F30 is not set
-# CONFIG_RMI4_F31 is not set
-# CONFIG_RMI4_F34 is not set
-# CONFIG_RMI4_F41 is not set
-# CONFIG_RMI4_F54 is not set
-# CONFIG_RMI4_SMB is not set
-# CONFIG_RMI4_I2C is not set
-# CONFIG_RMI4_SPI is not set
-# CONFIG_RMI4_DEV is not set
-# CONFIG_RMI4_FWLIB is not set
CONFIG_INPUT_MISC=y
# CONFIG_SENSORS_BH1721FVC is not set
# CONFIG_INPUT_AD714X is not set
@@ -1828,10 +1832,15 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17042_FUELGAUGE is not set
# CONFIG_BATTERY_MAX17047_FUELGAUGE is not set
CONFIG_BATTERY_MAX17047_C_FUELGAUGE=y
-CONFIG_BATTERY_MAX77693_CHARGER=y
# CONFIG_BATTERY_SMB136_CHARGER is not set
+CONFIG_BATTERY_MAX77693_CHARGER=y
+# CONFIG_BATTERY_WPC_CHARGER is not set
# CONFIG_BATTERY_SAMSUNG_P1X is not set
+# CONFIG_FUELGAUGE_DUMMY is not set
+# CONFIG_FUELGAUGE_MAX17048 is not set
+# CONFIG_CHARGER_DUMMY is not set
# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_SMB328 is not set
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
# CONFIG_TEST_POWER is not set
@@ -1854,16 +1863,13 @@ CONFIG_BATTERY_SAMSUNG=y
# CONFIG_SMB328_CHARGER is not set
# CONFIG_SMB347_CHARGER is not set
# CONFIG_CHARGER_MANAGER is not set
-CONFIG_SAMSUNG_LPM_MODE=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_CPU_THERMAL is not set
# CONFIG_SENSORS_EXYNOS4_TMU is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_CHARGER_NCP1851 is not set
-# CONFIG_FUELGAUGE_MAX17050 is not set
-# CONFIG_FUELGAUGE_MAX17050_COULOMB_COUNTING is not set
+
#
# Watchdog Device Drivers
#
@@ -2059,12 +2065,6 @@ CONFIG_VIDEO_IR_I2C=y
# CONFIG_VIDEO_TVP5150 is not set
# CONFIG_VIDEO_TVP7002 is not set
# CONFIG_VIDEO_VPX3220 is not set
-# CONFIG_VIDEO_S5K3H2 is not set
-# CONFIG_VIDEO_S5K3H7 is not set
-# CONFIG_VIDEO_S5K4E5 is not set
-# CONFIG_VIDEO_S5K6A3 is not set
-# CONFIG_S5K6A3_CSI_C is not set
-# CONFIG_S5K6A3_CSI_D is not set
# CONFIG_VIDEO_M5MO is not set
# CONFIG_VIDEO_M9MO is not set
# CONFIG_VIDEO_S5K5BAFX is not set
@@ -2072,12 +2072,12 @@ CONFIG_VIDEO_IR_I2C=y
# CONFIG_VIDEO_SR200PC20 is not set
# CONFIG_VIDEO_SR200PC20M is not set
CONFIG_VIDEO_ISX012=y
-CONFIG_VIDEO_SR130PC20=y
# CONFIG_VIDEO_SLP_S5K4ECGX is not set
# CONFIG_VIDEO_SLP_DB8131M is not set
# CONFIG_VIDEO_S5K4EA is not set
# CONFIG_VIDEO_S5C73M3 is not set
# CONFIG_VIDEO_SLP_S5C73M3 is not set
+CONFIG_VIDEO_SR130PC20=y
CONFIG_VIDEO_IMPROVE_STREAMOFF=y
#
@@ -2144,7 +2144,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
-CONFIG_MALI_400MP_UMP=y
CONFIG_VIDEO_SAMSUNG=y
CONFIG_VIDEO_SAMSUNG_V4L2=y
CONFIG_VIDEO_FIMC=y
@@ -2173,6 +2172,8 @@ CONFIG_LSI_HDMI_AUDIO_CH_EVENT=y
CONFIG_VIDEO_MFC5X=y
CONFIG_VIDEO_MFC_MAX_INSTANCE=4
# CONFIG_VIDEO_MFC5X_DEBUG is not set
+# CONFIG_VIDEO_MALI400MP is not set
+# CONFIG_VIDEO_UMP is not set
CONFIG_VIDEO_FIMG2D=y
# CONFIG_VIDEO_FIMG2D_DEBUG is not set
CONFIG_VIDEO_FIMG2D4X=y
@@ -2194,20 +2195,10 @@ CONFIG_VIDEO_SAMSUNG_MEMSIZE_JPEG=0
CONFIG_VIDEO_SAMSUNG_MEMSIZE_TVOUT=0
CONFIG_VIDEO_EXYNOS=y
CONFIG_VIDEO_EXYNOS_MEMSIZE_FIMC_IS=12288
-CONFIG_EXYNOS_MEDIA_DEVICE=y
-# CONFIG_VIDEO_EXYNOS_FIMC_LITE is not set
-
-#
-# Reserved memory configurations
-#
-CONFIG_VIDEO_SAMSUNG_MEMSIZE_FLITE0=10240
-CONFIG_VIDEO_SAMSUNG_MEMSIZE_FLITE1=10240
-# CONFIG_VIDEO_EXYNOS_MIPI_CSIS is not set
+# CONFIG_VIDEO_EXYNOS_FIMC_LITE is not set
# CONFIG_VIDEO_EXYNOS_TV is not set
# CONFIG_VIDEO_EXYNOS_ROTATOR is not set
-# CONFIG_VIDEO_EXYNOS_FIMC_IS is not set
-# CONFIG_VIDEO_EXYNOS_FIMC_IS_BAYER is not set
-CONFIG_MEDIA_EXYNOS=y
+# CONFIG_VIDEO_EXYNOS_FIMC_IS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
@@ -2224,29 +2215,14 @@ CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE=y
# CONFIG_ISDBT is not set
#
-# MUIC device
-#
-# CONFIG_STMPE811_ADC is not set
-CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK=y
-CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK=y
-
-#
# Graphics support
#
-# CONFIG_MALI_VER_BEFORE_R3P2 is not set
# CONFIG_DRM is not set
CONFIG_ION=y
CONFIG_ION_EXYNOS=y
CONFIG_ION_EXYNOS_CONTIGHEAP_SIZE=81920
# CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG is not set
-# CONFIG_VITHAR is not set
-CONFIG_MALI400=y
-CONFIG_MALI_VER_R3P2=y
-# CONFIG_MALI400_DEBUG is not set
-# CONFIG_MALI400_PROFILING is not set
-CONFIG_MALI_DVFS=y
-CONFIG_MALI400_UMP=y
-# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
@@ -2277,6 +2253,7 @@ CONFIG_FB_S5P_SPLASH_SCREEN=y
# CONFIG_FB_S5P_LCD_INIT is not set
# CONFIG_FB_S5P_DEBUG is not set
CONFIG_FB_S5P_VSYNC_THREAD=y
+# CONFIG_FB_S5P_VSYNC_SEND_UEVENTS is not set
CONFIG_FB_S5P_VSYNC_SYSFS=y
# CONFIG_FB_S5P_TRACE_UNDERRUN is not set
CONFIG_FB_S5P_DEFAULT_WINDOW=3
@@ -2285,12 +2262,18 @@ CONFIG_FB_S5P_NR_BUFFERS=2
CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMD=8192
CONFIG_FB_S5P_MDNIE=y
CONFIG_FB_MDNIE_PWM=y
-CONFIG_FB_EBOOK_PANEL_SCENARIO=y
CONFIG_FB_S5P_MIPI_DSIM=y
CONFIG_FB_BGRA_ORDER=y
# CONFIG_FB_RGBA_ORDER is not set
# CONFIG_FB_S5P_S6C1372 is not set
# CONFIG_FB_S5P_LD9040 is not set
+# CONFIG_FB_S5P_LMS501XX is not set
+# CONFIG_FB_S5P_DUMMY_MIPI_LCD is not set
+# CONFIG_FB_S5P_S6E8AA0 is not set
+# CONFIG_FB_S5P_EA8061 is not set
+# CONFIG_FB_S5P_S6EVR02 is not set
+# CONFIG_FB_S5P_S6D6AA1 is not set
+# CONFIG_FB_S5P_S6E63M0 is not set
CONFIG_FB_S5P_NT71391=y
# CONFIG_LCD_FREQ_SWITCH is not set
CONFIG_FB_S5P_EXTDSP=y
@@ -2299,10 +2282,10 @@ CONFIG_FB_S5P_EXTDSP_NR_BUFFERS=3
# CONFIG_S5P_DSIM_SWITCHABLE_DUAL_LCD is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_TMIO is not set
-# CONFIG_S5P_MIPI_DSI2 is not set
# CONFIG_FB_UDL is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX_PCI_GDC is not set
# CONFIG_FB_BROADSHEET is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
@@ -2372,6 +2355,7 @@ CONFIG_SND_SOC=y
# CONFIG_SND_SOC_CACHE_LZO is not set
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SAMSUNG_I2S=y
+# CONFIG_SND_SOC_SAMSUNG_MIDAS_WM1811 is not set
CONFIG_SND_SOC_SAMSUNG_KONA_WM1811=y
# CONFIG_SND_SOC_SAMSUNG_USE_DMA_WRAPPER is not set
CONFIG_SND_SOC_SAMSUNG_I2S_SEC=y
@@ -2485,7 +2469,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2554,7 +2538,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_STORAGE_ENE_UB6250 is not set
-# CONFIG_USB_UAS is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -2656,6 +2639,12 @@ CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_GADGET_S3C_OTGD=y
# CONFIG_USB_GADGET_PXA_U2O is not set
# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_CI13XXX_PCI is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_EG20T is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
#
@@ -2752,12 +2741,14 @@ CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_LT3593 is not set
# CONFIG_LEDS_SWITCH is not set
+# CONFIG_LEDS_MAX77693 is not set
# CONFIG_LEDS_AAT1290A is not set
# CONFIG_LEDS_TRIGGERS is not set
#
# LED Triggers
#
+# CONFIG_LEDS_TRIGGER_NOTIFICATION is not set
# CONFIG_NFC_DEVICES is not set
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
@@ -2870,14 +2861,14 @@ CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
CONFIG_ANDROID_TIMED_OUTPUT=y
# CONFIG_ANDROID_TIMED_GPIO is not set
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
+CONFIG_ANDROID_LMK_ADJ_RBTREE=y
# CONFIG_POHMELFS is not set
# CONFIG_LINE6_USB is not set
# CONFIG_USB_SERIAL_QUATECH2 is not set
# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-# CONFIG_XVMALLOC is not set
-# CONFIG_ZRAM is not set
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -2903,7 +2894,6 @@ CONFIG_CLKDEV_LOOKUP=y
CONFIG_VIBETONZ=y
CONFIG_MOTOR_DRV_MAX77693=y
# CONFIG_MOTOR_DRV_ISA1200 is not set
-# CONFIG_MOTOR_DRV_DRV2603 is not set
# CONFIG_FM_RADIO is not set
CONFIG_SENSORS_CORE=y
# CONFIG_SENSORS_AK8975C is not set
@@ -2911,10 +2901,7 @@ CONFIG_SENSORS_CORE=y
# CONFIG_SENSORS_BMP180 is not set
# CONFIG_SENSORS_CM3663 is not set
# CONFIG_SENSORS_PAS2M110 is not set
-CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=2
# CONFIG_SENSORS_BMA254 is not set
-CONFIG_SENSORS_YAS532=y
-CONFIG_SENSORS_YAS_ORI=y
# CONFIG_SENSORS_TAOS is not set
# CONFIG_SENSORS_GP2A is not set
# CONFIG_SENSORS_GP2A_ANALOG is not set
@@ -2927,6 +2914,9 @@ CONFIG_SENSOR_K3DH_INPUTDEV=y
# CONFIG_SENSORS_K3G is not set
# CONFIG_SENSORS_LSM330DLC is not set
# CONFIG_SENSORS_LPS331 is not set
+CONFIG_SENSORS_YAS532=y
+CONFIG_SENSORS_YAS_ORI=y
+CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=2
# CONFIG_SENSORS_SYSFS is not set
# CONFIG_SENSORS_SSP is not set
# CONFIG_SENSORS_SSP_LSM330 is not set
@@ -2948,13 +2938,13 @@ CONFIG_IR_REMOCON=y
CONFIG_IR_REMOCON_MC96=y
# CONFIG_EXTCON is not set
# CONFIG_BARCODE_EMUL is not set
+# CONFIG_SAMSUNG_PHONE_TTY is not set
CONFIG_MOBICORE_SUPPORT=y
# CONFIG_MOBICORE_DEBUG is not set
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
# CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR is not set
-# CONFIG_J4FS is not set
#
# File systems
@@ -2971,6 +2961,7 @@ CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_JBD2=y
# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
@@ -3033,6 +3024,10 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
# CONFIG_LOGFS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
@@ -3042,9 +3037,13 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -3142,7 +3141,6 @@ CONFIG_NLS_UTF8=y
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CPU_ID=y
-CONFIG_UID_CPUTIME=y
# CONFIG_PRINTK_PID is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
@@ -3288,6 +3286,9 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_IMA is not set
CONFIG_DEFAULT_SECURITY_SELINUX=y
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_DEFAULT_SECURITY="selinux"
CONFIG_CRYPTO=y
@@ -3388,6 +3389,8 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
@@ -3417,6 +3420,9 @@ CONFIG_ZLIB_DEFLATE=y
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=y
CONFIG_TEXTSEARCH_BM=y
@@ -3426,5 +3432,3 @@ CONFIG_HAS_DMA=y
CONFIG_CPU_RMAP=y
CONFIG_NLATTR=y
# CONFIG_AVERAGE is not set
-
-CONFIG_SENSORS_HALL=y
diff --git a/arch/arm/configs/cyanogenmod_n5120_defconfig b/arch/arm/configs/cyanogenmod_n5120_defconfig
index 541a128..445e41a 100644
--- a/arch/arm/configs/cyanogenmod_n5120_defconfig
+++ b/arch/arm/configs/cyanogenmod_n5120_defconfig
@@ -70,6 +70,7 @@ CONFIG_GENERIC_IRQ_CHIP=y
# RCU Subsystem
#
CONFIG_TREE_PREEMPT_RCU=y
+# CONFIG_TINY_RCU is not set
CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_FANOUT=32
@@ -107,6 +108,7 @@ CONFIG_RD_GZIP=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_CHECK_WARNING_STRICTLY is not set
CONFIG_SYSCTL=y
@@ -189,6 +191,8 @@ CONFIG_IOSCHED_ROW=y
CONFIG_IOSCHED_SIO=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_ROW is not set
+# CONFIG_DEFAULT_SIO is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_SPIN_TRYLOCK is not set
@@ -355,6 +359,7 @@ CONFIG_S5P_DEV_USB_EHCI=y
CONFIG_S5P_DEV_FIMD_S5P=y
CONFIG_S5P_DEV_USBGADGET=y
CONFIG_S5P_MEM_CMA=y
+CONFIG_S5P_DEV_MIPI_DSI=y
# CONFIG_S5P_BTS is not set
# CONFIG_S3C_DEV_TSI is not set
CONFIG_ARCH_EXYNOS4=y
@@ -369,7 +374,6 @@ CONFIG_EXYNOS4_LOWPWR_IDLE=y
CONFIG_EXYNOS_MCT=y
CONFIG_EXYNOS_DEV_PD=y
CONFIG_EXYNOS4_DEV_FIMC_LITE=y
-CONFIG_EXYNOS4_DEV_FIMC_IS=y
CONFIG_EXYNOS4_SETUP_I2C1=y
CONFIG_EXYNOS4_SETUP_I2C3=y
CONFIG_EXYNOS4_SETUP_I2C4=y
@@ -385,13 +389,13 @@ CONFIG_EXYNOS4_SETUP_FIMC0=y
CONFIG_EXYNOS4_SETUP_FIMC1=y
CONFIG_EXYNOS4_SETUP_FIMC2=y
CONFIG_EXYNOS4_SETUP_FIMC3=y
-CONFIG_EXYNOS4_SETUP_FIMC_IS=y
CONFIG_EXYNOS4_SETUP_USB_PHY=y
CONFIG_EXYNOS4_SETUP_CSIS=y
CONFIG_EXYNOS4_SETUP_FB_S5P=y
CONFIG_EXYNOS4_SETUP_TVOUT=y
CONFIG_EXYNOS4_SETUP_THERMAL=y
# CONFIG_EXYNOS_SETUP_THERMAL is not set
+CONFIG_EXYNOS4_SETUP_MIPI_DSI=y
CONFIG_EXYNOS4_SETUP_JPEG=y
CONFIG_EXYNOS4_ENABLE_CLOCK_DOWN=y
CONFIG_EXYNOS4_CPUFREQ=y
@@ -420,7 +424,6 @@ CONFIG_BUSFREQ_QOS_1280X800=y
# CONFIG_BUSFREQ_DEBUG is not set
# CONFIG_BUSFREQ_L2_160M is not set
CONFIG_SEC_THERMISTOR=y
-# CONFIG_SEC_SUBTHERMISTOR is not set
# CONFIG_EXYNOS_SYSREG_PM is not set
CONFIG_ANDROID_WIP=y
# CONFIG_COMPACTION_RETRY is not set
@@ -449,6 +452,11 @@ CONFIG_TARGET_LOCALE_EUR=y
# CONFIG_TARGET_LOCALE_JPN is not set
# CONFIG_TARGET_LOCALE_CHN is not set
# CONFIG_TARGET_LOCALE_USA is not set
+# CONFIG_MACH_KONA_EUR_OPEN is not set
+# CONFIG_MACH_KONA_EUR_WIFI is not set
+CONFIG_MACH_KONA_EUR_LTE=y
+# CONFIG_MACH_KONALTE_USA_ATT is not set
+# CONFIG_MACH_KONA_KOR_WIFI is not set
# CONFIG_MACH_SMDK4X12 is not set
CONFIG_MACH_MIDAS=y
# CONFIG_MACH_M0 is not set
@@ -458,7 +466,6 @@ CONFIG_MACH_MIDAS=y
# CONFIG_MACH_GC1 is not set
# CONFIG_MACH_T0 is not set
CONFIG_MACH_KONA=y
-CONFIG_MACH_KONA_SENSOR=y
# CONFIG_MACH_IRON is not set
# CONFIG_MACH_GRANDE is not set
# CONFIG_MACH_BAFFIN is not set
@@ -469,24 +476,14 @@ CONFIG_MACH_KONA_SENSOR=y
# CONFIG_T0_04_BD is not set
# CONFIG_KONA_00_BD is not set
CONFIG_KONA_01_BD=y
-CONFIG_MACH_KONA_EUR_LTE=y
# CONFIG_IRON_BD is not set
# CONFIG_GRANDE_BD is not set
-# CONFIG_SLP is not set
-# CONFIG_MACH_REDWOOD is not set
-# CONFIG_GPS_BCM47511 is not set
-# CONFIG_GPS_BCM4752 is not set
-# CONFIG_GPS_GSD4T is not set
-# CONFIG_GPIO_NAPLES_00_BD is not set
-# CONFIG_SLP_DISP_DEBUG is not set
-# CONFIG_EXYNOS4_DEV_TMU is not set
-# CONFIG_BT_TIZEN is not set
# CONFIG_WRITEBACK_ENABLED is not set
CONFIG_EXYNOS_SOUND_PLATFORM_DATA=y
-CONFIG_USE_ADC_DET=y
# CONFIG_JACK_FET is not set
# CONFIG_JACK_GROUND_DET is not set
-# CONFIG_SAMSUNG_ANALOG_UART_SWITCH is not set
+CONFIG_USE_ADC_DET=y
+CONFIG_SAMSUNG_ANALOG_UART_SWITCH=1
# CONFIG_EXYNOS5_DEV_BTS is not set
#
@@ -523,7 +520,6 @@ CONFIG_EXYNOS4_MSHC_DDR=y
#
CONFIG_SEC_DEBUG=y
CONFIG_SEC_DEBUG_SCHED_LOG=y
-CONFIG_SEC_DEBUG_HRTIMER_LOG=y
# CONFIG_SEC_DEBUG_SOFTIRQ_LOG is not set
CONFIG_SEC_DEBUG_SCHED_LOG_NONCACHED=y
# CONFIG_SEC_DEBUG_SEMAPHORE_LOG is not set
@@ -542,29 +538,6 @@ CONFIG_SEC_LOG_LAST_KMSG=y
CONFIG_EHCI_IRQ_DISTRIBUTION=y
#
-# Samsung Modem Feature
-#
-# CONFIG_LTE_VIA_SWITCH is not set
-# CONFIG_SEC_DUAL_MODEM_MODE is not set
-# CONFIG_SEC_MODEM_M0_C2C is not set
-# CONFIG_SEC_MODEM_M0 is not set
-# CONFIG_SEC_MODEM_M0_CTC is not set
-# CONFIG_SEC_MODEM_T0_CU_DUOS is not set
-# CONFIG_SEC_MODEM_T0_OPEN_DUOS is not set
-# CONFIG_SEC_MODEM_M0_GRANDECTC is not set
-# CONFIG_SEC_MODEM_M1 is not set
-# CONFIG_SEC_MODEM_C1 is not set
-# CONFIG_SEC_MODEM_C1_LGT is not set
-# CONFIG_SEC_MODEM_M2 is not set
-# CONFIG_SEC_MODEM_U1 is not set
-# CONFIG_SEC_MODEM_U1_LGT is not set
-# CONFIG_SEC_MODEM_GAIA is not set
-# CONFIG_SEC_MODEM_IRON is not set
-# CONFIG_SEC_MODEM_P8LTE is not set
-# CONFIG_SEC_MODEM_T0_TD_DUAL is not set
-# CONFIG_SEC_MODEM_U1_SPR is not set
-
-#
# Connectivity Feature
#
# CONFIG_GPS_BRCM_475X is not set
@@ -578,16 +551,16 @@ CONFIG_BT_MGMT=y
# Qualcomm Modem Feature
#
CONFIG_QC_MODEM=y
-# CONFIG_CPU_FREQ_TETHERING is not set
-# CONFIG_MSM_SUBSYSTEM_RESTART is not set
-# CONFIG_QC_MODEM_MDM9X15 is not set
-# CONFIG_MDM_HSIC_PM is not set
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_QC_MODEM_MDM9X15=y
+CONFIG_MDM_HSIC_PM=y
# CONFIG_EMI_ERROR_RECOVERY is not set
CONFIG_SIM_DETECT=y
+CONFIG_QC_MODEM_M3=y
CONFIG_USB_CDFS_SUPPORT=y
-# CONFIG_SAMSUNG_PRODUCT_SHIP is not set
+CONFIG_SAMSUNG_PRODUCT_SHIP=y
# CONFIG_CORESIGHT_ETM is not set
-CONFIG_HSIC_EURONLY_APPLY=y
+CONFIG_MACH_KONA_SENSOR=y
#
# Processor Type
@@ -642,6 +615,9 @@ CONFIG_ARM_ERRATA_761320=y
# CONFIG_ARM_ERRATA_761171 is not set
# CONFIG_ARM_ERRATA_762974 is not set
# CONFIG_ARM_ERRATA_763722 is not set
+CONFIG_ARM_ERRATA_764369=y
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
CONFIG_ARM_GIC=y
CONFIG_PL330=y
# CONFIG_FIQ_DEBUGGER is not set
@@ -652,8 +628,6 @@ CONFIG_PL330=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
-CONFIG_ARM_ERRATA_764369=y
-# CONFIG_PL310_ERRATA_769419 is not set
#
# Kernel Features
@@ -699,23 +673,21 @@ CONFIG_MIGRATION=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
-# CONFIG_KSM is not set
+CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
+# CONFIG_ZSMALLOC is not set
CONFIG_CMA=y
# CONFIG_CMA_DEVELOPEMENT is not set
CONFIG_CMA_BEST_FIT=y
# CONFIG_DEBUG_VMALLOC is not set
-# CONFIG_LOWMEM_CHECK is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_UACCESS_WITH_MEMCPY is not set
# CONFIG_SECCOMP is not set
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -760,6 +732,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+# CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST is not set
# CONFIG_CPU_FREQ_GOV_SLP is not set
CONFIG_CPU_FREQ_DVFS_MONITOR=y
CONFIG_CPU_IDLE=y
@@ -811,6 +784,7 @@ CONFIG_ARCH_HAS_OPP=y
CONFIG_PM_OPP=y
CONFIG_PM_RUNTIME_CLK=y
# CONFIG_SUSPEND_TIME is not set
+CONFIG_CPU_PM=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -853,6 +827,8 @@ CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
@@ -877,6 +853,7 @@ CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
CONFIG_ANDROID_PARANOID_NETWORK=y
CONFIG_NET_ACTIVITY_STATS=y
CONFIG_NETWORK_SECMARK=y
@@ -893,6 +870,7 @@ CONFIG_NETFILTER_NETLINK_QUEUE=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_SECMARK is not set
CONFIG_NF_CONNTRACK_EVENTS=y
# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
CONFIG_NF_CT_PROTO_DCCP=y
@@ -923,6 +901,7 @@ CONFIG_NETFILTER_XT_CONNMARK=y
#
# Xtables targets
#
+# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set
# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
@@ -938,6 +917,7 @@ CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
# CONFIG_NETFILTER_XT_TARGET_TEE is not set
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
+# CONFIG_NETFILTER_XT_TARGET_SECMARK is not set
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
@@ -1024,6 +1004,7 @@ CONFIG_IP_NF_MANGLE=y
# CONFIG_IP_NF_TARGET_ECN is not set
# CONFIG_IP_NF_TARGET_TTL is not set
CONFIG_IP_NF_RAW=y
+# CONFIG_IP_NF_SECURITY is not set
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -1050,6 +1031,7 @@ CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
+# CONFIG_IP6_NF_SECURITY is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_RDS is not set
@@ -1193,6 +1175,7 @@ CONFIG_WIRELESS_EXT_SYSFS=y
# CONFIG_LIB80211 is not set
# CONFIG_CFG80211_ALLOW_RECONNECT is not set
# CONFIG_MAC80211 is not set
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
CONFIG_RFKILL_PM=y
@@ -1206,6 +1189,14 @@ CONFIG_RFKILL_PM=y
#
# Device Drivers
#
+CONFIG_MALI400=y
+CONFIG_MALI_VER_R3P2=y
+# CONFIG_MALI400_DEBUG is not set
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_DVFS=y
+CONFIG_MALI400_UMP=y
+# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_UMP_DEBUG is not set
#
# Generic Driver Options
@@ -1261,7 +1252,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_SENSORS_APDS990X is not set
# CONFIG_HMC6352 is not set
# CONFIG_SENSORS_AK8975 is not set
-# CONFIG_SENSORS_AK8963 is not set
# CONFIG_DS1682 is not set
# CONFIG_TI_DAC7512 is not set
CONFIG_UID_STAT=y
@@ -1271,19 +1261,24 @@ CONFIG_UID_STAT=y
# CONFIG_JACK_MON is not set
# CONFIG_UART_SELECT is not set
# CONFIG_SWITCH_DUAL_MODEM is not set
-# CONFIG_SWITCH_USB_PATH_AUTO is not set
# CONFIG_WIMAX_CMC is not set
# CONFIG_SEC_DEV_JACK is not set
# CONFIG_MUIC_DET_JACK is not set
# CONFIG_FM34_WE395 is not set
# CONFIG_AUDIENCE_ES305 is not set
# CONFIG_2MIC_FM34_WE395 is not set
+# CONFIG_MUIC_MAX77693_SEPARATE_MHL_PORT is not set
+CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK=y
+CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK=y
+# CONFIG_MUIC_MAX77693_SUPPORT_CAR_DOCK is not set
# CONFIG_USBHUB_USB3503 is not set
# CONFIG_USBHUB_USB3503_OTG_CONN is not set
# CONFIG_USBHUB_USB3803 is not set
# CONFIG_PN544 is not set
+# CONFIG_STMPE811_ADC is not set
# CONFIG_MPU_SENSORS_MPU3050 is not set
# CONFIG_MPU_SENSORS_MPU6050 is not set
+CONFIG_UID_CPUTIME=y
# CONFIG_C2PORT is not set
#
@@ -1304,28 +1299,6 @@ CONFIG_UID_STAT=y
# CONFIG_SENSORS_LIS3_I2C is not set
# CONFIG_SAMSUNG_C2C is not set
# CONFIG_SEC_MODEM is not set
-# CONFIG_UMTS_MODEM_XMM6260 is not set
-# CONFIG_UMTS_MODEM_XMM6262 is not set
-# CONFIG_CDMA_MODEM_CBP71 is not set
-# CONFIG_CDMA_MODEM_CBP72 is not set
-# CONFIG_LTE_MODEM_CMC221 is not set
-# CONFIG_CDMA_MODEM_MDM6600 is not set
-# CONFIG_TDSCDMA_MODEM_SPRD8803 is not set
-# CONFIG_GSM_MODEM_ESC6270 is not set
-# CONFIG_LINK_DEVICE_MIPI is not set
-# CONFIG_LINK_DEVICE_DPRAM is not set
-# CONFIG_LINK_DEVICE_PLD is not set
-# CONFIG_LINK_DEVICE_USB is not set
-# CONFIG_LINK_DEVICE_HSIC is not set
-# CONFIG_LINK_DEVICE_C2C is not set
-# CONFIG_LINK_DEVICE_SPI is not set
-# CONFIG_WORKQUEUE_FRONT is not set
-# CONFIG_IPC_CMC22x_OLD_RFS is not set
-# CONFIG_SIPC_VER_5 is not set
-# CONFIG_SIM_SLOT_SWITCH is not set
-# CONFIG_LTE_MODEM_CMC220 is not set
-# CONFIG_INTERNAL_MODEM_IF is not set
-# CONFIG_CDMA_MODEM_QSC6085 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -1406,18 +1379,25 @@ CONFIG_WLAN=y
# CONFIG_USB_NET_RNDIS_WLAN is not set
CONFIG_WIFI_CONTROL_FUNC=y
# CONFIG_ATH_COMMON is not set
+# CONFIG_B43LEGACY_DMA_AND_PIO_MODE is not set
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
# CONFIG_BCM4330 is not set
CONFIG_BCM4334=m
+# CONFIG_BCM4335 is not set
+# CONFIG_BCM4339 is not set
+# CONFIG_BCM4354 is not set
# CONFIG_BCM43241 is not set
+CONFIG_BROADCOM_WIFI=y
CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
CONFIG_BCMDHD_NVRAM_PATH="/system/etc/wifi/bcmdhd.cal"
CONFIG_BROADCOM_WIFI_RESERVED_MEM=y
CONFIG_WLAN_REGION_CODE=100
+CONFIG_WIFI_BROADCOM_COB=y
# CONFIG_HOSTAP is not set
# CONFIG_IWM is not set
# CONFIG_LIBERTAS is not set
# CONFIG_MWIFIEX is not set
-# CONFIG_LGUIWLAN is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -1431,9 +1411,35 @@ CONFIG_WLAN_REGION_CODE=100
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+# CONFIG_USB_NET_SMSC95XX is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
# CONFIG_USB_HSO is not set
+# CONFIG_USB_NET_INT51X1 is not set
# CONFIG_USB_CDC_PHONET is not set
# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+CONFIG_MSM_RMNET_USB=y
# CONFIG_WAN is not set
#
@@ -1479,8 +1485,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_SECBRIDGE is not set
CONFIG_INPUT_KEYRESET=y
# CONFIG_INPUT_FBSUSPEND is not set
-# CONFIG_INPUT_MPU6050 is not set
-# CONFIG_INPUT_MPU6050_POLLING is not set
#
# Input Device Drivers
@@ -1504,7 +1508,9 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_SENSORS_HALL=y
# CONFIG_KEYBOARD_CYPRESS_TOUCH is not set
+# CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -1562,7 +1568,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_S7301=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND=y
CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED=y
-# CONFIG_TOUCHSCREEN_CYPRESS_TMA46X is not set
+# CONFIG_TOUCHSCREEN_CYTTSP4 is not set
CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK=y
CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH=y
# CONFIG_KEYPAD_MELFAS_TOUCH is not set
@@ -1570,27 +1576,6 @@ CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH=y
CONFIG_INPUT_WACOM=y
# CONFIG_EPEN_WACOM_G5SP is not set
# CONFIG_EPEN_WACOM_G9PM is not set
-CONFIG_EPEN_WACOM_G9PL=y
-# CONFIG_RMI4_DEBUG is not set
-# CONFIG_RMI4_BUS is not set
-# CONFIG_RMI4_GENERIC is not set
-# CONFIG_RMI4_F09 is not set
-# CONFIG_RMI4_F1A is not set
-# CONFIG_RMI4_F11 is not set
-# CONFIG_RMI4_VIRTUAL_BUTTONS is not set
-# CONFIG_RMI4_F17 is not set
-# CONFIG_RMI4_F19 is not set
-# CONFIG_RMI4_F21 is not set
-# CONFIG_RMI4_F30 is not set
-# CONFIG_RMI4_F31 is not set
-# CONFIG_RMI4_F34 is not set
-# CONFIG_RMI4_F41 is not set
-# CONFIG_RMI4_F54 is not set
-# CONFIG_RMI4_SMB is not set
-# CONFIG_RMI4_I2C is not set
-# CONFIG_RMI4_SPI is not set
-# CONFIG_RMI4_DEV is not set
-# CONFIG_RMI4_FWLIB is not set
CONFIG_INPUT_MISC=y
# CONFIG_SENSORS_BH1721FVC is not set
# CONFIG_INPUT_AD714X is not set
@@ -1673,11 +1658,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y
#
# Diag Support
#
-# CONFIG_DIAG_CHAR is not set
+CONFIG_DIAG_CHAR=y
#
# DIAG traffic over USB
#
+CONFIG_DIAG_OVER_USB=y
#
# SDIO support for DIAG
@@ -1686,6 +1672,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
#
# HSIC support for DIAG
#
+CONFIG_DIAG_HSIC_PIPE=y
# CONFIG_TTY_PRINTK is not set
# CONFIG_HVC_DCC is not set
# CONFIG_IPMI_HANDLER is not set
@@ -1824,10 +1811,15 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17042_FUELGAUGE is not set
# CONFIG_BATTERY_MAX17047_FUELGAUGE is not set
CONFIG_BATTERY_MAX17047_C_FUELGAUGE=y
-CONFIG_BATTERY_MAX77693_CHARGER=y
# CONFIG_BATTERY_SMB136_CHARGER is not set
+CONFIG_BATTERY_MAX77693_CHARGER=y
+# CONFIG_BATTERY_WPC_CHARGER is not set
# CONFIG_BATTERY_SAMSUNG_P1X is not set
+# CONFIG_FUELGAUGE_DUMMY is not set
+# CONFIG_FUELGAUGE_MAX17048 is not set
+# CONFIG_CHARGER_DUMMY is not set
# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_SMB328 is not set
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
# CONFIG_TEST_POWER is not set
@@ -1850,16 +1842,13 @@ CONFIG_BATTERY_SAMSUNG=y
# CONFIG_SMB328_CHARGER is not set
# CONFIG_SMB347_CHARGER is not set
# CONFIG_CHARGER_MANAGER is not set
-CONFIG_SAMSUNG_LPM_MODE=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_CPU_THERMAL is not set
# CONFIG_SENSORS_EXYNOS4_TMU is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_CHARGER_NCP1851 is not set
-# CONFIG_FUELGAUGE_MAX17050 is not set
-# CONFIG_FUELGAUGE_MAX17050_COULOMB_COUNTING is not set
+
#
# Watchdog Device Drivers
#
@@ -2055,12 +2044,6 @@ CONFIG_VIDEO_IR_I2C=y
# CONFIG_VIDEO_TVP5150 is not set
# CONFIG_VIDEO_TVP7002 is not set
# CONFIG_VIDEO_VPX3220 is not set
-# CONFIG_VIDEO_S5K3H2 is not set
-# CONFIG_VIDEO_S5K3H7 is not set
-# CONFIG_VIDEO_S5K4E5 is not set
-# CONFIG_VIDEO_S5K6A3 is not set
-# CONFIG_S5K6A3_CSI_C is not set
-# CONFIG_S5K6A3_CSI_D is not set
# CONFIG_VIDEO_M5MO is not set
# CONFIG_VIDEO_M9MO is not set
# CONFIG_VIDEO_S5K5BAFX is not set
@@ -2068,12 +2051,12 @@ CONFIG_VIDEO_IR_I2C=y
# CONFIG_VIDEO_SR200PC20 is not set
# CONFIG_VIDEO_SR200PC20M is not set
CONFIG_VIDEO_ISX012=y
-CONFIG_VIDEO_SR130PC20=y
# CONFIG_VIDEO_SLP_S5K4ECGX is not set
# CONFIG_VIDEO_SLP_DB8131M is not set
# CONFIG_VIDEO_S5K4EA is not set
# CONFIG_VIDEO_S5C73M3 is not set
# CONFIG_VIDEO_SLP_S5C73M3 is not set
+CONFIG_VIDEO_SR130PC20=y
CONFIG_VIDEO_IMPROVE_STREAMOFF=y
#
@@ -2140,7 +2123,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
-CONFIG_MALI_400MP_UMP=y
CONFIG_VIDEO_SAMSUNG=y
CONFIG_VIDEO_SAMSUNG_V4L2=y
CONFIG_VIDEO_FIMC=y
@@ -2169,6 +2151,8 @@ CONFIG_LSI_HDMI_AUDIO_CH_EVENT=y
CONFIG_VIDEO_MFC5X=y
CONFIG_VIDEO_MFC_MAX_INSTANCE=4
# CONFIG_VIDEO_MFC5X_DEBUG is not set
+# CONFIG_VIDEO_MALI400MP is not set
+# CONFIG_VIDEO_UMP is not set
CONFIG_VIDEO_FIMG2D=y
# CONFIG_VIDEO_FIMG2D_DEBUG is not set
CONFIG_VIDEO_FIMG2D4X=y
@@ -2190,20 +2174,10 @@ CONFIG_VIDEO_SAMSUNG_MEMSIZE_JPEG=0
CONFIG_VIDEO_SAMSUNG_MEMSIZE_TVOUT=0
CONFIG_VIDEO_EXYNOS=y
CONFIG_VIDEO_EXYNOS_MEMSIZE_FIMC_IS=12288
-CONFIG_EXYNOS_MEDIA_DEVICE=y
-# CONFIG_VIDEO_EXYNOS_FIMC_LITE is not set
-
-#
-# Reserved memory configurations
-#
-CONFIG_VIDEO_SAMSUNG_MEMSIZE_FLITE0=10240
-CONFIG_VIDEO_SAMSUNG_MEMSIZE_FLITE1=10240
-# CONFIG_VIDEO_EXYNOS_MIPI_CSIS is not set
+# CONFIG_VIDEO_EXYNOS_FIMC_LITE is not set
# CONFIG_VIDEO_EXYNOS_TV is not set
# CONFIG_VIDEO_EXYNOS_ROTATOR is not set
-# CONFIG_VIDEO_EXYNOS_FIMC_IS is not set
-# CONFIG_VIDEO_EXYNOS_FIMC_IS_BAYER is not set
-CONFIG_MEDIA_EXYNOS=y
+# CONFIG_VIDEO_EXYNOS_FIMC_IS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
@@ -2220,29 +2194,14 @@ CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE=y
# CONFIG_ISDBT is not set
#
-# MUIC device
-#
-# CONFIG_STMPE811_ADC is not set
-CONFIG_MUIC_MAX77693_SUPPORT_OTG_AUDIO_DOCK=y
-CONFIG_MUIC_MAX77693_SUPPORT_SMART_DOCK=y
-
-#
# Graphics support
#
-# CONFIG_MALI_VER_BEFORE_R3P2 is not set
# CONFIG_DRM is not set
CONFIG_ION=y
CONFIG_ION_EXYNOS=y
CONFIG_ION_EXYNOS_CONTIGHEAP_SIZE=81920
# CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG is not set
-# CONFIG_VITHAR is not set
-CONFIG_MALI400=y
-CONFIG_MALI_VER_R3P2=y
-# CONFIG_MALI400_DEBUG is not set
-# CONFIG_MALI400_PROFILING is not set
-CONFIG_MALI_DVFS=y
-CONFIG_MALI400_UMP=y
-# CONFIG_MALI_SHARED_INTERRUPTS is not set
+# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
@@ -2273,6 +2232,7 @@ CONFIG_FB_S5P_SPLASH_SCREEN=y
# CONFIG_FB_S5P_LCD_INIT is not set
# CONFIG_FB_S5P_DEBUG is not set
CONFIG_FB_S5P_VSYNC_THREAD=y
+# CONFIG_FB_S5P_VSYNC_SEND_UEVENTS is not set
CONFIG_FB_S5P_VSYNC_SYSFS=y
# CONFIG_FB_S5P_TRACE_UNDERRUN is not set
CONFIG_FB_S5P_DEFAULT_WINDOW=3
@@ -2281,12 +2241,18 @@ CONFIG_FB_S5P_NR_BUFFERS=2
CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMD=8192
CONFIG_FB_S5P_MDNIE=y
CONFIG_FB_MDNIE_PWM=y
-CONFIG_FB_EBOOK_PANEL_SCENARIO=y
CONFIG_FB_S5P_MIPI_DSIM=y
CONFIG_FB_BGRA_ORDER=y
# CONFIG_FB_RGBA_ORDER is not set
# CONFIG_FB_S5P_S6C1372 is not set
# CONFIG_FB_S5P_LD9040 is not set
+# CONFIG_FB_S5P_LMS501XX is not set
+# CONFIG_FB_S5P_DUMMY_MIPI_LCD is not set
+# CONFIG_FB_S5P_S6E8AA0 is not set
+# CONFIG_FB_S5P_EA8061 is not set
+# CONFIG_FB_S5P_S6EVR02 is not set
+# CONFIG_FB_S5P_S6D6AA1 is not set
+# CONFIG_FB_S5P_S6E63M0 is not set
CONFIG_FB_S5P_NT71391=y
# CONFIG_LCD_FREQ_SWITCH is not set
CONFIG_FB_S5P_EXTDSP=y
@@ -2295,10 +2261,10 @@ CONFIG_FB_S5P_EXTDSP_NR_BUFFERS=3
# CONFIG_S5P_DSIM_SWITCHABLE_DUAL_LCD is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_TMIO is not set
-# CONFIG_S5P_MIPI_DSI2 is not set
# CONFIG_FB_UDL is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX_PCI_GDC is not set
# CONFIG_FB_BROADSHEET is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
@@ -2368,6 +2334,7 @@ CONFIG_SND_SOC=y
# CONFIG_SND_SOC_CACHE_LZO is not set
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SAMSUNG_I2S=y
+# CONFIG_SND_SOC_SAMSUNG_MIDAS_WM1811 is not set
CONFIG_SND_SOC_SAMSUNG_KONA_WM1811=y
# CONFIG_SND_SOC_SAMSUNG_USE_DMA_WRAPPER is not set
CONFIG_SND_SOC_SAMSUNG_I2S_SEC=y
@@ -2405,7 +2372,6 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
# CONFIG_HID_ACRUX_FF is not set
@@ -2482,7 +2448,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2551,7 +2517,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_STORAGE_ENE_UB6250 is not set
-# CONFIG_USB_UAS is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -2608,6 +2573,7 @@ CONFIG_USB_SERIAL_QUALCOMM=y
# CONFIG_USB_SERIAL_TI is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
+CONFIG_USB_SERIAL_WWAN=y
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
# CONFIG_USB_SERIAL_OPTICON is not set
@@ -2640,8 +2606,9 @@ CONFIG_USB_SERIAL_CSVT=y
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_YUREX is not set
-# CONFIG_USB_QCOM_DIAG_BRIDGE is not set
-# CONFIG_USB_QCOM_MDM_BRIDGE is not set
+CONFIG_USB_QCOM_DIAG_BRIDGE=y
+# CONFIG_USB_QCOM_DIAG_BRIDGE_TEST is not set
+CONFIG_USB_QCOM_MDM_BRIDGE=y
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
@@ -2653,6 +2620,12 @@ CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_GADGET_S3C_OTGD=y
# CONFIG_USB_GADGET_PXA_U2O is not set
# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_CI13XXX_PCI is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_EG20T is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
#
@@ -2749,12 +2722,14 @@ CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_LT3593 is not set
# CONFIG_LEDS_SWITCH is not set
+# CONFIG_LEDS_MAX77693 is not set
# CONFIG_LEDS_AAT1290A is not set
# CONFIG_LEDS_TRIGGERS is not set
#
# LED Triggers
#
+# CONFIG_LEDS_TRIGGER_NOTIFICATION is not set
# CONFIG_NFC_DEVICES is not set
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
@@ -2867,14 +2842,14 @@ CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
CONFIG_ANDROID_TIMED_OUTPUT=y
# CONFIG_ANDROID_TIMED_GPIO is not set
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
+CONFIG_ANDROID_LMK_ADJ_RBTREE=y
# CONFIG_POHMELFS is not set
# CONFIG_LINE6_USB is not set
# CONFIG_USB_SERIAL_QUATECH2 is not set
# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
# CONFIG_VT6656 is not set
# CONFIG_IIO is not set
-# CONFIG_XVMALLOC is not set
-# CONFIG_ZRAM is not set
# CONFIG_FB_SM7XX is not set
# CONFIG_LIRC_STAGING is not set
# CONFIG_EASYCAP is not set
@@ -2900,7 +2875,6 @@ CONFIG_CLKDEV_LOOKUP=y
CONFIG_VIBETONZ=y
CONFIG_MOTOR_DRV_MAX77693=y
# CONFIG_MOTOR_DRV_ISA1200 is not set
-# CONFIG_MOTOR_DRV_DRV2603 is not set
# CONFIG_FM_RADIO is not set
CONFIG_SENSORS_CORE=y
# CONFIG_SENSORS_AK8975C is not set
@@ -2908,10 +2882,7 @@ CONFIG_SENSORS_CORE=y
# CONFIG_SENSORS_BMP180 is not set
# CONFIG_SENSORS_CM3663 is not set
# CONFIG_SENSORS_PAS2M110 is not set
-CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=2
# CONFIG_SENSORS_BMA254 is not set
-CONFIG_SENSORS_YAS532=y
-CONFIG_SENSORS_YAS_ORI=y
# CONFIG_SENSORS_TAOS is not set
CONFIG_SENSORS_GP2A=y
# CONFIG_SENSORS_GP2A_ANALOG is not set
@@ -2924,6 +2895,9 @@ CONFIG_SENSOR_K3DH_INPUTDEV=y
# CONFIG_SENSORS_K3G is not set
# CONFIG_SENSORS_LSM330DLC is not set
# CONFIG_SENSORS_LPS331 is not set
+CONFIG_SENSORS_YAS532=y
+CONFIG_SENSORS_YAS_ORI=y
+CONFIG_INPUT_YAS_MAGNETOMETER_POSITION=2
# CONFIG_SENSORS_SYSFS is not set
# CONFIG_SENSORS_SSP is not set
# CONFIG_SENSORS_SSP_LSM330 is not set
@@ -2945,13 +2919,13 @@ CONFIG_IR_REMOCON=y
CONFIG_IR_REMOCON_MC96=y
# CONFIG_EXTCON is not set
# CONFIG_BARCODE_EMUL is not set
+# CONFIG_SAMSUNG_PHONE_TTY is not set
CONFIG_MOBICORE_SUPPORT=y
# CONFIG_MOBICORE_DEBUG is not set
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
# CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR is not set
-# CONFIG_J4FS is not set
#
# File systems
@@ -2968,6 +2942,7 @@ CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_JBD2=y
# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
@@ -3030,6 +3005,10 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
# CONFIG_LOGFS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
@@ -3039,9 +3018,13 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -3139,7 +3122,6 @@ CONFIG_NLS_UTF8=y
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CPU_ID=y
-CONFIG_UID_CPUTIME=y
# CONFIG_PRINTK_PID is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
@@ -3285,6 +3267,9 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_IMA is not set
CONFIG_DEFAULT_SECURITY_SELINUX=y
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_DEFAULT_SECURITY="selinux"
CONFIG_CRYPTO=y
@@ -3385,6 +3370,8 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
@@ -3414,6 +3401,9 @@ CONFIG_ZLIB_DEFLATE=y
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=y
CONFIG_TEXTSEARCH_BM=y
@@ -3423,5 +3413,3 @@ CONFIG_HAS_DMA=y
CONFIG_CPU_RMAP=y
CONFIG_NLATTR=y
# CONFIG_AVERAGE is not set
-
-CONFIG_SENSORS_HALL=y
diff --git a/arch/arm/configs/cyanogenmod_n7000_defconfig b/arch/arm/configs/cyanogenmod_n7000_defconfig
index 0ac33a0..ca6968c 100644
--- a/arch/arm/configs/cyanogenmod_n7000_defconfig
+++ b/arch/arm/configs/cyanogenmod_n7000_defconfig
@@ -685,7 +685,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
-# CONFIG_VMWARE_MVP is not set
#
# Boot options
@@ -1228,7 +1227,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_SENSORS_LIS3LV02D is not set
CONFIG_MISC_DEVICES=y
# CONFIG_AD525X_DPOT is not set
-# CONFIG_ANDROID_PMEM is not set
# CONFIG_INTEL_MID_PTI is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
@@ -2376,7 +2374,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
diff --git a/arch/arm/configs/cyanogenmod_n7100_defconfig b/arch/arm/configs/cyanogenmod_n7100_defconfig
index 9b0dd73..124066d 100644
--- a/arch/arm/configs/cyanogenmod_n7100_defconfig
+++ b/arch/arm/configs/cyanogenmod_n7100_defconfig
@@ -145,7 +145,7 @@ CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
@@ -688,8 +688,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -734,6 +732,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_ADAPTIVE is not set
CONFIG_CPU_FREQ_GOV_PEGASUSQ=y
+CONFIG_CPU_FREQ_GOV_PEGASUSQ_BOOST=y
# CONFIG_CPU_FREQ_GOV_SLP is not set
# CONFIG_CPU_FREQ_DVFS_MONITOR is not set
CONFIG_CPU_IDLE=y
@@ -2449,7 +2448,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -3107,6 +3106,7 @@ CONFIG_NLS_UTF8=y
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CPU_ID=y
+CONFIG_UID_CPUTIME=y
# CONFIG_PRINTK_PID is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
diff --git a/arch/arm/configs/cyanogenmod_n8000_defconfig b/arch/arm/configs/cyanogenmod_n8000_defconfig
index bb6f24e..45cf051 100644
--- a/arch/arm/configs/cyanogenmod_n8000_defconfig
+++ b/arch/arm/configs/cyanogenmod_n8000_defconfig
@@ -684,8 +684,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -2425,7 +2423,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
diff --git a/arch/arm/configs/cyanogenmod_n8013_defconfig b/arch/arm/configs/cyanogenmod_n8013_defconfig
index 37bc308..f55906c 100644
--- a/arch/arm/configs/cyanogenmod_n8013_defconfig
+++ b/arch/arm/configs/cyanogenmod_n8013_defconfig
@@ -663,8 +663,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -2385,7 +2383,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
diff --git a/arch/arm/configs/cyanogenmod_t0lte_defconfig b/arch/arm/configs/cyanogenmod_t0lte_defconfig
index b69d4fe..7a07860 100755
--- a/arch/arm/configs/cyanogenmod_t0lte_defconfig
+++ b/arch/arm/configs/cyanogenmod_t0lte_defconfig
@@ -687,8 +687,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -2438,7 +2436,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2891,7 +2889,7 @@ CONFIG_MOBICORE_SUPPORT=y
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
-CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR=m
+# CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR is not set
#
# File systems
diff --git a/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig b/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig
index 43e473a..4a914ff 100755
--- a/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig
+++ b/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig
@@ -687,8 +687,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
-CONFIG_VMWARE_MVP=y
-# CONFIG_VMWARE_MVP_DEBUG is not set
#
# Boot options
@@ -2438,7 +2436,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICEFS is not set
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
@@ -2891,7 +2889,7 @@ CONFIG_MOBICORE_SUPPORT=y
CONFIG_MOBICORE_API=y
CONFIG_IOMMU_SUPPORT=y
# CONFIG_FELICA is not set
-CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR=m
+# CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR is not set
#
# File systems
diff --git a/arch/arm/mach-exynos/board-m0-modems.c b/arch/arm/mach-exynos/board-m0-modems.c
index 4139c79..50d475e 100644
--- a/arch/arm/mach-exynos/board-m0-modems.c
+++ b/arch/arm/mach-exynos/board-m0-modems.c
@@ -28,7 +28,12 @@
#include <linux/usb/hcd.h>
#include <linux/usb/ehci_def.h>
+#ifdef CONFIG_SEC_MODEM_M0
+#include "../../../drivers/misc/modem_if/modem.h"
+#else
#include <linux/platform_data/modem.h>
+#endif
+
#include <mach/sec_modem.h>
extern int s3c_gpio_slp_cfgpin(unsigned int pin, unsigned int config);
diff --git a/arch/arm/mach-exynos/board-trats.c b/arch/arm/mach-exynos/board-trats.c
index cf725ab..ed62092 100644
--- a/arch/arm/mach-exynos/board-trats.c
+++ b/arch/arm/mach-exynos/board-trats.c
@@ -47,9 +47,6 @@
#ifdef CONFIG_JACK_MON
#include <linux/jack.h>
#endif
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
#include <linux/k3g.h>
#include <asm/mach/arch.h>
@@ -4844,53 +4841,6 @@ static struct platform_device s3c_device_i2c17 = {
};
#endif
-#ifdef CONFIG_ANDROID_PMEM
-static struct android_pmem_platform_data pmem_pdata = {
- .name = "pmem",
- .no_allocator = 1,
- .cached = 0,
- .start = 0,
- .size = 0
-};
-
-static struct android_pmem_platform_data pmem_gpu1_pdata = {
- .name = "pmem_gpu1",
- .no_allocator = 1,
- .cached = 0,
- .start = 0,
- .size = 0,
-};
-
-static struct platform_device pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = {
- .platform_data = &pmem_pdata},
-};
-
-static struct platform_device pmem_gpu1_device = {
- .name = "android_pmem",
- .id = 1,
- .dev = {
- .platform_data = &pmem_gpu1_pdata},
-};
-
-static void __init android_pmem_set_platdata(void)
-{
-#if defined(CONFIG_S5P_MEM_CMA)
- pmem_pdata.size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K;
- pmem_gpu1_pdata.size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K;
-#else
- pmem_pdata.start = (u32) s5p_get_media_memory_bank(S5P_MDEV_PMEM, 0);
- pmem_pdata.size = (u32) s5p_get_media_memsize_bank(S5P_MDEV_PMEM, 0);
- pmem_gpu1_pdata.start =
- (u32) s5p_get_media_memory_bank(S5P_MDEV_PMEM_GPU1, 0);
- pmem_gpu1_pdata.size =
- (u32) s5p_get_media_memsize_bank(S5P_MDEV_PMEM_GPU1, 0);
-#endif
-}
-#endif
-
/* USB EHCI */
#ifdef CONFIG_USB_EHCI_S5P
static struct s5p_ehci_platdata smdkc210_ehci_pdata;
@@ -5187,10 +5137,6 @@ static struct platform_device *smdkc210_devices[] __initdata = {
&ipc_spi_device,
#endif
-#ifdef CONFIG_ANDROID_PMEM
- &pmem_device,
- &pmem_gpu1_device,
-#endif
#ifdef CONFIG_VIDEO_FIMC
&s3c_device_fimc0,
&s3c_device_fimc1,
@@ -5350,20 +5296,6 @@ static void __init exynos4_reserve_mem(void)
.start = 0
},
#endif
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM
- {
- .name = "pmem",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K,
- .start = 0,
- },
-#endif
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1
- {
- .name = "pmem_gpu1",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K,
- .start = 0,
- },
-#endif
#ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMC0
{
.name = "fimc0",
@@ -5453,7 +5385,6 @@ static void __init exynos4_reserve_mem(void)
#ifdef CONFIG_DRM_EXYNOS
"exynos-drm=drm;"
#endif
- "android_pmem.0=pmem;android_pmem.1=pmem_gpu1;"
"s3c-fimc.0=fimc0;s3c-fimc.1=fimc1;s3c-fimc.2=fimc2;s3c-fimc.3=fimc3;"
"exynos4210-fimc.0=fimc0;exynos4210-fimc.1=fimc1;exynos4210-fimc.2=fimc2;exynos4210-fimc3=fimc3;"
#ifdef CONFIG_ION_EXYNOS
@@ -5726,9 +5657,6 @@ static void __init trats_machine_init(void)
s5p_device_jpeg.dev.parent = &exynos4_device_pd[PD_CAM].dev;
#endif
#endif
-#ifdef CONFIG_ANDROID_PMEM
- android_pmem_set_platdata();
-#endif
#ifdef CONFIG_VIDEO_FIMC
/* fimc */
s3c_fimc0_set_platdata(&fimc_plat);
diff --git a/arch/arm/mach-exynos/include/mach/busfreq_exynos4.h b/arch/arm/mach-exynos/include/mach/busfreq_exynos4.h
index f8f377d..ab75f55 100644
--- a/arch/arm/mach-exynos/include/mach/busfreq_exynos4.h
+++ b/arch/arm/mach-exynos/include/mach/busfreq_exynos4.h
@@ -27,6 +27,11 @@
#define PRIME_DMC_MAX_THRESHOLD 30
#define EXYNOS4412_DMC_MAX_THRESHOLD 30
#define EXYNOS4212_DMC_MAX_THRESHOLD 30
+#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_SP7160LTE) || defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1) || defined(CONFIG_MACH_T0)
+#define DECODING_LOAD 5
+#else
+#define DECODING_LOAD 10
+#endif
extern unsigned int up_threshold;
extern unsigned int ppmu_threshold;
diff --git a/arch/arm/mach-exynos/mach-px.c b/arch/arm/mach-exynos/mach-px.c
index eaec80f..cc26a75 100644
--- a/arch/arm/mach-exynos/mach-px.c
+++ b/arch/arm/mach-exynos/mach-px.c
@@ -57,9 +57,6 @@
#if defined(CONFIG_S5P_MEM_CMA)
#include <linux/cma.h>
#endif
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -5914,53 +5911,6 @@ static void __init mipi_fb_init(void)
}
#endif
-#ifdef CONFIG_ANDROID_PMEM
-static struct android_pmem_platform_data pmem_pdata = {
- .name = "pmem",
- .no_allocator = 1,
- .cached = 0,
- .start = 0,
- .size = 0
-};
-
-static struct android_pmem_platform_data pmem_gpu1_pdata = {
- .name = "pmem_gpu1",
- .no_allocator = 1,
- .cached = 0,
- .start = 0,
- .size = 0,
-};
-
-static struct platform_device pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = {
- .platform_data = &pmem_pdata},
-};
-
-static struct platform_device pmem_gpu1_device = {
- .name = "android_pmem",
- .id = 1,
- .dev = {
- .platform_data = &pmem_gpu1_pdata},
-};
-
-static void __init android_pmem_set_platdata(void)
-{
-#if defined(CONFIG_S5P_MEM_CMA)
- pmem_pdata.size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K;
- pmem_gpu1_pdata.size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K;
-#else
- pmem_pdata.start = (u32) s5p_get_media_memory_bank(S5P_MDEV_PMEM, 0);
- pmem_pdata.size = (u32) s5p_get_media_memsize_bank(S5P_MDEV_PMEM, 0);
- pmem_gpu1_pdata.start =
- (u32) s5p_get_media_memory_bank(S5P_MDEV_PMEM_GPU1, 0);
- pmem_gpu1_pdata.size =
- (u32) s5p_get_media_memsize_bank(S5P_MDEV_PMEM_GPU1, 0);
-#endif
-}
-#endif
-
/* USB EHCI */
#ifdef CONFIG_USB_EHCI_S5P
static struct s5p_ehci_platdata smdkc210_ehci_pdata;
@@ -6753,10 +6703,6 @@ static struct platform_device *smdkc210_devices[] __initdata = {
#ifdef CONFIG_BATTERY_SEC_PX
&sec_battery_device,
#endif
-#ifdef CONFIG_ANDROID_PMEM
- &pmem_device,
- &pmem_gpu1_device,
-#endif
#ifdef CONFIG_INTERNAL_MODEM_IF
&sec_idpram_pm_device,
@@ -7132,20 +7078,6 @@ static void __init exynos4_cma_region_reserve(struct cma_region *regions_normal,
static void __init exynos4_reserve_mem(void)
{
static struct cma_region regions[] = {
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM
- {
- .name = "pmem",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K,
- .start = 0,
- },
-#endif
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1
- {
- .name = "pmem_gpu1",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K,
- .start = 0,
- },
-#endif
#ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMD
{
.name = "fimd",
@@ -7245,7 +7177,6 @@ static void __init exynos4_reserve_mem(void)
};
static const char map[] __initconst =
- "android_pmem.0=pmem;android_pmem.1=pmem_gpu1;"
"s3cfb.0=fimd;exynos4-fb.0=fimd;samsung-pd.1=fimd;"
"s3c-fimc.0=fimc0;s3c-fimc.1=fimc1;s3c-fimc.2=fimc2;s3c-fimc.3=fimc3;"
"exynos4210-fimc.0=fimc0;exynos4210-fimc.1=fimc1;exynos4210-fimc.2=fimc2;exynos4210-fimc.3=fimc3;"
@@ -7674,9 +7605,6 @@ static void __init smdkc210_machine_init(void)
s3c24xx_ts1_set_platdata(&s3c_ts_platform);
#endif
#endif
-#ifdef CONFIG_ANDROID_PMEM
- android_pmem_set_platdata();
-#endif
#ifdef CONFIG_VIDEO_FIMC
/* fimc */
s3c_fimc0_set_platdata(&fimc_plat);
diff --git a/arch/arm/mach-exynos/mach-smdk5210.c b/arch/arm/mach-exynos/mach-smdk5210.c
index 16ccba4..9ed28fa 100644
--- a/arch/arm/mach-exynos/mach-smdk5210.c
+++ b/arch/arm/mach-exynos/mach-smdk5210.c
@@ -947,20 +947,6 @@ static void __init exynos5_cma_region_reserve(
static void __init exynos5_reserve_mem(void)
{
static struct cma_region regions[] = {
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM
- {
- .name = "pmem",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K,
- .start = 0,
- },
-#endif
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1
- {
- .name = "pmem_gpu1",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K,
- .start = 0,
- },
-#endif
#ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMD
{
.name = "fimd",
@@ -1021,7 +1007,6 @@ static void __init exynos5_reserve_mem(void)
},
};
static const char map[] __initconst =
- "android_pmem.0=pmem;android_pmem.1=pmem_gpu1;"
"s3cfb.0=fimd;"
"exynos-gsc.0=gsc0;exynos-gsc.1=gsc1;exynos-gsc.2=gsc2;exynos-gsc.3=gsc3;"
"ion-exynos=fimd,gsc0,gsc1,gsc2,gsc3;"
diff --git a/arch/arm/mach-exynos/mach-u1.c b/arch/arm/mach-exynos/mach-u1.c
index ab756ab..ba440d2 100644
--- a/arch/arm/mach-exynos/mach-u1.c
+++ b/arch/arm/mach-exynos/mach-u1.c
@@ -55,9 +55,6 @@
#if defined(CONFIG_S5P_MEM_CMA)
#include <linux/cma.h>
#endif
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -198,7 +195,7 @@
static struct wacom_g5_callbacks *wacom_callbacks;
#endif /* CONFIG_EPEN_WACOM_G5SP */
-#ifdef CONFIG_KEYBOARD_CYPRESS_TOUCH
+#if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH) || defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN)
#include <linux/i2c/touchkey_i2c.h>
#endif
@@ -3095,7 +3092,11 @@ REGULATOR_INIT(ldo17, "VTF_2.8V", 2800000, 2800000, 0,
REGULATOR_INIT(ldo18, "TOUCH_LED_3.3V", 3300000, 3300000, 0,
REGULATOR_CHANGE_STATUS, 1);
#else
+#if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN) && defined(CONFIG_TOUCHKEY_BLN)
+REGULATOR_INIT(ldo18, "TOUCH_LED_3.3V", 2500000, 3300000, 0,
+#else
REGULATOR_INIT(ldo18, "TOUCH_LED_3.3V", 3000000, 3300000, 0,
+#endif
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, 1);
#endif
REGULATOR_INIT(ldo21, "VDDQ_M1M2_1.2V", 1200000, 1200000, 1,
@@ -6194,7 +6195,7 @@ static void p6_wacom_register_callbacks(struct wacom_g5_callbacks *cb)
#ifdef CONFIG_S3C_DEV_I2C8_EMUL
static struct i2c_board_info i2c_devs8_emul[];
#endif
-#ifdef CONFIG_KEYBOARD_CYPRESS_TOUCH
+#if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH) || defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN)
static void touchkey_init_hw(void)
{
gpio_request(GPIO_3_TOUCH_INT, "3_TOUCH_INT");
@@ -6295,7 +6296,7 @@ static struct touchkey_platform_data touchkey_pdata = {
.power_on = touchkey_power_on,
.led_power_on = touchkey_led_power_on,
};
-#endif /*CONFIG_KEYBOARD_CYPRESS_TOUCH*/
+#endif /*(CONFIG_KEYBOARD_CYPRESS_TOUCH) || (CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN)*/
@@ -6448,7 +6449,7 @@ struct platform_device s3c_device_i2c8 = {
/* I2C8 */
static struct i2c_board_info i2c_devs8_emul[] = {
-#ifdef CONFIG_KEYBOARD_CYPRESS_TOUCH
+#if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH) || defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN)
{
I2C_BOARD_INFO("sec_touchkey", 0x20),
.platform_data = &touchkey_pdata,
@@ -7128,53 +7129,6 @@ static void __init mipi_fb_init(void)
}
#endif
-#ifdef CONFIG_ANDROID_PMEM
-static struct android_pmem_platform_data pmem_pdata = {
- .name = "pmem",
- .no_allocator = 1,
- .cached = 0,
- .start = 0,
- .size = 0
-};
-
-static struct android_pmem_platform_data pmem_gpu1_pdata = {
- .name = "pmem_gpu1",
- .no_allocator = 1,
- .cached = 0,
- .start = 0,
- .size = 0,
-};
-
-static struct platform_device pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = {
- .platform_data = &pmem_pdata},
-};
-
-static struct platform_device pmem_gpu1_device = {
- .name = "android_pmem",
- .id = 1,
- .dev = {
- .platform_data = &pmem_gpu1_pdata},
-};
-
-static void __init android_pmem_set_platdata(void)
-{
-#if defined(CONFIG_S5P_MEM_CMA)
- pmem_pdata.size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K;
- pmem_gpu1_pdata.size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K;
-#else
- pmem_pdata.start = (u32) s5p_get_media_memory_bank(S5P_MDEV_PMEM, 0);
- pmem_pdata.size = (u32) s5p_get_media_memsize_bank(S5P_MDEV_PMEM, 0);
- pmem_gpu1_pdata.start =
- (u32) s5p_get_media_memory_bank(S5P_MDEV_PMEM_GPU1, 0);
- pmem_gpu1_pdata.size =
- (u32) s5p_get_media_memsize_bank(S5P_MDEV_PMEM_GPU1, 0);
-#endif
-}
-#endif
-
/* USB EHCI */
#ifdef CONFIG_USB_EHCI_S5P
static struct s5p_ehci_platdata smdkc210_ehci_pdata;
@@ -7479,10 +7433,6 @@ static struct platform_device *smdkc210_devices[] __initdata = {
&s5p_device_cec,
&s5p_device_hpd,
#endif
-#ifdef CONFIG_ANDROID_PMEM
- &pmem_device,
- &pmem_gpu1_device,
-#endif
#ifdef CONFIG_VIDEO_FIMC
&s3c_device_fimc0,
&s3c_device_fimc1,
@@ -7645,20 +7595,6 @@ static void __init exynos4_cma_region_reserve(struct cma_region *regions_normal,
static void __init exynos4_reserve_mem(void)
{
static struct cma_region regions[] = {
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM
- {
- .name = "pmem",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K,
- .start = 0,
- },
-#endif
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1
- {
- .name = "pmem_gpu1",
- .size = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K,
- .start = 0,
- },
-#endif
#ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMD
{
.name = "fimd",
@@ -7766,7 +7702,6 @@ static void __init exynos4_reserve_mem(void)
};
static const char map[] __initconst =
- "android_pmem.0=pmem;android_pmem.1=pmem_gpu1;"
"s3cfb.0=fimd;exynos4-fb.0=fimd;samsung-pd.1=fimd;"
"s3c-fimc.0=fimc0;s3c-fimc.1=fimc1;s3c-fimc.2=fimc2;s3c-fimc.3=fimc3;"
"exynos4210-fimc.0=fimc0;exynos4210-fimc.1=fimc1;"
@@ -7983,7 +7918,7 @@ static void __init smdkc210_machine_init(void)
ARRAY_SIZE(tuna_i2c15_boardinfo));
#endif
#ifdef CONFIG_S3C_DEV_I2C8_EMUL
-#ifdef CONFIG_KEYBOARD_CYPRESS_TOUCH
+#if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH) || defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN)
touchkey_init_hw();
#endif
i2c_register_board_info(8, i2c_devs8_emul, ARRAY_SIZE(i2c_devs8_emul));
@@ -8095,9 +8030,6 @@ static void __init smdkc210_machine_init(void)
s3c24xx_ts1_set_platdata(&s3c_ts_platform);
#endif
#endif
-#ifdef CONFIG_ANDROID_PMEM
- android_pmem_set_platdata();
-#endif
#ifdef CONFIG_VIDEO_FIMC
/* fimc */
s3c_fimc0_set_platdata(&fimc_plat);
diff --git a/arch/arm/mach-exynos/reserve_mem-exynos4.c b/arch/arm/mach-exynos/reserve_mem-exynos4.c
index c48c64f..bd0d332 100644
--- a/arch/arm/mach-exynos/reserve_mem-exynos4.c
+++ b/arch/arm/mach-exynos/reserve_mem-exynos4.c
@@ -49,28 +49,6 @@ struct s5p_media_device media_devs[] = {
},
#endif
-#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS)
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM
- {
- .id = S5P_MDEV_PMEM,
- .name = "pmem",
- .bank = 0,
- .memsize = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM * SZ_1K,
- .paddr = 0,
- },
-#endif
-
-#ifdef CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1
- {
- .id = S5P_MDEV_PMEM_GPU1,
- .name = "pmem_gpu1",
- .bank = 0,
- .memsize = CONFIG_ANDROID_PMEM_MEMSIZE_PMEM_GPU1 * SZ_1K,
- .paddr = 0,
- },
-#endif
-#endif
-
#ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMC0
{
.id = S5P_MDEV_FIMC0,
diff --git a/arch/arm/mach-exynos/sec_watchdog.c b/arch/arm/mach-exynos/sec_watchdog.c
index b903b80..4ee118a 100644
--- a/arch/arm/mach-exynos/sec_watchdog.c
+++ b/arch/arm/mach-exynos/sec_watchdog.c
@@ -69,7 +69,7 @@ static spinlock_t wdt_lock;
#if defined(PET_BY_WORKQUEUE)
static void watchdog_workfunc(struct work_struct *work)
{
- pr_info("%s kicking...%x\n", __func__, readl(S3C2410_WTCNT));
+ pr_debug("%s kicking...%x\n", __func__, readl(S3C2410_WTCNT));
writel(watchdog_reset * TPS, S3C2410_WTCNT);
queue_delayed_work_on(0, watchdog_wq, &watchdog_work,
watchdog_pet * HZ);
@@ -77,7 +77,7 @@ static void watchdog_workfunc(struct work_struct *work)
#elif defined(PET_BY_DIRECT_TIMER)
static void pet_watchdog_timer_fn(unsigned long data)
{
- pr_info("%s kicking...%x\n", __func__, readl(S3C2410_WTCNT));
+ pr_debug("%s kicking...%x\n", __func__, readl(S3C2410_WTCNT));
writel(watchdog_reset * TPS, S3C2410_WTCNT);
pet_watchdog_timer.expires += watchdog_pet * HZ;
add_timer_on(&pet_watchdog_timer, 0);
@@ -85,7 +85,7 @@ static void pet_watchdog_timer_fn(unsigned long data)
#else
static enum hrtimer_restart watchdog_timerfunc(struct hrtimer *timer)
{
- pr_info("%s kicking...%x\n", __func__, readl(S3C2410_WTCNT));
+ pr_debug("%s kicking...%x\n", __func__, readl(S3C2410_WTCNT));
writel(watchdog_reset * TPS, S3C2410_WTCNT);
hrtimer_start(&watchdog_timer,
ktime_set(watchdog_pet, 0), HRTIMER_MODE_REL);
diff --git a/arch/arm/mvp/Kconfig b/arch/arm/mvp/Kconfig
deleted file mode 100644
index 4f2c5c7..0000000
--- a/arch/arm/mvp/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
-config VMWARE_MVP
- bool "Build VMware Mobile Virtualization Platform modules"
- select MODULES
- select MODULE_UNLOAD
- select SYSFS
- select NAMESPACES
- select NET_NS
- select INET
- select IPV6
- select TUN
- select NETFILTER
- help
- Say Y here to enable the building of kernel modules
- for VMware's Mobile Virtualization Platform
-
-config VMWARE_MVP_DEBUG
- bool "Enable debug for VMware Mobile Virtualization Platform modules"
- depends on VMWARE_MVP
- select IKCONFIG
- select IKCONFIG_PROC
- help
- Say Y here to enable debug on kernel modules
- for VMware's Mobile Virtualization Platform.
- This should be enabled for eng or userdebug builds.
diff --git a/arch/arm/mvp/Makefile b/arch/arm/mvp/Makefile
deleted file mode 100644
index cd38d75..0000000
--- a/arch/arm/mvp/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-y += mvpkm/
-obj-y += commkm/
-obj-y += pvtcpkm/
diff --git a/arch/arm/mvp/commkm/COPYING b/arch/arm/mvp/commkm/COPYING
deleted file mode 100644
index 10828e0..0000000
--- a/arch/arm/mvp/commkm/COPYING
+++ /dev/null
@@ -1,341 +0,0 @@
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/arch/arm/mvp/commkm/Kbuild b/arch/arm/mvp/commkm/Kbuild
deleted file mode 100644
index de43a5c..0000000
--- a/arch/arm/mvp/commkm/Kbuild
+++ /dev/null
@@ -1,9 +0,0 @@
-# Warning: autogenerated
-obj-m := commkm.o
-commkm-objs := check_kconfig.o comm_ev_kernel.o comm.o comm_os_linux.o comm_os_mod_linux.o comm_svc.o comm_transp_mvp.o
-
-ccflags-y += -fno-pic -fno-dwarf2-cfi-asm -march=armv7-a -D__linux__
-ccflags-y += -DCOMM_BUILDING_SERVER
-ccflags-y += -mfpu=neon -DIN_MODULE -DGPLED_CODE
-ccflags-y += --std=gnu89 -O2 -g2 -ggdb -mapcs -fno-optimize-sibling-calls -mno-sched-prolog
-ccflags-$(CONFIG_VMWARE_MVP_DEBUG) += -DMVP_DEBUG
diff --git a/arch/arm/mvp/commkm/Makefile b/arch/arm/mvp/commkm/Makefile
deleted file mode 100644
index 16eb389..0000000
--- a/arch/arm/mvp/commkm/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-# Warning: autogenerated
diff --git a/arch/arm/mvp/commkm/check_kconfig.c b/arch/arm/mvp/commkm/check_kconfig.c
deleted file mode 100644
index 0867d74..0000000
--- a/arch/arm/mvp/commkm/check_kconfig.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- * @brief Check for required kernel configuration
- *
- * Check to make sure that the kernel options that the MVP hypervisor requires
- * have been enabled in the kernel that this kernel module is being built
- * against.
- */
-#include <linux/version.h>
-
-/*
- * Minimum kernel version
- * - network namespace support is only really functional starting in 2.6.29
- * - Android Gingerbread requires 2.6.35
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
-#error "MVP requires a host kernel newer than 2.6.35"
-#endif
-
-/* module loading ability */
-#ifndef CONFIG_MODULES
-#error "MVP requires kernel loadable module support be enabled (CONFIG_MODULES)"
-#endif
-#ifndef CONFIG_MODULE_UNLOAD
-#error "MVP requires kernel module unload support be enabled (CONFIG_MODULE_UNLOAD)"
-#endif
-
-/* sysfs */
-#ifndef CONFIG_SYSFS
-#error "MVP requires sysfs support (CONFIG_SYSFS)"
-#endif
-
-/* network traffic isolation */
-#ifndef CONFIG_NAMESPACES
-#error "MVP networking support requires namespace support (CONFIG_NAMESPACES)"
-#endif
-#ifndef CONFIG_NET_NS
-#error "MVP networking support requires Network Namespace support to be enabled (CONFIG_NET_NS)"
-#endif
-
-/* TCP/IP networking */
-#ifndef CONFIG_INET
-#error "MVP networking requires IPv4 support (CONFIG_INET)"
-#endif
-#ifndef CONFIG_IPV6
-#error "MVP networking requires IPv6 support (CONFIG_IPV6)"
-#endif
-
-/* VPN support */
-#if !defined(CONFIG_TUN) && !defined(CONFIG_TUN_MODULE)
-#error "MVP VPN support requires TUN device support (CONFIG_TUN)"
-#endif
-
-#if !defined(CONFIG_NETFILTER) && !defined(PVTCP_DISABLE_NETFILTER)
-#error "MVP networking support requires netfilter support (CONFIG_NETFILTER)"
-#endif
-
-/* Force /proc/config.gz support for eng/userdebug builds */
-#ifdef MVP_DEBUG
-#if !defined(CONFIG_IKCONFIG) || !defined(CONFIG_IKCONFIG_PROC)
-#error "MVP kernel /proc/config.gz support required for debuggability (CONFIG_IKCONFIG_PROC)"
-#endif
-#endif
-
-/* Sanity check we're only dealing with the memory hotplug + migrate and/or
- * compaction combo */
-#ifdef CONFIG_MIGRATION
-#if defined(CONFIG_NUMA) || defined(CONFIG_CPUSETS) || defined(CONFIG_MEMORY_FAILURE)
-#error "MVP not tested with migration features other than CONFIG_MEMORY_HOTPLUG and CONFIG_COMPACTION"
-#endif
-#endif
diff --git a/arch/arm/mvp/commkm/comm.c b/arch/arm/mvp/commkm/comm.c
deleted file mode 100644
index 8fd591c..0000000
--- a/arch/arm/mvp/commkm/comm.c
+++ /dev/null
@@ -1,1457 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Communication functions based on transport functionality.
- */
-
-#include "comm.h"
-#include "comm_transp_impl.h"
-
-
-/* Constant and macro definitions */
-
-#if defined(COMM_INSTRUMENT)
-static CommOSAtomic commMaxCoalesceSize;
-static CommOSAtomic commPacketsReceived;
-static CommOSAtomic commCommittedPacketsReceived;
-static CommOSAtomic commOpCalls;
-#endif
-
-#define COMM_DISPATCH_EXTRA_WRITER_WAKEUP 1
-
-#define COMM_CHANNEL_MAX_CAPACITY 2048
-#define COMM_CHANNEL_FREE 0x0
-#define COMM_CHANNEL_INITIALIZED 0x1
-#define COMM_CHANNEL_OPENED 0x2
-#define COMM_CHANNEL_ACTIVE 0x4
-#define COMM_CHANNEL_ZOMBIE 0x8
-
-#define CommIsFree(chan) \
- ((chan)->lifecycleState == COMM_CHANNEL_FREE)
-#define CommIsInitialized(chan) \
- ((chan)->lifecycleState == COMM_CHANNEL_INITIALIZED)
-#define CommIsOpened(chan) \
- ((chan)->lifecycleState == COMM_CHANNEL_OPENED)
-#define CommIsActive(chan) \
- ((chan)->lifecycleState == COMM_CHANNEL_ACTIVE)
-#define CommIsZombie(chan) \
- ((chan)->lifecycleState == COMM_CHANNEL_ZOMBIE)
-
-#define CommSetFree(chan) \
- SetLifecycleState(chan, COMM_CHANNEL_FREE)
-#define CommSetInitialized(chan) \
- SetLifecycleState(chan, COMM_CHANNEL_INITIALIZED)
-#define CommSetOpened(chan) \
- SetLifecycleState(chan, COMM_CHANNEL_OPENED)
-#define CommSetActive(chan) \
- SetLifecycleState(chan, COMM_CHANNEL_ACTIVE)
-#define CommSetZombie(chan) \
- SetLifecycleState(chan, COMM_CHANNEL_ZOMBIE)
-
-#define CommGlobalLock() CommOS_SpinLock(&commGlobalLock)
-#define CommGlobalUnlock() CommOS_SpinUnlock(&commGlobalLock)
-#define CommGlobalLockBH() CommOS_SpinLockBH(&commGlobalLock)
-#define CommGlobalUnlockBH() CommOS_SpinUnlockBH(&commGlobalLock)
-
-#define DispatchTrylock(chan) CommOS_MutexTrylock(&(chan)->dispatchMutex)
-#define DispatchUnlock(chan) CommOS_MutexUnlock(&(chan)->dispatchMutex)
-
-#define WriteLock(chan) CommOS_MutexLock(&(chan)->writeMutex)
-#define WriteTrylock(chan) CommOS_MutexTrylock(&(chan)->writeMutex)
-#define WriteUnlock(chan) CommOS_MutexUnlock(&(chan)->writeMutex)
-
-#define StateLock(chan) CommOS_MutexLock(&(chan)->stateMutex)
-#define StateTrylock(chan) CommOS_MutexTrylock(&(chan)->stateMutex)
-#define StateUnlock(chan) CommOS_MutexUnlock(&(chan)->stateMutex)
-
-#define CommHoldInit(chan) CommOS_WriteAtomic(&(chan)->holds, 0)
-#define CommHold(chan) CommOS_AddReturnAtomic(&(chan)->holds, 1)
-#define CommRelease(chan) CommOS_SubReturnAtomic(&(chan)->holds, 1)
-#define CommIsHeld(chan) (CommOS_ReadAtomic(&(chan)->holds) > 0)
-
-#define PacketLenOverLimit(chan, len) \
- (((len) - sizeof (CommPacket)) > ((chan)->transpArgs.capacity / 4))
-
-
-/*
- * Data structure describing the offload <-> paravirtualized module
- * communication channel.
- */
-
-struct CommChannelPriv {
- CommOSAtomic holds; // Active readers and writers
- CommTranspInitArgs transpArgs; // Transport initialization arguments
- CommTransp transp; // Transport handle
- CommOSMutex dispatchMutex; // Dispatch mutex
- CommOSMutex writeMutex; // Non-BH write mutex
- CommOSMutex stateMutex; // Upper-layer state mutex
- CommOSWaitQueue availableWaitQ; // Available write space wait data
- unsigned int desiredWriteSpace; // Size of write space needed
- const CommImpl *impl; // Implementation
- unsigned int implNmbOps; // Number of implementation operations
- unsigned int lifecycleState; // Lifecycle state
- void *state; // Upper layer-specific state
-};
-
-
-static volatile int running; // Initialized and running.
-static CommOSWaitQueue exitWaitQ; // Exit wait queue.
-static CommOSSpinlock commGlobalLock; // Global lock.
-
-
-/* Communication channel slots. */
-
-static unsigned int commChannelCapacity; // Maximum number of channels.
-static unsigned int commChannelSize; // Current size of channel array.
-static unsigned int commChannelAllocated; // Nmb. entries currently in use.
-static struct CommChannelPriv *commChannels; // Allocated channel array.
-
-
-/**
- * @brief Callback function called when the other side created a transport
- * handle to which we need to potentially attach.
- * @param[in,out] transpArgs arguments used when shared memory area was created.
- * @param probeData our callback data, an implementation block.
- * @return 0 if successful, -1 otherwise.
- * @sideeffects May allocate a channel.
- */
-
-static int
-DefaultTranspListener(CommTranspInitArgs *transpArgs,
- void *probeData)
-{
- int rc = -1;
- const int inBH = 1;
- const CommImpl *impl;
-
- if (!transpArgs || !probeData) {
- CommOS_Debug(("%s: NULL args [0x%p, 0x%p].\n",
- __FUNCTION__, transpArgs, probeData));
- goto out;
- }
-
- impl = probeData;
- CommOS_Debug(("%s: Received attach info [%u,%u,%u:%u].\n",
- __FUNCTION__,
- transpArgs->capacity, transpArgs->type,
- transpArgs->id.d32[0], transpArgs->id.d32[1]));
-
- if (impl->checkArgs(transpArgs)) {
- goto out;
- }
- transpArgs->mode = COMM_TRANSP_INIT_ATTACH; /* Ensure we attach. */
-
- /* We recognized it, so don't let others waste any time. Even if we fail. */
-
- rc = 0;
- if (Comm_Alloc(transpArgs, impl, inBH, NULL)) {
- impl->closeNtf(impl->closeNtfData, transpArgs, inBH);
- CommOS_Log(("%s: Can't allocate new channel!\n", __FUNCTION__));
- }
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Sets the lifecycle state of a channel entry
- * @param channel channel to update
- * @param newState state to update to
- */
-
-static inline void
-SetLifecycleState(CommChannel channel,
- unsigned int newState)
-{
-
- channel->lifecycleState = newState;
-}
-
-
-/* Wait conditions: functions returning 1: true, 0: false, < 0: error. */
-
-/**
- * @brief Wait condition function to check whether module can be unloaded.
- * @param arg1 dummy
- * @param arg2 dummy
- * @return 1 if no channels are currently allocated, 0 if there are
- */
-
-static int
-ExitCondition(void *arg1,
- void *arg2)
-{
- unsigned int i;
- int rc;
-
- (void)arg1;
- (void)arg2;
- CommOS_Debug(("%s: running [%d] "
- "commChannelAllocated [%u] commChannelSize [%u].\n",
- __FUNCTION__, running, commChannelAllocated, commChannelSize));
- rc = !running && (commChannelAllocated == 0);
- if (!rc) {
- for (i = 0; i < commChannelCapacity; i++) {
- CommOS_Debug(("%s: channel[%u] state [0x%x].\n",
- __FUNCTION__, i, commChannels[i].lifecycleState));
- }
- }
- return rc;
-}
-
-
-/**
- * @brief Wait condition function to check available write space.
- * @param arg1 pointer to CommChannel struct
- * @param arg2 size argument
- * @return 1 if there is enough write space, 0 if not, -ENOMEM if comm down.
- */
-
-static int
-WriteSpaceCondition(void *arg1,
- void *arg2)
-{
- CommChannel channel = arg1;
-
- if (!CommIsActive(channel)) {
- return -ENOMEM;
- }
- return channel->desiredWriteSpace < CommTransp_EnqueueSpace(channel->transp);
-}
-
-
-/**
- * @brief Registers an implementation block used when attaching to channels
- * in response to transport attach events.
- * @param impl implementation block.
- * @return 0 if successful, non-zero otherwise.
- */
-
-int
-Comm_RegisterImpl(const CommImpl *impl)
-{
- CommTranspListener listener = {
- .probe = DefaultTranspListener,
- .probeData = (void *)impl
- };
-
- return CommTransp_Register(&listener);
-}
-
-
-/**
- * @brief Unregisters an implementation block used when attaching to channels
- * in response to transport attach events.
- * @param impl implementation block.
- */
-
-void
-Comm_UnregisterImpl(const CommImpl *impl)
-{
- CommTranspListener listener = {
- .probe = DefaultTranspListener,
- .probeData = (void *)impl
- };
-
- CommTransp_Unregister(&listener);
-}
-
-
-/**
- * @brief Allocates and initializes comm global state. Single-threaded use.
- * @param maxChannels maximum number of channels.
- * @return zero if successful, non-zero otherwise.
- */
-
-int
-Comm_Init(unsigned int maxChannels)
-{
- int rc = -1;
- unsigned int i;
-
- if (running || commChannels ||
- (maxChannels == 0) || (maxChannels > COMM_CHANNEL_MAX_CAPACITY)) {
- goto out;
- }
-
-#if defined(COMM_INSTRUMENT)
- CommOS_WriteAtomic(&commMaxCoalesceSize, 0);
- CommOS_WriteAtomic(&commPacketsReceived, 0);
- CommOS_WriteAtomic(&commCommittedPacketsReceived, 0);
- CommOS_WriteAtomic(&commOpCalls, 0);
-#endif
-
- CommOS_WaitQueueInit(&exitWaitQ);
- CommOS_SpinlockInit(&commGlobalLock);
- commChannelCapacity = maxChannels;
- commChannelAllocated = 0;
- commChannels = CommOS_Kmalloc((sizeof *commChannels) * commChannelCapacity);
- if (!commChannels) {
- goto out;
- }
-
- memset(commChannels, 0, (sizeof *commChannels) * commChannelCapacity);
- for (i = 0; i < commChannelCapacity; i++ ) {
- CommChannel channel;
-
- channel = &commChannels[i];
- CommHoldInit(channel);
- channel->transp = NULL;
- CommOS_MutexInit(&channel->dispatchMutex);
- CommOS_MutexInit(&channel->writeMutex);
- CommOS_MutexInit(&channel->stateMutex);
- CommOS_WaitQueueInit(&channel->availableWaitQ);
- channel->desiredWriteSpace = -1U;
- channel->state = NULL;
- CommSetFree(channel);
- }
-
- rc = CommTransp_Init();
- if (!rc) {
- commChannelSize = 0;
- running = 1;
- rc = 0;
- } else {
- CommOS_Kfree(commChannels);
- }
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Initiates and finishes, comm global state deallocations.
- * @param timeoutMillis initialization timeout in milliseconds
- * @return zero if deallocations done, non-zero if more calls are needed.
- */
-
-int
-Comm_Finish(unsigned long long *timeoutMillis)
-{
- int rc;
- unsigned int i;
- unsigned long long timeout;
-
- for (i = 0; i < commChannelSize; i++) {
- Comm_Zombify(&commChannels[i], 0);
- }
-
- running = 0;
- timeout = timeoutMillis ? *timeoutMillis : 0;
- /* coverity[var_deref_model] */
- rc = CommOS_Wait(&exitWaitQ, ExitCondition, NULL, NULL, &timeout);
- if (rc == 1) {
- /*
- * Didn't time out, task wasn't interrupted, we can wrap it up..
- */
-
- CommTransp_Exit();
- CommOS_Kfree(commChannels);
- commChannels = NULL;
- commChannelSize = 0;
-#if defined(COMM_INSTRUMENT)
- CommOS_Log(("%s: commMaxCoalesceSize = %lu.\n",
- __FUNCTION__,
- CommOS_ReadAtomic(&commMaxCoalesceSize)));
- CommOS_Log(("%s: commPacketsReceived = %lu.\n",
- __FUNCTION__,
- CommOS_ReadAtomic(&commPacketsReceived)));
- CommOS_Log(("%s: commCommittedPacketsReceived = %lu.\n",
- __FUNCTION__,
- CommOS_ReadAtomic(&commCommittedPacketsReceived)));
- CommOS_Log(("%s: commOpCalls = %lu.\n",
- __FUNCTION__,
- CommOS_ReadAtomic)(&commOpCalls)));
-#endif
- rc = 0;
- } else {
- rc = -1;
- }
- return rc;
-}
-
-
-/**
- * @brief Finds a free entry and initializes it with the information provided.
- * May be called from BH. It doesn't call potentially blocking functions.
- *
- * @note Depending on the choice of shared memory transport (VMCI or MVP QP),
- * the 'inBH' distinction is important. VMCI datagrams are received under
- * some circumstances in bottom-half context, so 'inBH' should be set. This
- * is not a restriction on MVP.
- *
- * @param transpArgs transport initialization arguments.
- * @param impl implementation block.
- * @param inBH non-zero if called in bottom half.
- * @param[out] newChannel newly allocated channel.
- * @return zero if successful, non-zero otherwise.
- * @sideeffects Initializes the communications channel with given parameters
- */
-
-int
-Comm_Alloc(const CommTranspInitArgs *transpArgs,
- const CommImpl *impl,
- int inBH,
- CommChannel *newChannel)
-{
- unsigned int i;
- CommChannel channel = NULL;
- int restoreSize = 0;
- int modHeld = 0;
- int rc = -1;
-
- if (inBH) {
- CommGlobalLock();
- } else {
- CommGlobalLockBH();
- }
-
- if (!running || !transpArgs || !impl) {
- goto out;
- }
-
- if (CommOS_ModuleGet(impl->owner)) {
- goto out;
- }
- modHeld = 1;
-
- for (i = 0; i < commChannelSize; i++) {
- /*
- * Check if this channel is already allocated. We don't match against
- * ANY because those channels are in the process of being opened; after
- * that happens, they'll get proper IDs.
- */
-
- if (!CommIsFree(&commChannels[i]) &&
- (transpArgs->id.d64 != COMM_TRANSP_ID_64_ANY) &&
- (transpArgs->id.d64 == commChannels[i].transpArgs.id.d64)) {
- goto out;
- }
- if (!channel && CommIsFree(&commChannels[i])) {
- channel = &commChannels[i];
- }
- }
- if (!channel) {
- if (commChannelSize == commChannelCapacity) {
- goto out;
- }
- channel = &commChannels[commChannelSize];
- commChannelSize++;
- restoreSize = 1;
- }
-
- if (channel->transp) { /* Inconsistency! */
- if (restoreSize) {
- commChannelSize--;
- }
- goto out;
- }
-
- channel->transpArgs = *transpArgs;
- channel->impl = impl;
- for (i = 0; impl->operations[i]; i++) {
- ;
- }
- channel->implNmbOps = i;
- channel->desiredWriteSpace = -1U;
- commChannelAllocated++;
- CommSetInitialized(channel);
- if (newChannel) {
- *newChannel = channel;
- }
- rc = 0;
- CommOS_ScheduleDisp();
-
-out:
- if (inBH) {
- CommGlobalUnlock();
- } else {
- CommGlobalUnlockBH();
- }
- if (rc && modHeld) {
- CommOS_ModulePut(impl->owner);
- }
- return rc;
-}
-
-
-/**
- * @brief Zombifies a channel. May fail if channel isn't active.
- * @param[in,out] channel channel to zombify.
- * @param inBH non-zero if called in bottom half.
- * @return zero if channel zombified, non-zero otherwise.
- */
-
-int
-Comm_Zombify(CommChannel channel,
- int inBH)
-{
- int rc = -1;
-
- if (!running) {
- goto out;
- }
- if (inBH) {
- CommGlobalLock();
- } else {
- CommGlobalLockBH();
- }
- if (CommIsActive(channel) || CommIsOpened(channel)) {
- CommSetZombie(channel);
- rc = 0;
- }
- if (inBH) {
- CommGlobalUnlock();
- } else {
- CommGlobalUnlockBH();
- }
-
-out:
- if (!rc) {
- CommOS_ScheduleDisp();
- }
- return rc;
-}
-
-
-/**
- * @brief Reports whether a channel is active.
- * @param channel channel to report on.
- * @return non-zero if channel active, zero otherwise.
- */
-
-int
-Comm_IsActive(CommChannel channel)
-{
- return channel ? CommIsActive(channel) : 0;
-}
-
-
-/**
- * @brief Wakes up potential writer on the channel. This function must be
- * called on an active channel, with either the dispatch lock taken, or
- * the channel ref count incremented.
- * @param channel CommChannel structure on which potential writer waits.
- */
-
-static inline void
-WakeUpWriter(CommChannel channel)
-{
- if (WriteSpaceCondition(channel, NULL)) {
- CommOS_WakeUp(&channel->availableWaitQ);
- }
-}
-
-
-/**
- * @brief Transport event handler for comm channels.
- * @param transp transport handle.
- * @param event type of event.
- * @param data callback data.
- * @sideeffects may put the channel into zombie state, or schedule it for I/O.
- */
-
-static void
-TranspEventHandler(CommTransp transp,
- CommTranspIOEvent event,
- void *data)
-{
- CommChannel channel = (CommChannel)data;
-
- switch (event) {
- case COMM_TRANSP_IO_DETACH:
- CommOS_Debug(("%s: Detach event. Zombifying channel.\n", __FUNCTION__));
- Comm_Zombify(channel, 1);
- break;
-
- case COMM_TRANSP_IO_IN:
- case COMM_TRANSP_IO_INOUT:
- /*
- * The dispatch threads may not have been started because either:
- * a) we're not running in the CommSvc service, or
- * b) the Comm client didn't create them explicitly (CommOS_StartIO()).
- *
- * If so, the CommOS_ScheduleDisp() call is ineffective. This is
- * the intended behavior: the client obviously wants to call the Comm
- * dispatch function(s) directly.
- */
-
- CommOS_ScheduleDisp();
- break;
-
- case COMM_TRANSP_IO_OUT:
- CommHold(channel);
- if (CommIsActive(channel)) {
- WakeUpWriter(channel);
- }
- CommRelease(channel);
- if (CommIsZombie(channel)) {
- /*
- * After releasing the hold on the channel, we must check if it was
- * set to zombie and the dispatcher was supposed to nuke it. If the
- * dispatcher had made its run while we were holding the channel, it
- * gave up. So schedule it.
- */
-
- CommOS_ScheduleDisp();
- }
- break;
-
- default:
- CommOS_Debug(("%s: Unhandled event [%u, %p, %p].\n",
- __FUNCTION__, event, transp, data));
- }
-}
-
-
-/**
- * @brief Destroys upper layer state, unregisters event handlers and
- * detaches from or deletes shared memory.
- * @param[in,out] channel CommChannel structure to close.
- */
-
-static void
-CommClose(CommChannel channel)
-{
- const CommImpl *impl = channel->impl;
-
- StateLock(channel);
- if (impl->stateDtor && channel->state) {
- impl->stateDtor(channel->state);
- }
- channel->state = NULL;
- StateUnlock(channel);
-
- CommOS_ModulePut(impl->owner);
-
- if (channel->transp) {
- CommTransp_Close(channel->transp);
- channel->transp = NULL;
- }
-
- CommGlobalLockBH();
- CommSetFree(channel);
- commChannelAllocated--;
- if (channel == &commChannels[commChannelSize - 1]) {
- commChannelSize--;
- }
- CommGlobalUnlockBH();
- if (!running && (commChannelAllocated == 0)) {
- CommOS_WakeUp(&exitWaitQ);
- }
-}
-
-
-/**
- * @brief Allocates upper layer state, registers transport event handler
- * and creates or attaches to shared memory.
- * @param[in,out] channel CommChannel structure to open.
- * @return zero if successful, -1 otherwise
- * @sideeffects Memory may be allocated, event handlers registered and
- * QP allocated or attached to.
- */
-
-static int
-CommOpen(CommChannel channel)
-{
- int rc = -1;
- CommTranspEvent transpEvent = {
- .ioEvent = TranspEventHandler,
- .ioEventData = channel
- };
- const CommImpl *impl;
-
- if (!channel || !CommIsInitialized(channel)) {
- return rc;
- }
-
- if (!running) { /* Ok, toggle it back to FREE. */
- goto out;
- }
-
- impl = channel->impl;
- if (impl->stateCtor) {
- channel->state = impl->stateCtor(channel);
- if (!channel->state) {
- goto out;
- }
- }
-
- if (!CommTransp_Open(&channel->transp, &channel->transpArgs, &transpEvent)) {
- rc = 0;
- } else {
- channel->transp = NULL;
- }
-
-out:
- if (!rc) {
- CommSetOpened(channel);
- } else {
- CommClose(channel);
- }
- return rc;
-}
-
-
-/**
- * @brief Retrieves a channel's transport initialization arguments.
- * It doesn't lock, the caller must ensure the channel may be accessed.
- * @param channel CommChannel structure to get initialization arguments from.
- * @return initialization arguments used to allocate/attach to channel.
- */
-
-CommTranspInitArgs
-Comm_GetTranspInitArgs(CommChannel channel)
-{
- if (!channel) {
- CommTranspInitArgs res = { .capacity = 0 };
-
- return res;
- }
- return channel->transpArgs;
-}
-
-
-/**
- * @brief Retrieves upper layer state (pointer). It doesn't lock, the caller
- * must ensure the channel may be accessed.
- * @param channel CommChannel structure to get state from.
- * @return pointer to upper layer state.
- */
-
-void *
-Comm_GetState(CommChannel channel)
-{
- if (!channel) {
- return NULL;
- }
- return channel->state;
-}
-
-
-/**
- * @brief Main input processing function operating on a given channel.
- * @param channel CommChannel structure to process.
- * @return number of processed channels (0 or 1), or -1 if channel closed.
- * @sideeffects Lifecycle states are transitioned to and from. Channel may
- * be opened or destroyed, waiting writers may be woken up, and input
- * may be handed off to operation callbacks.
- */
-
-int
-Comm_Dispatch(CommChannel channel)
-{
- int rc = 0;
- int zombify = 0;
- CommPacket packet;
- CommPacket firstPacket;
- unsigned int dataLen;
-#define VEC_SIZE 32
- struct kvec vec[VEC_SIZE];
- unsigned int vecLen;
-
- /*
- * Taking the reader mutex is safe in all cases: entries, including
- * free ones, are guaranteed to have initialized mutexes and locks.
- * Locking empty entries may seem wasteful, but those entries are rare.
- */
-
- if (DispatchTrylock(channel)) {
- return 0;
- }
-
- /* Process input and writer wake-up. */
-
- if (CommIsActive(channel)) {
- /*
- * The entry may have transitioned to ZOMBIE, somehow. That's OK
- * since it can't be freed just yet (it's currently locked).
- */
-
- /* Wake up any waiting writers, if necessary. */
-
- WakeUpWriter(channel);
-
- /* Read packets, payloads. */
- CommTransp_DequeueReset(channel->transp);
-
- for (vecLen = 0; vecLen < VEC_SIZE; vecLen++) {
- if (!running) {
- break;
- }
-
- /* Read header. */
-
- rc = CommTransp_DequeueSegment(channel->transp,
- &packet, sizeof packet);
- if (rc <= 0) {
- /* No packet (header). */
-
- rc = vecLen == 0 ? 0 : 1;
- break;
- }
-#if defined(COMM_INSTRUMENT)
- CommOS_AddReturnAtomic(commPacketsReceived, 1);
-#endif
- if ((rc != sizeof packet) || (packet.len < sizeof packet)) {
- rc = -1; /* Fatal protocol error, close down comm. */
- break;
- }
- rc = 1;
-
- /* Read payload, if any. */
-
- dataLen = packet.len - sizeof packet;
- if (vecLen == 0) {
- /* Save header of first packet. */
-
- firstPacket = packet;
- if (dataLen == 0) {
- /* Commit no-payload packet read and we're done. */
-
- CommTransp_DequeueCommit(channel->transp);
-#if defined(COMM_INSTRUMENT)
- CommOS_AddReturnAtomic(&commCommittedPacketsReceived, 1);
-#endif
- break;
- }
- } else {
- /*
- * Check if non-equivalent packet or above coalescing limit.
- * If so, don't commit the read.
- */
-
- if (memcmp(&packet.opCode, &firstPacket.opCode,
- sizeof packet - offsetof(CommPacket, opCode)) ||
- PacketLenOverLimit(channel, firstPacket.len + dataLen)) {
- break;
- }
- }
-
- if (dataLen == 0) {
- /*
- * Received equivalent packet with zero-sized payload. This may
- * happen in certain cases, such as pvtcp forwarding zero-sized
- * datagrams. So don't break the loop, but keep going for as
- * along as we can.
- */
-
- vec[vecLen].iov_base = NULL;
- goto dequeueCommit;
- }
-
- /* The packet has a payload (dataLen > 0). */
-
- if (!(vec[vecLen].iov_base = channel->impl->dataAlloc(dataLen))) {
- /*
- * We treat out-of-(net?-)memory errors as "nothing to read".
- * Memory pressure may either subside, in which case a future
- * read may be successful, or be severe enough for the kernel
- * to oops, anyway. Leave packet uncommitted.
- */
-
- CommOS_Debug(("%s: COULD NOT ALLOC PAYLOAD BYTES!\n",
- __FUNCTION__));
- rc = vecLen == 0 ? 0 : 1;
- break;
- }
-
- /* Read payload and commit (packet and payload). */
-
- rc = CommTransp_DequeueSegment(channel->transp,
- vec[vecLen].iov_base, dataLen);
- if (rc != dataLen) {
- channel->impl->dataFree(vec[vecLen].iov_base);
- CommOS_Log(("%s: BOOG -- COULD NOT DEQUEUE PAYLOAD! [%d != %u]",
- __FUNCTION__, rc, dataLen));
- rc = -1; /* Fatal protocol error, close down comm. */
- break;
- }
- rc = 1;
-
-dequeueCommit:
- CommTransp_DequeueCommit(channel->transp);
-#if defined(COMM_INSTRUMENT)
- CommOS_AddReturnAtomic(&commCommittedPacketsReceived, 1);
-#endif
- vec[vecLen].iov_len = dataLen;
- if (vecLen > 0) {
- firstPacket.len += dataLen;
- if (packet.flags) {
- /* Update to latest flags _iff_ latter non-zero. */
-
- firstPacket.flags = packet.flags;
- }
- }
-#if defined(COMM_INSTRUMENT)
- if (firstPacket.len >
- CommOS_ReadAtomic(&commMaxCoalesceSize)) {
- CommOS_WriteAtomic(&commMaxCoalesceSize, firstPacket.len);
- }
-#endif
- if (COMM_OPF_TEST_ERR(packet.flags)) {
- /* If error bit is set, we're done (no more coalescing). */
-
- vecLen++;
- break;
- }
- }
-
- if (rc <= 0) {
- if (rc < 0) {
- zombify = 1;
- rc = 1;
- }
- goto outUnlockAndFreeIovec;
- }
-
-#if defined(COMM_DISPATCH_EXTRA_WRITER_WAKEUP)
- /* Check again if we need to wake up any writers. */
-
- WakeUpWriter(channel);
-#endif
-
- if (firstPacket.opCode >= channel->implNmbOps) {
- CommOS_Debug(("%s: Ignoring illegal opCode [%u]!\n",
- __FUNCTION__, (unsigned int)firstPacket.opCode));
- CommOS_Debug(("%s: Max opCode: %u\n",
- __FUNCTION__, channel->implNmbOps));
- goto outUnlockAndFreeIovec;
- }
-
- /*
- * NOTE:
- * DispatchUnlock() _must_ be called from the operation callback.
- * The reason for doing so is that, for better scalability, we want
- * it released as soon as possible, BUT:
- * - releasing it here, before calling into the operation, doesn't
- * let the latter coordinate its own lock acquisition, such as
- * potential socket or state locks.
- * - alternatively, always releasing the dispatch lock after the
- * operation completes, ties up the channel and imposes too much
- * serialization between sockets.
- * - to prevent the channel from being torn down while an operation
- * is in flight (and potentially having released the dispatch lock),
- * we increment the ref count on the channel and then release it
- * after the function returns.
- */
-
-#if defined(COMM_INSTRUMENT)
- CommOS_AddReturnAtomic(&commOpCalls, 1);
-#endif
-
- CommHold(channel);
- channel->impl->operations[firstPacket.opCode](channel, channel->state,
- &firstPacket, vec, vecLen);
- CommRelease(channel);
- goto out; /* No unlocking, see comment above. */
- }
-
- /* Process state changes. */
-
- if (CommIsZombie(channel) && !CommIsHeld(channel)) {
- CommTranspInitArgs transpArgs = channel->transpArgs;
- void (*closeNtf)(void *,
- const CommTranspInitArgs *,
- int inBH) = channel->impl->closeNtf;
- void *closeNtfData = channel->impl->closeNtfData;
-
- while (WriteTrylock(channel)) {
- /* Take the write lock; kick writers out if necessary. */
-
- CommOS_Debug(("%s: Kicking writers out...\n", __FUNCTION__));
- CommOS_WakeUp(&channel->availableWaitQ);
- }
- WriteUnlock(channel);
-
- CommOS_Debug(("%s: Nuking zombie channel.\n", __FUNCTION__));
- CommClose(channel);
- if (closeNtf) {
- closeNtf(closeNtfData, &transpArgs, 0);
- }
- rc = -1;
- } else if (CommIsInitialized(channel) &&
- (channel->impl->openAtMillis <=
- CommOS_GetCurrentMillis())) {
- if (!CommOpen(channel)) {
- if (channel->transpArgs.mode == COMM_TRANSP_INIT_CREATE) {
- /*
- * If the attach side doesn't get notified, the entry will
- * time out in OPENED and will be collected.
- * Note that during the CommOpen(Transp_Open) call, the IDs
- * in the transpArgs may have changed. Use those.
- */
-
- CommTransp_Notify(&channel->impl->ntfCenterID,
- &channel->transpArgs);
- } else { /* Attach mode */
- packet.len = sizeof packet;
- packet.opCode = 0xff;
- packet.flags = 0x00;
-
- /*
- * Send out control packet, attach ack, and transition straight
- * to ACTIVE.
- */
-
- rc = CommTransp_EnqueueAtomic(channel->transp,
- &packet, sizeof packet);
- if (rc == sizeof packet) {
- /* Guard against potentially concurrent zombify. */
-
- CommGlobalLockBH();
- if (CommIsOpened(channel)) {
- CommOS_Debug(("%s: Sent attach ack. Activating channel.\n",
- __FUNCTION__));
- CommSetActive(channel);
- }
- CommGlobalUnlockBH();
- }
- }
- rc = 1;
- }
- } else if (CommIsOpened(channel) &&
- (channel->transpArgs.mode == COMM_TRANSP_INIT_CREATE)) {
- /*
- * Get control packet (opCode == 0xff), attach ack (flags == 0x0),
- * or check whether the channel timed out in OPENED.
- */
-
- rc = CommTransp_DequeueAtomic(channel->transp,
- &packet, sizeof packet);
- if (rc == sizeof packet) {
- void (*activateNtf)(void *activateNtfData, CommChannel) = NULL;
- void *activateNtfData = NULL;
-
- /* Guard against potentially concurrent zombify. */
-
- CommGlobalLockBH();
- if (CommIsOpened(channel) &&
- (packet.opCode == 0xff) && (packet.flags == 0x0)) {
- activateNtf = channel->impl->activateNtf;
- activateNtfData = channel->impl->activateNtfData;
-
- CommSetActive(channel);
- CommOS_Debug(("%s: Received attach ack. Activating channel.\n",
- __FUNCTION__));
- }
- CommHold(channel);
- CommGlobalUnlockBH();
-
- if (activateNtf) {
- /* The callback must be short and 'put' the channel when done. */
-
- activateNtf(activateNtfData, channel);
- } else {
- /* Don't forget to put back the channel if no activate callback. */
-
- CommRelease(channel);
- }
- } else if ((channel->impl->openTimeoutAtMillis <=
- CommOS_GetCurrentMillis()) ||
- !running) {
- zombify = 1;
- CommOS_Debug(("%s: Zombifying expired opened channel.\n",
- __FUNCTION__));
- }
- rc = 1;
- }
- DispatchUnlock(channel);
-
-out:
- if (zombify) {
- Comm_Zombify(channel, 0);
- }
- return rc;
-
-outUnlockAndFreeIovec:
- DispatchUnlock(channel);
- for ( ; vecLen; ) {
- if (vec[--vecLen].iov_base) {
- channel->impl->dataFree(vec[vecLen].iov_base);
- vec[vecLen].iov_base = NULL;
- }
- vec[vecLen].iov_len = 0;
- }
- goto out;
-#undef VEC_SIZE
-}
-
-
-/**
- * @brief Main input processing function operating on all channels.
- * @return number of processed channels.
- * @sideeffects Lifecycle states are transitioned to and from. Channels may
- * be opened and destroyed, waiting writers may be woken up, and input
- * may be handed off to operation callbacks.
- */
-
-unsigned int
-Comm_DispatchAll(void)
-{
- unsigned int i;
- unsigned int hits;
-
- for (hits = 0, i = 0; running && (i < commChannelSize); i++) {
- hits += !!Comm_Dispatch(&commChannels[i]);
- }
- return hits;
-}
-
-
-/**
- * @brief Writes a fully formatted packet (containing payload data, if
- * applicable) to the specified channel.
- *
- * The operation may block until enough write space is available, but no
- * more than the specified interval. The operation either writes the full
- * amount of bytes, or it fails. Warning: callers must _not_ use the
- * _Lock/_Unlock functions to bracket calls to this function.
- * @param[in,out] channel channel to write to.
- * @param packet packet to write.
- * @param[in,out] timeoutMillis interval in milliseconds to wait.
- * @return number of bytes written, 0 if it times out, -1 error.
- * @sideeffects Data may be written to the channel.
- */
-
-int
-Comm_Write(CommChannel channel,
- const CommPacket *packet,
- unsigned long long *timeoutMillis)
-{
- int rc = -1;
- int zombify;
-
- if (!channel || !timeoutMillis ||
- !packet || (packet->len < sizeof *packet)) {
- return rc;
- }
-
- zombify = (*timeoutMillis >= COMM_MAX_TO);
-
- WriteLock(channel);
- if (!CommIsActive(channel)) {
- goto out;
- }
-
- CommTransp_EnqueueReset(channel->transp);
- channel->desiredWriteSpace = packet->len;
- rc = CommOS_DoWait(&channel->availableWaitQ, WriteSpaceCondition,
- channel, NULL, timeoutMillis,
- (*timeoutMillis != COMM_MAX_TO_UNINT));
- channel->desiredWriteSpace = -1U;
-
- if (rc) { /* Don't zombify, if it didn't time out. */
- zombify = 0;
- }
- if (rc == 1) { /* Enough write space, enqueue the packet. */
- rc = CommTransp_EnqueueAtomic(channel->transp, packet, packet->len);
- if (rc != packet->len) {
- zombify = 1;
- rc = -1; /* Fatal protocol error. */
- }
- }
-
-out:
- WriteUnlock(channel);
- if (zombify) {
- Comm_Zombify(channel, 0);
- }
- return rc;
-}
-
-
-/**
- * @brief Writes a packet and associated payload data to the specified channel.
- * The operation may block until enough write space is available, but
- * not more than the specified interval.
- * The operation either writes the full amount of bytes, or it fails.
- * If there is not enough data in the vector, padding will be added to
- * reach the specified packet length, if the flags parameter requires it.
- * Users may call this function successively to write several packets
- * from large {io|k}vecs, when the flags parameter indicates it. If this
- * is the case, the packet header needs to be updated accordingly in
- * between calls, for the different (total) lengths.
- * Warning: callers must _not_ use the _Lock/_Unlock functions to bracket
- * calls to this function.
- * @param[in,out] channel the specified channel.
- * @param packet packet to write.
- * @param[in,out] vec kvec to write from.
- * @param[in,out] vecLen length of kvec.
- * @param[in,out] timeoutMillis interval in milliseconds to wait.
- * @param[in,out] iovOffset must be set to 0 before first call (internal cookie)
- * @return number of bytes written, 0 if it timed out, -1 error.
- * @sideeffects data may be written to the channel.
- */
-
-int
-Comm_WriteVec(CommChannel channel,
- const CommPacket *packet,
- struct kvec **vec,
- unsigned int *vecLen,
- unsigned long long *timeoutMillis,
- unsigned int *iovOffset)
-{
- int rc;
- int zombify;
- unsigned int dataLen;
- unsigned int vecDataLen;
- unsigned int vecNdx;
- unsigned int iovLen;
- void *iovBase;
-
- if (!channel || !timeoutMillis || !iovOffset ||
- !packet || (packet->len < sizeof *packet) ||
- (((dataLen = packet->len - sizeof *packet) > 0) &&
- (!*vec || !*vecLen))) {
- return -1;
- }
-
- zombify = (*timeoutMillis >= COMM_MAX_TO);
-
- WriteLock(channel);
- if (!CommIsActive(channel)) {
- rc = -1;
- goto out;
- }
-
- CommTransp_EnqueueReset(channel->transp);
- channel->desiredWriteSpace = packet->len;
- rc = CommOS_DoWait(&channel->availableWaitQ, WriteSpaceCondition,
- channel, NULL, timeoutMillis,
- (*timeoutMillis != COMM_MAX_TO_UNINT));
- channel->desiredWriteSpace = -1U;
-
- if (rc) { /* Don't zombify, if it didn't time out. */
- zombify = 0;
- }
- if (rc == 1) { /* Enough write space, enqueue the packet. */
- iovLen = 0;
- rc = CommTransp_EnqueueSegment(channel->transp, packet, sizeof *packet);
- if (rc != sizeof *packet) {
- zombify = 1;
- rc = -1; /* Fatal protocol error. */
- goto out;
- }
-
- if (dataLen > 0) {
- int done = 0;
-
- for (vecDataLen = 0, vecNdx = 0; vecNdx < *vecLen; vecNdx++) {
- if (vecNdx) {
- *iovOffset = 0;
- }
- iovLen = (*vec)[vecNdx].iov_len - *iovOffset;
- iovBase = (*vec)[vecNdx].iov_base + *iovOffset;
-
- if (!iovLen) {
- continue;
- }
-
- vecDataLen += iovLen;
- if (vecDataLen >= dataLen) {
- iovLen -= (vecDataLen - dataLen);
- done = 1;
- }
-
- rc = CommTransp_EnqueueSegment(channel->transp, iovBase, iovLen);
- if (rc != iovLen) {
- zombify = 1;
- rc = -1; /* Fatal protocol error, close down comm. */
- goto out;
- }
-
- if (done) {
- CommTransp_EnqueueCommit(channel->transp);
- if (vecDataLen == dataLen) {
- vecNdx++;
- *iovOffset = 0;
- } else {
- *iovOffset += iovLen;
- }
- *vecLen -= vecNdx;
- *vec += vecNdx;
- break;
- }
- }
-
- if (!done) {
- /*
- * We exhausted all the bytes in the given vector, but total length
- * in the packet header is more than we sent (was available).
- * If so, we pad by sending zero bytes to reach length required.
- */
-
- static char pad[1024];
- unsigned int delta;
- unsigned int toSend;
-
- while (vecDataLen < dataLen) {
- delta = dataLen - vecDataLen;
- toSend = delta <= sizeof pad ? delta : sizeof pad;
- if (toSend == delta) {
- done = 1;
- }
- vecDataLen += toSend;
-
- rc = CommTransp_EnqueueSegment(channel->transp, pad, toSend);
- if (rc != toSend) {
- zombify = 1;
- rc = -1; /* Fatal protocol error, close down comm. */
- goto out;
- }
-
- if (done) {
- CommTransp_EnqueueCommit(channel->transp);
- *vec = NULL;
- *vecLen = 0;
- *iovOffset = 0;
- break;
- }
- }
- }
- } else {
- CommTransp_EnqueueCommit(channel->transp);
- }
- rc = (int)packet->len;
- } else {
- CommOS_Debug(("%s: timed out...\n", __FUNCTION__));
- }
-
-out:
- WriteUnlock(channel);
- if (zombify) {
- Comm_Zombify(channel, 0);
- }
- return rc;
-}
-
-
-/**
- * @brief Releases channel ref count. This function is exported for the upper
- * layer's 'activateNtf' callback which may be run asynchronously. The
- * callback is protected from concurrent channel releases until it calls
- * this function.
- * @param[in,out] channel CommChannel structure to release.
- */
-
-void
-Comm_Put(CommChannel channel)
-{
- if (channel) {
- CommRelease(channel);
- }
-}
-
-
-/**
- * @brief Uses the read lock. This function is exported for the upper layer
- * such that it can order acquisition of a different lock (socket) with
- * the release of the dispatch lock.
- * @param[in,out] channel CommChannel structure to unlock.
- */
-
-void
-Comm_DispatchUnlock(CommChannel channel)
-{
- if (channel) {
- DispatchUnlock(channel);
- }
-}
-
-
-/**
- * @brief Lock the channel for upper layer state.
- * This function is exported for the upper layer to ensure that channel
- * isn't closed while updating the layer state. Operations using this
- * function are expected to be short, since unlike the _Write functions,
- * these callers cannot be signaled.
- * @param[in,out] channel CommChannel structure to lock.
- * @return zero if successful, -1 otherwise.
- */
-
-int
-Comm_Lock(CommChannel channel)
-{
- if (!channel) {
- return -1;
- }
- StateLock(channel);
- if (!CommIsActive(channel) && !CommIsZombie(channel)) {
- StateUnlock(channel);
- return -1;
- }
- return 0;
-}
-
-
-/**
- * @brief Uses the writer lock. This function is exported for the upper layer
- * to ensure that channel isn't closed while updating the layer state.
- * See Comm_Lock for details).
- * @param[in,out] channel CommChannel structure to unlock.
- */
-
-void
-Comm_Unlock(CommChannel channel)
-{
- if (channel) {
- StateUnlock(channel);
- }
-}
-
-
-/**
- * @brief Requests events be posted in-line after the function completes.
- * @param channel channel object.
- * @return current number of requests for inline event posting, or -1 on error.
- */
-
-unsigned int
-Comm_RequestInlineEvents(CommChannel channel)
-{
- if (channel->transp) {
- return CommTransp_RequestInlineEvents(channel->transp);
- } else {
- return (unsigned int)-1;
- }
-}
-
-
-/**
- * @brief Requests events be posted out-of-band after the function completes.
- * @param channel channel object.
- * @return current number of requests for inline event posting, or -1 on error.
- */
-
-unsigned int
-Comm_ReleaseInlineEvents(CommChannel channel)
-{
- if (channel->transp) {
- return CommTransp_ReleaseInlineEvents(channel->transp);
- } else {
- return (unsigned int)-1;
- }
-}
diff --git a/arch/arm/mvp/commkm/comm.h b/arch/arm/mvp/commkm/comm.h
deleted file mode 100644
index 8291ae4..0000000
--- a/arch/arm/mvp/commkm/comm.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Communication functions based on queue pair transport APIs.
- *
- * Comm is a shared memory-based mechanism that facilitates the implementation
- * of kernel components that require host-to-guest, or guest-to-guest
- * communication.
- * This facility assumes the availability of a minimal shared memory queue pair
- * implementation, such as MVP queue pairs or VMCI queue pairs. The latter must
- * provide primitives for queue pair creation and destruction, and reading and
- * writing from/to queue pairs.
- * Comm assumes that the queue pair (transport) layer is not concerned with
- * multi-threading, locking or flow control, and does not require such features.
- */
-
-#ifndef _COMM_H_
-#define _COMM_H_
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "comm_os.h"
-#include "comm_transp.h"
-
-
-/* Default/maximum Comm timeouts (in milliseconds). */
-#define COMM_MAX_TO 60000ULL
-#define COMM_MAX_TO_UNINT (COMM_MAX_TO + 1)
-
-#define COMM_OPF_SET_ERR(flags) ((flags) |= 128)
-#define COMM_OPF_CLEAR_ERR(flags) ((flags) &= 127)
-#define COMM_OPF_TEST_ERR(flags) ((flags) & 128)
-
-#define COMM_OPF_SET_VAL(flags, val) ((flags) |= ((val) & 127))
-#define COMM_OPF_GET_VAL(flags) ((flags) & 127)
-
-/**
- * Packet (header) structure.
- * NB: Do not change this structure, especially the first three fields; there
- * will be consequences. It may be extended, but it's not recommended: all
- * operations carry this header, so it's better kept in its minimal form.
- */
-
-typedef struct CommPacket {
- unsigned int len; // Total length
- unsigned char flags; // Operation flags
- unsigned char opCode; // Operation to call
- unsigned short data16; // Auxiliary data
- unsigned long long data64;
- unsigned long long data64ex;
- union {
- struct {
- unsigned int data32;
- unsigned int data32ex;
- };
- unsigned long long data64ex2;
- };
-} CommPacket;
-
-
-/* Opaque structure representing a communication channel. */
-
-struct CommChannelPriv;
-typedef struct CommChannelPriv *CommChannel;
-
-
-/* Input operations associated with a comm channel. */
-
-typedef void (*CommOperationFunc)(CommChannel channel,
- void *state,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen);
-
-
-/* Helper macros */
-
-#define COMM_DEFINE_OP(funcName) \
-void \
-funcName(CommChannel channel, \
- void *state, \
- CommPacket *packet, \
- struct kvec *vec, \
- unsigned int vecLen)
-
-
-/* Comm-based implementations. */
-
-typedef struct CommImpl {
- struct module *owner;
- int (*checkArgs)(CommTranspInitArgs *transpArgs);
- void *(*stateCtor)(CommChannel channel);
- void (*stateDtor)(void *state);
- void *(*dataAlloc)(unsigned int dataLen);
- void (*dataFree)(void *data);
- const CommOperationFunc *operations;
- void (*closeNtf)(void *closeNtfData,
- const CommTranspInitArgs *transpArgs,
- int inBH);
- void *closeNtfData;
- void (*activateNtf)(void *activateNtfData,
- CommChannel channel);
- void *activateNtfData;
- unsigned long long openAtMillis;
- unsigned long long openTimeoutAtMillis;
- CommTranspID ntfCenterID;
-} CommImpl;
-
-
-int Comm_Init(unsigned int maxChannels);
-int Comm_Finish(unsigned long long *timeoutMillis);
-int Comm_RegisterImpl(const CommImpl *impl);
-void Comm_UnregisterImpl(const CommImpl *impl);
-int Comm_IsActive(CommChannel channel);
-CommTranspInitArgs Comm_GetTranspInitArgs(CommChannel channel);
-void *Comm_GetState(CommChannel channel);
-int Comm_Dispatch(CommChannel channel);
-unsigned int Comm_DispatchAll(void);
-void Comm_Put(CommChannel channel);
-void Comm_DispatchUnlock(CommChannel channel);
-int Comm_Lock(CommChannel channel);
-void Comm_Unlock(CommChannel channel);
-int Comm_Zombify(CommChannel channel, int inBH);
-
-int
-Comm_Alloc(const CommTranspInitArgs *transpArgs,
- const CommImpl *impl,
- int inBH,
- CommChannel *newChannel);
-
-
-int
-Comm_Write(CommChannel channel,
- const CommPacket *packet,
- unsigned long long *timeoutMillis);
-
-int
-Comm_WriteVec(CommChannel channel,
- const CommPacket *packet,
- struct kvec **vec,
- unsigned int *vecLen,
- unsigned long long *timeoutMillis,
- unsigned int *iovOffset);
-
-unsigned int Comm_RequestInlineEvents(CommChannel channel);
-unsigned int Comm_ReleaseInlineEvents(CommChannel channel);
-
-#endif // _COMM_H_
diff --git a/arch/arm/mvp/commkm/comm_ev.h b/arch/arm/mvp/commkm/comm_ev.h
deleted file mode 100644
index bf629c3..0000000
--- a/arch/arm/mvp/commkm/comm_ev.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief various comm event signaling types and signatures
- */
-
-#ifndef _COMM_EV_H
-#define _COMM_EV_H
-
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_MODULE
-#include "include_check.h"
-
-/**
- * @name Identifiers of comm event signaling class methods
- * @{
- */
-#define MVP_COMM_EV_SIGNATURE 0x4d4d4f43 ///< 'COMM'
-#define MVP_COMM_EV_SIGNAL (MVP_OBJECT_CUSTOM_BASE + 0) ///< Signal host
-#define MVP_COMM_EV_READ_EVENT_DATA (MVP_OBJECT_CUSTOM_BASE + 1) ///< read event data
-#define MVP_COMM_EV_LAST (MVP_OBJECT_CUSTOM_BASE + 2) ///< Number of methods
-/**@}*/
-
-typedef struct CommEvent {
- CommTranspID id;
- CommTranspIOEvent event;
-} CommEvent;
-
-#endif
diff --git a/arch/arm/mvp/commkm/comm_ev_kernel.c b/arch/arm/mvp/commkm/comm_ev_kernel.c
deleted file mode 100644
index 0701945..0000000
--- a/arch/arm/mvp/commkm/comm_ev_kernel.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Comm event signaling, host kernel side.
- */
-
-#include <linux/net.h>
-
-#include "mvp_types.h"
-#include "comm_os.h"
-#include "comm_transp_impl.h"
-#include "mksck_sockaddr.h"
-#include "comm_ev.h"
-#include "mvpkm_comm_ev.h"
-
-static struct socket *sock;
-
-/**
- * @brief Raises a transport event on the provided event ID (address). This
- * function is called from a comm_transp provider, such as comm_transp_mvp,
- * when it needs to signal an event on a given channel.
- * @param targetEvID opaque event channel ID (interpreted by implementation).
- * @param transpID ID of transport to signal.
- * @param eventType event type to raise.
- * @return 0 if successful, -1 otherwise.
- */
-
-int
-CommTranspEvent_Raise(unsigned int targetEvID, // unused
- CommTranspID *transpID,
- CommTranspIOEvent eventType)
-{
- struct sockaddr_mk guestAddr;
- struct msghdr msg;
- struct kvec vec[1];
- int rc;
- CommEvent event;
-
- if (!transpID) {
- return -1;
- }
-
- guestAddr.mk_family = AF_MKSCK;
- guestAddr.mk_addr.addr = Mksck_AddrInit(transpID->d32[0], MKSCK_PORT_COMM_EV);
-
- memset(&msg, 0, sizeof (struct msghdr));
- msg.msg_name = &guestAddr;
- msg.msg_namelen = sizeof (guestAddr);
-
- event.id = *transpID;
- event.event = eventType;
-
- vec[0].iov_base = &event;
- vec[0].iov_len = sizeof (CommEvent);
-
- rc = kernel_sendmsg(sock,
- &msg,
- vec,
- 1,
- sizeof (CommEvent));
- rc = (rc < 0) ? -1 : 0;
- return rc;
-}
-
-
-/**
- * @brief Performs one-time, global initialization of event provider.
- * @return 0 if successful, -1 otherwise.
- */
-int
-CommTranspEvent_Init(void)
-{
- struct sockaddr_mk addr = { AF_MKSCK, { .addr = MKSCK_ADDR_UNDEF } };
- int rc;
-
- rc = sock_create_kern(AF_MKSCK, SOCK_DGRAM, 0, &sock);
- if (rc < 0) {
- goto out;
- }
-
- rc = kernel_bind(sock, (struct sockaddr *) &addr, sizeof addr);
- if (rc < 0) {
- sock_release(sock);
- sock = NULL;
- goto out;
- }
-
- Mvpkm_CommEvRegisterProcessCB(CommTranspEvent_Process);
-
-out:
- if (rc) {
- CommOS_Log(("%s: Failed to initialize transport event signaling\n",
- __FUNCTION__));
- } else {
- CommOS_Log(("%s: Transport event signaling initialization successful\n",
- __FUNCTION__));
- }
- return rc;
-}
-
-
-/**
- * @brief Performs global clean-up of event provider.
- */
-
-void
-CommTranspEvent_Exit(void)
-{
- Mvpkm_CommEvUnregisterProcessCB();
- if (sock) {
- sock_release(sock);
- sock = NULL;
- }
-
- CommOS_Debug(("%s: done.\n", __FUNCTION__));
-}
diff --git a/arch/arm/mvp/commkm/comm_os.h b/arch/arm/mvp/commkm/comm_os.h
deleted file mode 100644
index f98c8d4..0000000
--- a/arch/arm/mvp/commkm/comm_os.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Cross-platform base type definitions and function declarations.
- * Includes OS-specific base type definitions and function declarations.
- */
-
-#ifndef _COMM_OS_H_
-#define _COMM_OS_H_
-
-/* For-ever timeout constant (in milliseconds). */
-#define COMM_OS_4EVER_TO ((unsigned long long)(~0UL >> 1))
-
-/* Condition function prototype. Returns 1: true, 0: false, < 0: error code. */
-typedef int (*CommOSWaitConditionFunc)(void *arg1, void *arg2);
-
-/* Dispatch function prototype. Called by input (dispatch) kernel threads. */
-typedef unsigned int (*CommOSDispatchFunc)(void);
-
-/* Module initialization and exit callback functions. */
-extern int (*commOSModInit)(void *args);
-extern void (*commOSModExit)(void);
-
-/* Macro to assign Init and Exit callbacks. */
-#define COMM_OS_MOD_INIT(init, exit) \
- int (*commOSModInit)(void *args) = init; \
- void (*commOSModExit)(void) = exit
-
-
-/*
- * OS-specific implementations must provide the following:
- * 1. Types:
- * CommOSAtomic
- * CommOSSpinlock
- * CommOSMutex
- * CommOSWaitQueue
- * CommOSWork
- * CommOSWorkFunc
- * CommOSList
- * CommOSModule
- * struct kvec
- *
- * 2. Definition, initializers:
- * CommOSSpinlock_Define()
- *
- * 3. Functions:
- * void CommOS_Debug(const char *format, ...);
- * void CommOS_Log(const char *format, ...);
- * void CommOS_WriteAtomic(CommOSAtomic *atomic, int val);
- * int CommOS_ReadAtomic(CommOSAtomic *atomic);
- * int CommOS_AddReturnAtomic(CommOSAtomic *atomic, int val);
- * int CommOS_SubReturnAtomic(CommOSAtomic *atomic, int val);
- * void CommOS_SpinlockInit(CommOSSpinlock *lock);
- * void CommOS_SpinLockBH(CommOSSpinlock *lock);
- * int CommOS_SpinTrylockBH(CommOSSpinlock *lock);
- * void CommOS_SpinUnlockBH(CommOSSpinlock *lock);
- * void CommOS_SpinLock(CommOSSpinlock *lock);
- * int CommOS_SpinTrylock(CommOSSpinlock *lock);
- * void CommOS_SpinUnlock(CommOSSpinlock *lock);
- * void CommOS_MutexInit(CommOSMutex *mutex);
- * void CommOS_MutexLock(CommOSMutex *mutex);
- * int CommOS_MutexLockUninterruptible(CommOSMutex *mutex);
- * int CommOS_MutexTrylock(CommOSMutex *mutex);
- * void CommOS_MutexUnlock(CommOSMutex *mutex);
- * void CommOS_WaitQueueInit(CommOSWaitQueue *wq);
- * CommOS_DoWait(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc cond,
- * void *condArg1,
- * void *condArg2,
- * unsigned long long *timeoutMillis,
- * int interruptible);
- * int CommOS_Wait(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc func,
- * void *funcArg1,
- * void *funcArg2,
- * unsigned long long *timeoutMillis);
- * int CommOS_WaitUninterruptible(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc func,
- * void *funcArg1,
- * void *funcArg2,
- * unsigned long long *timeoutMillis);
- * void CommOS_WakeUp(CommOSWaitQueue *wq);
- * void *CommOS_KmallocNoSleep(unsigned int size);
- * void *CommOS_Kmalloc(unsigned int size);
- * void CommOS_Kfree(void *arg);
- * void CommOS_Yield(void);
- * unsigned long long CommOS_GetCurrentMillis(void);
- * void CommOS_ListInit(CommOSList *list);
- * int CommOS_ListEmpty(CommOSList *list);
- * void CommOS_ListAdd(CommOSList *list, CommOSList *listElem);
- * void CommOS_ListAddTail(CommOSList *list, CommOSList *listElem);
- * void int CommOS_ListDel(CommOSList *listElem);
- * Macros:
- * CommOS_ListForEach(*list, *item, itemListFieldName);
- * CommOS_ListForEachSafe(*list, *item, *tmp, itemListFieldName);
- * void CommOS_ListSplice(CommOSList *list, CommOSList *listToAdd);
- * void CommOS_ListSpliceTail(CommOSList *list, CommOSList *listToAdd);
- * CommOSModule CommOS_ModuleSelf(void);
- * int CommOS_ModuleGet(CommOSModule module);
- * void CommOS_ModulePut(CommOSModule module);
- * void CommOS_MemBarrier(void);
- *
- * These cannot be defined here: a) non-pointer type definitions need size
- * information, and b) functions may or may not be inlined, or macros may
- * be used instead.
- */
-
-
-#ifdef __linux__
-#include "comm_os_linux.h"
-#else
-#error "Unsupported OS"
-#endif
-
-/* Functions to start and stop the dispatch and aio kernel threads. */
-void CommOS_StopIO(void);
-void CommOS_ScheduleDisp(void);
-void CommOS_InitWork(CommOSWork *work, CommOSWorkFunc func);
-int CommOS_ScheduleAIOWork(CommOSWork *work);
-void CommOS_FlushAIOWork(CommOSWork *work);
-
-int
-CommOS_StartIO(const char *dispatchTaskName,
- CommOSDispatchFunc dispatchHandler,
- unsigned int interval,
- unsigned int maxCycles,
- const char *aioTaskName);
-
-
-#endif /* _COMM_OS_H_ */
diff --git a/arch/arm/mvp/commkm/comm_os_linux.c b/arch/arm/mvp/commkm/comm_os_linux.c
deleted file mode 100644
index 74f99f5..0000000
--- a/arch/arm/mvp/commkm/comm_os_linux.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Linux-specific functions/types.
- */
-
-#include "comm_os.h"
-
-#define DISPATCH_MAX_CYCLES 8192
-
-/* Type definitions */
-
-typedef struct workqueue_struct CommOSWorkQueue;
-
-
-/* Static data */
-
-static volatile int running;
-static int numCpus;
-static CommOSWorkQueue *dispatchWQ;
-static CommOSDispatchFunc dispatch;
-static CommOSWork dispatchWorksNow[NR_CPUS];
-static CommOSWork dispatchWorks[NR_CPUS];
-static unsigned int dispatchInterval = 1;
-static unsigned int dispatchMaxCycles = 2048;
-static CommOSWorkQueue *aioWQ;
-
-
-/**
- * @brief Initializes a workqueue consisting of per-cpu kernel threads.
- * @param name workqueue name
- * @return workqueue handle if successful, NULL otherwise
- */
-
-static inline CommOSWorkQueue *
-CreateWorkqueue(const char *name)
-{
- return create_workqueue(name);
-}
-
-
-/**
- * @brief Destroys a workqueue and stops its threads.
- * @param[in,out] wq workqueue to destroy.
- * @return workqueue handle is successful, NULL otherwise.
- */
-
-static inline void
-DestroyWorkqueue(CommOSWorkQueue *wq)
-{
- destroy_workqueue(wq);
-}
-
-
-/**
- * @brief Force execution of a work item.
- * @param[in,out] work work item to dequeue.
- */
-
-static inline void
-FlushDelayedWork(CommOSWork *work)
-{
- flush_delayed_work(work);
-}
-
-
-/**
- * @brief Enqueue a work item to a workqueue for execution on a given cpu
- * and after the specified interval.
- * @param cpu cpu number. If negative, work item is enqueued on current cpu.
- * @param[in,out] wq target work queue.
- * @param[in,out] work work item to enqueue.
- * @param jif delay interval.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-QueueDelayedWorkOn(int cpu,
- CommOSWorkQueue *wq,
- CommOSWork *work,
- unsigned long jif)
-{
- if (cpu < 0) {
- return !queue_delayed_work(wq, work, jif) ? -1 : 0;
- } else {
- return !queue_delayed_work_on(cpu, wq, work, jif) ? -1 : 0;
- }
-}
-
-
-/**
- * @brief Enqueues a work item to a workqueue for execution on the current cpu
- * and after the specified interval.
- * @param[in,out] wq target work queue.
- * @param[in,out] work work item to enqueue.
- * @param jif delay interval.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-QueueDelayedWork(CommOSWorkQueue *wq,
- CommOSWork *work,
- unsigned long jif)
-{
- return QueueDelayedWorkOn(-1, wq, work, jif);
-}
-
-
-/**
- * @brief Cancels a queued delayed work item and synchronizes with its
- * completion.
- * @param[in,out] work work item to cancel
- */
-
-static inline void
-WaitForDelayedWork(CommOSWork *work)
-{
- cancel_delayed_work_sync(work);
-}
-
-
-/**
- * @brief Discards work items queued to the specified workqueue.
- * @param[in,out] wq work queue to flush.
- */
-
-static inline void
-FlushWorkqueue(CommOSWorkQueue *wq)
-{
- flush_workqueue(wq);
-}
-
-
-/**
- * @brief Schedules dispatcher threads for immediate execution.
- */
-
-void
-CommOS_ScheduleDisp(void)
-{
- CommOSWork *work = &dispatchWorksNow[get_cpu()];
-
- put_cpu();
- if (running) {
- QueueDelayedWork(dispatchWQ, work, 0);
- }
-}
-
-
-/**
- * @brief Default delayed work callback function implementation.
- * Calls the input function specified at initialization.
- * @param[in,out] work work item.
- */
-
-static void
-DispatchWrapper(CommOSWork *work)
-{
- unsigned int misses;
-
- for (misses = 0; running && (misses < dispatchMaxCycles); ) {
- /* We run for at most dispatchMaxCycles worth of channel no-ops. */
-
- if (!dispatch()) {
- /* No useful work was done, on any of the channels. */
-
- misses++;
- if ((misses % 32) == 0) {
- CommOS_Yield();
- }
- } else {
- misses = 0;
- }
- }
-
- if (running &&
- (work >= &dispatchWorks[0]) &&
- (work <= &dispatchWorks[NR_CPUS - 1])) {
- /*
- * If still running _and_ this was a regular, time-based run, then
- * re-arm the timer.
- */
-
- QueueDelayedWork(dispatchWQ, work, dispatchInterval);
- }
-}
-
-
-/**
- * @brief Initializes work item with specified callback function.
- * @param[in,out] work work queue to initialize.
- * @param func work item to initialize the queue with.
- */
-
-void
-CommOS_InitWork(CommOSWork *work,
- CommOSWorkFunc func)
-{
- INIT_DELAYED_WORK(work, (work_func_t)func);
-}
-
-
-/**
- * @brief Flush execution of a work item
- * @param{in,out] work work item to dequeue
- */
-void
-CommOS_FlushAIOWork(CommOSWork *work)
-{
- if (aioWQ && work) {
- FlushDelayedWork(work);
- }
-}
-
-
-/**
- * @brief Queue a work item to the AIO workqueue.
- * @param[in,out] work work item to enqueue.
- * @return zero if work enqueued, non-zero otherwise.
- */
-
-int
-CommOS_ScheduleAIOWork(CommOSWork *work)
-{
- if (running && aioWQ && work) {
- return QueueDelayedWork(aioWQ, work, 0);
- }
- return -1;
-}
-
-
-/**
- * @brief Initializes the base IO system.
- * @param dispatchTaskName dispatch thread(s) name.
- * @param dispatchFunc dispatch function.
- * @param intervalMillis periodic interval in milliseconds to call dispatch.
- * The floor is 1 jiffy, regardless of how small intervalMillis is
- * @param maxCycles number of cycles to do adaptive polling before scheduling.
- * The maximum number of cycles is DISPATCH_MAX_CYCLES.
- * @param aioTaskName AIO thread(s) name. If NULL, AIO threads aren't started.
- * @return zero is successful, -1 otherwise.
- * @sideeffects Dispatch threads, and if applicable, AIO threads are started.
- */
-
-int
-CommOS_StartIO(const char *dispatchTaskName, // IN
- CommOSDispatchFunc dispatchFunc, // IN
- unsigned int intervalMillis, // IN
- unsigned int maxCycles, // IN
- const char *aioTaskName) // IN
-{
- int rc;
- int cpu;
-
- if (running) {
- CommOS_Debug(("%s: I/O tasks already running.\n", __FUNCTION__));
- return 0;
- }
-
- /*
- * OK, let's test the handler against NULL. Though, the whole concept
- * of checking for NULL pointers, outside cases where NULL is meaningful
- * to the implementation, is relatively useless: garbage, random pointers
- * rarely happen to be all-zeros.
- */
-
- if (!dispatchFunc) {
- CommOS_Log(("%s: a NULL Dispatch handler was passed.\n", __FUNCTION__));
- return -1;
- }
- dispatch = dispatchFunc;
-
- if (intervalMillis == 0) {
- intervalMillis = 4;
- }
- if ((dispatchInterval = msecs_to_jiffies(intervalMillis)) < 1) {
- dispatchInterval = 1;
- }
- if (maxCycles > DISPATCH_MAX_CYCLES) {
- dispatchMaxCycles = DISPATCH_MAX_CYCLES;
- } else if (maxCycles > 0) {
- dispatchMaxCycles = maxCycles;
- }
- CommOS_Debug(("%s: Interval millis %u (jif:%u).\n", __FUNCTION__,
- intervalMillis, dispatchInterval));
- CommOS_Debug(("%s: Max cycles %u.\n", __FUNCTION__, dispatchMaxCycles));
-
- numCpus = num_present_cpus();
- dispatchWQ = CreateWorkqueue(dispatchTaskName);
- if (!dispatchWQ) {
- CommOS_Log(("%s: Couldn't create %s task(s).\n", __FUNCTION__,
- dispatchTaskName));
- return -1;
- }
-
- if (aioTaskName) {
- aioWQ = CreateWorkqueue(aioTaskName);
- if (!aioWQ) {
- CommOS_Log(("%s: Couldn't create %s task(s).\n", __FUNCTION__,
- aioTaskName));
- DestroyWorkqueue(dispatchWQ);
- return -1;
- }
- } else {
- aioWQ = NULL;
- }
-
- running = 1;
- for (cpu = 0; cpu < numCpus; cpu++) {
- CommOS_InitWork(&dispatchWorksNow[cpu], DispatchWrapper);
- CommOS_InitWork(&dispatchWorks[cpu], DispatchWrapper);
- rc = QueueDelayedWorkOn(cpu, dispatchWQ,
- &dispatchWorks[cpu],
- dispatchInterval);
- if (rc != 0) {
- CommOS_StopIO();
- return -1;
- }
- }
- CommOS_Log(("%s: Created I/O task(s) successfully.\n", __FUNCTION__));
- return 0;
-}
-
-
-/**
- * @brief Stops the base IO system.
- * @sideeffects Dispatch threads, and if applicable, AIO threads are stopped.
- */
-
-void
-CommOS_StopIO(void)
-{
- int cpu;
-
- if (running) {
- running = 0;
- if (aioWQ) {
- FlushWorkqueue(aioWQ);
- DestroyWorkqueue(aioWQ);
- aioWQ = NULL;
- }
- FlushWorkqueue(dispatchWQ);
- for (cpu = 0; cpu < numCpus; cpu++) {
- WaitForDelayedWork(&dispatchWorksNow[cpu]);
- WaitForDelayedWork(&dispatchWorks[cpu]);
- }
- DestroyWorkqueue(dispatchWQ);
- dispatchWQ = NULL;
- CommOS_Log(("%s: I/O tasks stopped.\n", __FUNCTION__));
- }
-}
diff --git a/arch/arm/mvp/commkm/comm_os_linux.h b/arch/arm/mvp/commkm/comm_os_linux.h
deleted file mode 100644
index f92c8bd..0000000
--- a/arch/arm/mvp/commkm/comm_os_linux.h
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Contains linux-specific type definitions and function declarations
- */
-
-#ifndef _COMM_OS_LINUX_H_
-#define _COMM_OS_LINUX_H_
-
-#include <linux/types.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-#error "Kernel versions lower than 2.6.20 are not supported"
-#endif
-
-#include <linux/kernel.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-
-/*
- * Type definitions.
- */
-
-typedef atomic_t CommOSAtomic;
-typedef spinlock_t CommOSSpinlock;
-typedef struct mutex CommOSMutex;
-typedef wait_queue_head_t CommOSWaitQueue;
-typedef struct delayed_work CommOSWork;
-typedef void (*CommOSWorkFunc)(CommOSWork *work);
-typedef struct list_head CommOSList;
-typedef struct module *CommOSModule;
-
-
-/*
- * Initializers.
- */
-
-#define CommOSSpinlock_Define DEFINE_SPINLOCK
-
-
-#define COMM_OS_DOLOG(...) printk(KERN_INFO __VA_ARGS__)
-
-
-/**
- * @brief Logs given arguments in debug builds.
- */
-
-#if defined(COMM_OS_DEBUG)
- #define CommOS_Debug(args) COMM_OS_DOLOG args
-#else
- #define CommOS_Debug(args)
-#endif
-
-
-/**
- * @brief Logs given arguments.
- */
-
-#define CommOS_Log(args) COMM_OS_DOLOG args
-
-
-/**
- * @brief Logs function name and location.
- */
-
-#if defined(COMM_OS_TRACE)
-#define TRACE(ptr) \
- do { \
- CommOS_Debug(("%p:%s: at [%s:%d] with arg ptr [0x%p].\n", current, \
- __FUNCTION__, __FILE__, __LINE__, (ptr))); \
- } while (0)
-#else
-#define TRACE(ptr)
-#endif
-
-
-/**
- * @brief Write atomic variable
- * @param[in,out] atomic variable to write
- * @param val new value
- */
-
-static inline void
-CommOS_WriteAtomic(CommOSAtomic *atomic,
- int val)
-{
- atomic_set(atomic, val);
-}
-
-
-/**
- * @brief Reads atomic variable
- * @param atomic variable to read
- * @return value
- */
-
-static inline int
-CommOS_ReadAtomic(CommOSAtomic *atomic)
-{
- return atomic_read(atomic);
-}
-
-
-/**
- * @brief Atomically add value to atomic variable, return new value.
- * @param[in,out] atomic variable
- * @param val value to add
- * @return new value
- */
-
-static inline int
-CommOS_AddReturnAtomic(CommOSAtomic *atomic,
- int val)
-{
- return atomic_add_return(val, atomic);
-}
-
-
-/**
- * @brief Atomically substract value from atomic variable, return new value.
- * @param[in,out] atomic variable
- * @param val value to substract
- * @return new value
- */
-
-static inline int
-CommOS_SubReturnAtomic(CommOSAtomic *atomic,
- int val)
-{
- return atomic_sub_return(val, atomic);
-}
-
-
-/**
- * @brief Initializes a given lock.
- * @param[in,out] lock lock to initialize
- */
-
-static inline void
-CommOS_SpinlockInit(CommOSSpinlock *lock)
-{
- spin_lock_init(lock);
-}
-
-
-/**
- * @brief Locks given lock and disables bottom half processing.
- * @param[in,out] lock lock to lock
- */
-
-static inline void
-CommOS_SpinLockBH(CommOSSpinlock *lock)
-{
- spin_lock_bh(lock);
-}
-
-
-/**
- * @brief Attempts to lock the given lock and disable BH processing.
- * @param[in,out] lock lock to lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_SpinTrylockBH(CommOSSpinlock *lock)
-{
- return !spin_trylock_bh(lock);
-}
-
-
-/**
- * @brief Unlocks given lock and re-enables BH processing.
- * @param[in,out] lock lock to unlock
- */
-
-static inline void
-CommOS_SpinUnlockBH(CommOSSpinlock *lock)
-{
- spin_unlock_bh(lock);
-}
-
-
-/**
- * @brief Locks the given lock.
- * @param[in,out] lock lock to lock
- */
-
-static inline void
-CommOS_SpinLock(CommOSSpinlock *lock)
-{
- spin_lock(lock);
-}
-
-
-/**
- * @brief Attempts to lock the given lock.
- * @param[in,out] lock lock to try-lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_SpinTrylock(CommOSSpinlock *lock)
-{
- return !spin_trylock(lock);
-}
-
-
-/**
- * @brief Unlocks given lock.
- * @param[in,out] lock lock to unlock
- */
-
-static inline void
-CommOS_SpinUnlock(CommOSSpinlock *lock)
-{
- spin_unlock(lock);
-}
-
-
-/**
- * @brief Initializes given mutex.
- * @param[in,out] mutex mutex to initialize
- */
-
-static inline void
-CommOS_MutexInit(CommOSMutex *mutex)
-{
- mutex_init(mutex);
-}
-
-
-/**
- * @brief Acquires mutex.
- * @param[in,out] mutex mutex to lock
- * @return zero if successful, non-zero otherwise (interrupted)
- */
-
-static inline int
-CommOS_MutexLock(CommOSMutex *mutex)
-{
- return mutex_lock_interruptible(mutex);
-}
-
-
-/**
- * @brief Acquires mutex in uninterruptible mode.
- * @param[in,out] mutex mutex to lock
- */
-
-static inline void
-CommOS_MutexLockUninterruptible(CommOSMutex *mutex)
-{
- mutex_lock(mutex);
-}
-
-
-/**
- * @brief Attempts to acquire given mutex.
- * @param[in,out] mutex mutex to try-lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_MutexTrylock(CommOSMutex *mutex)
-{
- return !mutex_trylock(mutex);
-}
-
-
-/**
- * @brief Releases a given mutex.
- * @param[in,out] mutex mutex to unlock
- */
-
-static inline void
-CommOS_MutexUnlock(CommOSMutex *mutex)
-{
- mutex_unlock(mutex);
-}
-
-
-/**
- * @brief Initializes a wait queue.
- * @param[in,out] wq workqueue to initialize
- */
-
-static inline void
-CommOS_WaitQueueInit(CommOSWaitQueue *wq)
-{
- init_waitqueue_head(wq);
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * - a signal is pending
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @param interruptible enable/disable signal pending check
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, if a signal is pending or other error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_DoWait(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis,
- int interruptible)
-{
- int rc;
- DEFINE_WAIT(wait);
- long timeout;
-#if defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- long tmpTimeout;
- long retTimeout;
- const unsigned int interval = 50;
-#endif
-
- if (!timeoutMillis) {
- return -1;
- }
- if ((rc = cond(condArg1, condArg2)) != 0) {
- return rc;
- }
-
-#if defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- timeout = msecs_to_jiffies(interval < *timeoutMillis ?
- interval : (unsigned int)*timeoutMillis);
- retTimeout = msecs_to_jiffies((unsigned int)(*timeoutMillis));
-
- for (; retTimeout >= 0; ) {
- prepare_to_wait(wq, &wait,
- (interruptible?TASK_INTERRUPTIBLE:TASK_UNINTERRUPTIBLE));
- if ((rc = cond(condArg1, condArg2))) {
- break;
- }
- if (interruptible && signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if ((tmpTimeout = schedule_timeout(timeout))) {
- retTimeout -= (timeout - tmpTimeout);
- } else {
- retTimeout -= timeout;
- }
- if (retTimeout < 0) {
- retTimeout = 0;
- }
- }
- finish_wait(wq, &wait);
- if (rc == 0) {
- rc = cond(condArg1, condArg2);
- if (rc && (retTimeout == 0)) {
- retTimeout = 1;
- }
- }
- *timeoutMillis = (unsigned long long)jiffies_to_msecs(retTimeout);
-#else // !defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- timeout = msecs_to_jiffies((unsigned int)(*timeoutMillis));
-
- for (;;) {
- prepare_to_wait(wq, &wait,
- (interruptible?TASK_INTERRUPTIBLE:TASK_UNINTERRUPTIBLE));
- if ((rc = cond(condArg1, condArg2)) != 0) {
- break;
- }
- if (interruptible && signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if ((timeout = schedule_timeout(timeout)) == 0) {
- rc = 0;
- break;
- }
- }
- finish_wait(wq, &wait);
- if (rc == 0) {
- rc = cond(condArg1, condArg2);
- if (rc && (timeout == 0)) {
- timeout = 1;
- }
- }
- *timeoutMillis = (unsigned long long)jiffies_to_msecs(timeout);
-#endif
-
- return rc;
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * - a signal is pending
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, if a signal is pending or other error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_Wait(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis)
-{
- return CommOS_DoWait(wq, cond, condArg1, condArg2, timeoutMillis, 1);
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_WaitUninterruptible(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis)
-{
- return CommOS_DoWait(wq, cond, condArg1, condArg2, timeoutMillis, 0);
-}
-
-
-/**
- * @brief Wakes up task(s) waiting on the given wait queue.
- * @param[in,out] wq wait queue.
- */
-
-static inline void
-CommOS_WakeUp(CommOSWaitQueue *wq)
-{
- wake_up(wq);
-}
-
-
-/**
- * @brief Allocates kernel memory of specified size; does not sleep.
- * @param size size to allocate.
- * @return Address of allocated memory or NULL if the allocation fails.
- */
-
-static inline void *
-CommOS_KmallocNoSleep(unsigned int size)
-{
- return kmalloc(size, GFP_ATOMIC);
-}
-
-
-/**
- * @brief Allocates kernel memory of specified size; may sleep.
- * @param size size to allocate.
- * @return Address of allocated memory or NULL if the allocation fails.
- */
-
-static inline void *
-CommOS_Kmalloc(unsigned int size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-
-/**
- * @brief Frees previously allocated kernel memory.
- * @param obj object to free.
- */
-
-static inline void
-CommOS_Kfree(void *obj)
-{
- if (obj) {
- kfree(obj);
- }
-}
-
-
-/**
- * @brief Yields the current cpu to other runnable tasks.
- */
-
-static inline void
-CommOS_Yield(void)
-{
- cond_resched();
-}
-
-
-/**
- * @brief Gets the current time in milliseconds.
- * @return Current time in milliseconds, with precision of at most one tick.
- */
-
-static inline unsigned long long
-CommOS_GetCurrentMillis(void)
-{
- return (unsigned long long)jiffies_to_msecs(jiffies);
-}
-
-
-/**
- * @brief Initializes given list.
- * @param list list to initialize.
- */
-
-static inline void
-CommOS_ListInit(CommOSList *list)
-{
- INIT_LIST_HEAD(list);
-}
-
-
-/**
- * @brief Tests if list is empty.
- * @param list list to test.
- * @return non-zero if empty, zero otherwise.
- */
-
-#define CommOS_ListEmpty(list) list_empty((list))
-
-
-/**
- * @brief Adds given element to beginning of list.
- * @param list list to add to.
- * @param elem element to add.
- */
-
-#define CommOS_ListAdd(list, elem) list_add((elem), (list))
-
-
-/**
- * @brief Adds given element to end of list.
- * @param list list to add to.
- * @param elem element to add.
- */
-
-#define CommOS_ListAddTail(list, elem) list_add_tail((elem), (list))
-
-
-/**
- * @brief Deletes given element from its list.
- * @param elem element to delete.
- */
-
-#define CommOS_ListDel(elem) \
- do { \
- list_del((elem)); \
- INIT_LIST_HEAD((elem)); \
- } while (0)
-
-
-/**
- * @brief Iterates over a list.
- * @param list list to iterate over.
- * @param[out] item stores next element.
- * @param itemListFieldName name in the item structure storing the list head.
- */
-
-#define CommOS_ListForEach(list, item, itemListFieldName) \
- list_for_each_entry((item), (list), itemListFieldName)
-
-
-/**
- * @brief Iterates safely over a list.
- * @param list list to iterate over.
- * @param[out] item stores next element. May be deleted in the loop.
- * @param[out] tmpItem saves iteration element.
- * @param itemListFieldName name in the item structure storing the list head.
- */
-
-#define CommOS_ListForEachSafe(list, item, tmpItem, itemListFieldName) \
- list_for_each_entry_safe((item), (tmpItem), (list), itemListFieldName)
-
-
-/**
- * @brief Combines two lists, adds second list to beginning of first one.
- * @param list list to add to.
- * @param list2 list to add.
- */
-
-#define CommOS_ListSplice(list, list2) list_splice((list2), (list))
-
-
-/**
- * @brief Combines two lists, adds second list to end of first one.
- * @param list list to add to.
- * @param list2 list to add.
- */
-
-#define CommOS_ListSpliceTail(list, list2) list_splice_tail((list2), (list))
-
-
-/**
- * @brief Gets current module handle.
- * @return module handle.
- */
-
-static inline CommOSModule
-CommOS_ModuleSelf(void)
-{
- return THIS_MODULE;
-}
-
-
-/**
- * @brief Retains module.
- * @param[in,out] module to retain.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-CommOS_ModuleGet(CommOSModule module)
-{
- int rc = 0;
-
- if (!module) {
- goto out;
- }
- if (!try_module_get(module)) {
- rc = -1;
- }
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Releases module.
- * @param[in,out] module to release.
- */
-
-static inline void
-CommOS_ModulePut(CommOSModule module)
-{
- if (module) {
- module_put(module);
- }
-}
-
-
-/**
- * @brief Inserts r/w memory barrier.
- */
-
-#define CommOS_MemBarrier smp_mb
-
-#endif /* _COMM_OS_LINUX_H_ */
diff --git a/arch/arm/mvp/commkm/comm_os_mod_linux.c b/arch/arm/mvp/commkm/comm_os_mod_linux.c
deleted file mode 100644
index 8470de6..0000000
--- a/arch/arm/mvp/commkm/comm_os_mod_linux.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Linux-specific module loading, unloading functions.
- */
-
-#include "comm_os.h"
-#include "comm_os_mod_ver.h"
-
-#include <linux/moduleparam.h>
-
-
-/* Module parameters -- passed as one 'name=value'-list string. */
-
-static char modParams[256];
-module_param_string(COMM_OS_MOD_SHORT_NAME, modParams, sizeof modParams, 0644);
-
-
-/**
- * @brief Module initialization entry point. Calls the commOSModInit
- * function pointer to perform upper layer initialization.
- * @return zero if successful, non-zero otherwise.
- */
-
-static int __init
-ModInit(void)
-{
- int rc;
-
- if (!commOSModInit) {
- CommOS_Log(("%s: Can't find \'init\' function for module \'" \
- COMM_OS_MOD_SHORT_NAME_STRING "\'.\n", __FUNCTION__));
- return -1;
- }
-
- CommOS_Debug(("%s: Module parameters: [%s].\n", __FUNCTION__, modParams));
-
- rc = (*commOSModInit)(modParams);
- if (rc == 0) {
- CommOS_Log(("%s: Module \'" COMM_OS_MOD_SHORT_NAME_STRING \
- "\' has been successfully initialized.\n", __FUNCTION__));
- } else {
- CommOS_Log(("%s: Module \'" COMM_OS_MOD_SHORT_NAME_STRING \
- "\' could not be initialized [%d].\n", __FUNCTION__, rc));
- }
-
- return rc > 0 ? -rc : rc;
-}
-
-
-/**
- * @brief Module exit function. Calls the commOSModExit function pointer
- * to perform upper layer cleanup.
- */
-
-static void __exit
-ModExit(void)
-{
- if (!commOSModExit) {
- CommOS_Log(("%s: Can't find \'fini\' function for module \'" \
- COMM_OS_MOD_SHORT_NAME_STRING "\'.\n", __FUNCTION__));
- return;
- }
-
- (*commOSModExit)();
- CommOS_Log(("%s: Module \'" COMM_OS_MOD_SHORT_NAME_STRING \
- "\' has been stopped.\n", __FUNCTION__));
-}
-
-
-module_init(ModInit);
-module_exit(ModExit);
-
-/* Module information. */
-MODULE_AUTHOR("VMware, Inc.");
-MODULE_DESCRIPTION(COMM_OS_MOD_NAME_STRING);
-MODULE_VERSION(COMM_OS_MOD_VERSION_STRING);
-MODULE_LICENSE("GPL v2");
-/*
- * Starting with SLE10sp2, Novell requires that IHVs sign a support agreement
- * with them and mark their kernel modules as externally supported via a
- * change to the module header. If this isn't done, the module will not load
- * by default (i.e., neither mkinitrd nor modprobe will accept it).
- */
-MODULE_INFO(supported, "external");
diff --git a/arch/arm/mvp/commkm/comm_os_mod_ver.h b/arch/arm/mvp/commkm/comm_os_mod_ver.h
deleted file mode 100644
index 059854c..0000000
--- a/arch/arm/mvp/commkm/comm_os_mod_ver.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Version definitions for the Comm module.
- */
-
-#ifndef _COMM_OS_MOD_VER_H_
-#define _COMM_OS_MOD_VER_H_
-
-#define COMM_OS_MOD_NAME_STRING "VMware communication module"
-#define COMM_OS_MOD_SHORT_NAME comm
-#define COMM_OS_MOD_SHORT_NAME_STRING "comm"
-
-#define COMM_OS_MOD_VERSION 1.0.0.0
-#define COMM_OS_MOD_VERSION_COMMAS 1,0,0,0
-#define COMM_OS_MOD_VERSION_STRING "1.0.0.0"
-
-#endif /* _COM_OS_MOD_VER_H_ */
diff --git a/arch/arm/mvp/commkm/comm_svc.c b/arch/arm/mvp/commkm/comm_svc.c
deleted file mode 100644
index 18f62bd..0000000
--- a/arch/arm/mvp/commkm/comm_svc.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Communication functions based on transport functionality.
- */
-
-#include "comm_os.h"
-#include "comm_os_mod_ver.h"
-#include "comm_svc.h"
-
-
-/*
- * Initialization of module entry and exit callbacks expected by module
- * loading/unloading functions in comm_os.
- */
-
-static int Init(void *args);
-static void Exit(void);
-
-COMM_OS_MOD_INIT(Init, Exit);
-
-static volatile int running; // Initialized and running.
-
-
-/**
- * @brief Allocates and initializes comm global state.
- * Starts input dispatch and aio threads.
- * @param argsIn arguments
- * @return zero if successful, non-zero otherwise.
- */
-
-static int
-Init(void *argsIn)
-{
- int rc = -1;
- unsigned int maxChannels = 8;
- /*
- * Infinite timeout, 1 polling cycle
- * see kernel/time.c: msecs_to_jiffies()
- */
- unsigned int pollingMillis = (unsigned int)-1;
- unsigned int pollingCycles = 1;
- const char *args = argsIn;
-
- if (args && *args) {
- /* coverity[secure_coding] */
- sscanf(args,
- "max_channels:%u,poll_millis:%u,poll_cycles:%u",
- &maxChannels, &pollingMillis, &pollingCycles);
- CommOS_Debug(("%s: arguments [%s].\n", __FUNCTION__, args));
- }
-
- rc = Comm_Init(maxChannels);
- if (rc) {
- goto out;
- }
-
- rc = CommOS_StartIO(COMM_OS_MOD_SHORT_NAME_STRING "-disp",
- Comm_DispatchAll, pollingMillis, pollingCycles,
- COMM_OS_MOD_SHORT_NAME_STRING "-aio");
- if (rc) {
- unsigned long long timeout = 0;
-
- Comm_Finish(&timeout); /* Nothing started, guaranteed to succeed. */
- goto out;
- }
- running = 1;
- rc = 0;
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Attempts to close all channels.
- * @return zero if successful, non-zero otherwise.
- */
-
-static int
-Halt(void)
-{
- unsigned int maxTries = 10;
- int rc = -1;
-
- if (!running) {
- rc = 0;
- goto out;
- }
-
- for ( ; maxTries; maxTries--) {
- unsigned long long timeout = 2000ULL;
-
- CommOS_Debug(("%s: Attempting to halt...\n", __FUNCTION__));
- if (!Comm_Finish(&timeout)) {
- running = 0;
- rc = 0;
- break;
- }
- }
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Stops the comm_rt module.
- * If Halt() call successful, stops input dispatch and aio threads.
- */
-
-static void
-Exit(void)
-{
- if (!Halt()) {
- CommOS_StopIO();
- }
-}
-
-
-/**
- * @brief Registers an implementation block used when attaching to channels
- * in response to transport attach events.
- * @param impl implementation block.
- * @return 0 if successful, non-zero otherwise.
- */
-
-int
-CommSvc_RegisterImpl(const CommImpl *impl)
-{
- return Comm_RegisterImpl(impl);
-}
-
-
-/**
- * @brief Unregisters an implementation block used when attaching to channels
- * in response to transport attach events.
- * @param impl implementation block.
- */
-
-void
-CommSvc_UnregisterImpl(const CommImpl *impl)
-{
- Comm_UnregisterImpl(impl);
-}
-
-
-/**
- * @brief Finds a free entry and initializes it with the information provided.
- * May be called from BH. It doesn't call potentially blocking functions.
- * @param transpArgs transport initialization arguments.
- * @param impl implementation block.
- * @param inBH non-zero if called in bottom half.
- * @param[out] newChannel newly allocated channel.
- * @return zero if successful, non-zero otherwise.
- * @sideeffects Initializes the communications channel with given parameters
- */
-
-int
-CommSvc_Alloc(const CommTranspInitArgs *transpArgs,
- const CommImpl *impl,
- int inBH,
- CommChannel *newChannel)
-{
- return Comm_Alloc(transpArgs, impl, inBH, newChannel);
-}
-
-
-/**
- * @brief Zombifies a channel. May fail if channel isn't active.
- * @param channel channel to zombify.
- * @param inBH non-zero if called in bottom half.
- * @return zero if channel zombified, non-zero otherwise.
- */
-
-int
-CommSvc_Zombify(CommChannel channel,
- int inBH)
-{
- return Comm_Zombify(channel, inBH);
-}
-
-
-/**
- * @brief Reports whether a channel is active.
- * @param channel channel to report on.
- * @return non-zero if channel active, zero otherwise.
- */
-
-int
-CommSvc_IsActive(CommChannel channel)
-{
- return Comm_IsActive(channel);
-}
-
-
-/**
- * @brief Retrieves a channel's transport initialization arguments.
- * It doesn't lock, the caller must ensure the channel may be accessed.
- * @param channel CommChannel structure to get initialization arguments from.
- * @return initialization arguments used to allocate/attach to channel.
- */
-
-CommTranspInitArgs
-CommSvc_GetTranspInitArgs(CommChannel channel)
-{
- return Comm_GetTranspInitArgs(channel);
-}
-
-
-/**
- * @brief Retrieves upper layer state (pointer). It doesn't lock, the caller
- * must ensure the channel may be accessed.
- * @param channel CommChannel structure to get state from.
- * @return pointer to upper layer state.
- */
-
-void *
-CommSvc_GetState(CommChannel channel)
-{
- return Comm_GetState(channel);
-}
-
-
-/**
- * @brief Writes a fully formatted packet (containing payload data, if
- * applicable) to the specified channel.
- *
- * The operation may block until enough write space is available, but no
- * more than the specified interval. The operation either writes the full
- * amount of bytes, or it fails. Warning: callers must _not_ use the
- * _Lock/_Unlock functions to bracket calls to this function.
- * @param[in,out] channel channel to write to.
- * @param packet packet to write.
- * @param[in,out] timeoutMillis interval in milliseconds to wait.
- * @return number of bytes written, 0 if it times out, -1 error.
- * @sideeffects Data may be written to the channel.
- */
-
-int
-CommSvc_Write(CommChannel channel,
- const CommPacket *packet,
- unsigned long long *timeoutMillis)
-{
- return Comm_Write(channel, packet, timeoutMillis);
-}
-
-
-/**
- * @brief Writes a packet and associated payload data to the specified channel.
- *
- * The operation may block until enough write space is available, but not
- * more than the specified interval. The operation either writes the full
- * amount of bytes, or it fails. Users may call this function successively
- * to write several packets from large {io|k}vecs. If that's the case, the
- * packet header needs to be updated in between calls, for the different
- * (total) lengths. Warning: callers must _not_ use the _Lock/_Unlock
- * functions to bracket calls to this function.
- * @param[in,out] channel the specified channel
- * @param packet packet to write
- * @param[in,out] vec kvec to write from
- * @param[in,out] vecLen length of kvec
- * @param[in,out] timeoutMillis interval in milliseconds to wait
- * @param[in,out] iovOffset must be set to 0 before first call (internal cookie)
- * @return number of bytes written, 0 if it timed out, -1 error
- * @sideeffects data may be written to the channel
- */
-
-int
-CommSvc_WriteVec(CommChannel channel,
- const CommPacket *packet,
- struct kvec **vec,
- unsigned int *vecLen,
- unsigned long long *timeoutMillis,
- unsigned int *iovOffset)
-{
- return Comm_WriteVec(channel, packet, vec, vecLen, timeoutMillis, iovOffset);
-}
-
-
-/**
- * @brief Releases channel ref count. This function is exported for the upper
- * layer's 'activateNtf' callback which may be run asynchronously. The
- * callback is protected from concurrent channel releases until it calls
- * this function.
- * @param[in,out] channel CommChannel structure to release.
- */
-
-void
-CommSvc_Put(CommChannel channel)
-{
- Comm_Put(channel);
-}
-
-
-/**
- * @brief Uses the read lock. This function is exported for the upper layer
- * such that it can order acquisition of a different lock (socket) with
- * the release of the dispatch lock.
- * @param[in,out] channel CommChannel structure to unlock.
- */
-
-void
-CommSvc_DispatchUnlock(CommChannel channel)
-{
- Comm_DispatchUnlock(channel);
-}
-
-
-/**
- * @brief Lock the channel.
- *
- * Uses the writer lock. This function is exported for the upper layer
- * to ensure that channel isn't closed while updating the layer state.
- * It also guarantees that if the lock is taken, the entry is either ACTIVE
- * or ZOMBIE. Operations using this function are expected to be short,
- * since unlike the _Write functions, these callers cannot be signaled.
- * @param[in,out] channel CommChannel structure to lock.
- * @return zero if successful, -1 otherwise.
- */
-
-int
-CommSvc_Lock(CommChannel channel)
-{
- return Comm_Lock(channel);
-}
-
-
-/**
- * @brief Unlock the channel.
- *
- * Uses the writer lock. This function is exported for the upper layer
- * to ensure that channel isn't closed while updating the layer state.
- * See Comm_WriteLock for details).
- * @param[in,out] channel CommChannel structure to unlock.
- */
-
-void
-CommSvc_Unlock(CommChannel channel)
-{
- Comm_Unlock(channel);
-}
-
-
-/**
- * @brief Schedules a work item on the AIO thread(s).
- * @param[in,out] work work item to be scheduled.
- * @return zero if successful, -1 otherwise.
- */
-
-int
-CommSvc_ScheduleAIOWork(CommOSWork *work)
-{
- return CommOS_ScheduleAIOWork(work);
-}
-
-
-/**
- * @brief Requests events be posted in-line after the function completes.
- * @param channel channel object.
- * @return current number of requests for inline event posting, or -1 on error.
- */
-
-unsigned int
-CommSvc_RequestInlineEvents(CommChannel channel)
-{
- return Comm_RequestInlineEvents(channel);
-}
-
-
-/**
- * @brief Requests events be posted out-of-band after the function completes.
- * @param channel channel object.
- * @return current number of requests for inline event posting, or -1 on error.
- */
-
-unsigned int
-CommSvc_ReleaseInlineEvents(CommChannel channel)
-{
- return Comm_ReleaseInlineEvents(channel);
-}
-
-
-#if defined(__linux__)
-EXPORT_SYMBOL(CommSvc_RegisterImpl);
-EXPORT_SYMBOL(CommSvc_UnregisterImpl);
-EXPORT_SYMBOL(CommSvc_Alloc);
-EXPORT_SYMBOL(CommSvc_Zombify);
-EXPORT_SYMBOL(CommSvc_IsActive);
-EXPORT_SYMBOL(CommSvc_GetTranspInitArgs);
-EXPORT_SYMBOL(CommSvc_GetState);
-EXPORT_SYMBOL(CommSvc_Write);
-EXPORT_SYMBOL(CommSvc_WriteVec);
-EXPORT_SYMBOL(CommSvc_Put);
-EXPORT_SYMBOL(CommSvc_DispatchUnlock);
-EXPORT_SYMBOL(CommSvc_Lock);
-EXPORT_SYMBOL(CommSvc_Unlock);
-EXPORT_SYMBOL(CommSvc_ScheduleAIOWork);
-EXPORT_SYMBOL(CommSvc_RequestInlineEvents);
-EXPORT_SYMBOL(CommSvc_ReleaseInlineEvents);
-#endif // defined(__linux__)
diff --git a/arch/arm/mvp/commkm/comm_svc.h b/arch/arm/mvp/commkm/comm_svc.h
deleted file mode 100644
index c4f3292..0000000
--- a/arch/arm/mvp/commkm/comm_svc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Communication functions exported by the comm_rt module.
- */
-
-#ifndef _COMM_SVC_H_
-#define _COMM_SVC_H_
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "comm.h"
-
-int CommSvc_RegisterImpl(const CommImpl *impl);
-void CommSvc_UnregisterImpl(const CommImpl *impl);
-int CommSvc_Zombify(CommChannel channel, int inBH);
-int CommSvc_IsActive(CommChannel channel);
-CommTranspInitArgs CommSvc_GetTranspInitArgs(CommChannel channel);
-void *CommSvc_GetState(CommChannel channel);
-void CommSvc_Put(CommChannel channel);
-void CommSvc_DispatchUnlock(CommChannel channel);
-int CommSvc_Lock(CommChannel channel);
-void CommSvc_Unlock(CommChannel channel);
-int CommSvc_ScheduleAIOWork(CommOSWork *work);
-
-int
-CommSvc_Alloc(const CommTranspInitArgs *transpArgs,
- const CommImpl *impl,
- int inBH,
- CommChannel *newChannel);
-
-int
-CommSvc_Write(CommChannel channel,
- const CommPacket *packet,
- unsigned long long *timeoutMillis);
-
-int
-CommSvc_WriteVec(CommChannel channel,
- const CommPacket *packet,
- struct kvec **vec,
- unsigned int *vecLen,
- unsigned long long *timeoutMillis,
- unsigned int *iovOffset);
-
-unsigned int CommSvc_RequestInlineEvents(CommChannel channel);
-unsigned int CommSvc_ReleaseInlineEvents(CommChannel channel);
-
-#endif // _COMM_SVC_H_
diff --git a/arch/arm/mvp/commkm/comm_transp.h b/arch/arm/mvp/commkm/comm_transp.h
deleted file mode 100644
index 6cc58ae..0000000
--- a/arch/arm/mvp/commkm/comm_transp.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Generic shared memory transport API.
- */
-
-#ifndef _COMM_TRANSP_H_
-#define _COMM_TRANSP_H_
-
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/*
- * Common shared memory identifier.
- * External handle that makes sense to both hypervisor and guest.
- */
-
-#define COMM_TRANSP_ID_8_ANY ((unsigned char)-1)
-#define COMM_TRANSP_ID_32_ANY ((unsigned int)-1)
-#define COMM_TRANSP_ID_64_ANY ((unsigned long long)-1)
-
-
-typedef struct CommTranspID {
- union {
- unsigned char d8[8];
- unsigned int d32[2];
- unsigned long long d64;
- };
-} CommTranspID;
-
-
-/* Basic initialization arguments. */
-
-typedef enum CommTranspInitMode {
- COMM_TRANSP_INIT_CREATE = 0x0,
- COMM_TRANSP_INIT_ATTACH = 0x1
-} CommTranspInitMode;
-
-typedef struct CommTranspInitArgs {
- unsigned int capacity; // Shared memory capacity.
- unsigned int type; // Type / implementation using this area.
- CommTranspID id; // ID (name) of shared memory area.
- CommTranspInitMode mode; // Init mode (above).
-} CommTranspInitArgs;
-
-
-/**
- * @brief Generate a type id from description (protocol) string. This function
- * uses djb2, a string hashing algorithm by Dan Bernstein.
- * (see http://www.cse.yorku.ca/~oz/hash.html)
- * @param str string to hash
- * @return 32-bit hash value
- */
-
-static inline unsigned int
-CommTransp_GetType(const char *str)
-{
- unsigned int hash = 5381;
- int c;
-
- while ((c = *str++)) {
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
- }
- return hash;
-}
-
-#endif // _COMM_TRANSP_H_
diff --git a/arch/arm/mvp/commkm/comm_transp_impl.h b/arch/arm/mvp/commkm/comm_transp_impl.h
deleted file mode 100644
index 113cd21..0000000
--- a/arch/arm/mvp/commkm/comm_transp_impl.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Generic shared memory transport private API.
- */
-
-#ifndef _COMM_TRANSP_IMPL_H_
-#define _COMM_TRANSP_IMPL_H_
-
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "comm_transp.h"
-
-
-/* Shared memory opaque descriptor/handle. Only meaningful locally. */
-
-typedef struct CommTranspPriv *CommTransp;
-
-
-/* Asynchronous signaling initialization arguments. */
-
-typedef enum CommTranspIOEvent {
- COMM_TRANSP_IO_DETACH = 0x0,
- COMM_TRANSP_IO_IN = 0x1,
- COMM_TRANSP_IO_OUT = 0x2,
- COMM_TRANSP_IO_INOUT = 0x3
-} CommTranspIOEvent;
-
-typedef struct CommTranspEvent {
- void (*ioEvent)(CommTransp transp, CommTranspIOEvent event, void *data);
- void *ioEventData;
-} CommTranspEvent;
-
-
-/*
- * Mechanism to detect and optionally attach to, created shared memory regions.
- */
-
-typedef struct CommTranspListener {
- int (*probe)(CommTranspInitArgs *transpArgs, void *probeData);
- void *probeData;
-} CommTranspListener;
-
-
-
-/*
- * Function prototypes.
- */
-
-int CommTranspEvent_Init(void);
-void CommTranspEvent_Exit(void);
-int CommTranspEvent_Process(CommTranspID *transpID, CommTranspIOEvent event);
-int
-CommTranspEvent_Raise(unsigned int peerEvID,
- CommTranspID *transpID,
- CommTranspIOEvent event);
-
-int CommTransp_Init(void);
-void CommTransp_Exit(void);
-
-int CommTransp_Register(const CommTranspListener *listener);
-void CommTransp_Unregister(const CommTranspListener *listener);
-int
-CommTransp_Notify(const CommTranspID *notificationCenterID,
- CommTranspInitArgs *transpArgs);
-
-int
-CommTransp_Open(CommTransp *transp,
- CommTranspInitArgs *transpArgs,
- CommTranspEvent *transpEvent);
-void CommTransp_Close(CommTransp transp);
-
-int CommTransp_EnqueueSpace(CommTransp transp);
-int CommTransp_EnqueueReset(CommTransp transp);
-int CommTransp_EnqueueCommit(CommTransp transp);
-int
-CommTransp_EnqueueSegment(CommTransp transp,
- const void *buf,
- unsigned int bufLen);
-
-int CommTransp_DequeueSpace(CommTransp transp);
-int CommTransp_DequeueReset(CommTransp transp);
-int CommTransp_DequeueCommit(CommTransp transp);
-int
-CommTransp_DequeueSegment(CommTransp transp,
- void *buf,
- unsigned int bufLen);
-
-unsigned int CommTransp_RequestInlineEvents(CommTransp transp);
-unsigned int CommTransp_ReleaseInlineEvents(CommTransp transp);
-
-
-/**
- * @brief Enqueues data into the transport object, data is available for
- * reading immediately.
- * @param transp handle to the transport object.
- * @param buf bytes to enqueue.
- * @param bufLen number of bytes to enqueue.
- * @return number of bytes enqueued on success, < 0 otherwise.
- */
-
-static inline int
-CommTransp_EnqueueAtomic(CommTransp transp,
- const void *buf,
- unsigned int bufLen)
-{
- int rc;
-
- CommTransp_EnqueueReset(transp);
- rc = CommTransp_EnqueueSegment(transp, buf, bufLen);
- if (CommTransp_EnqueueCommit(transp)) {
- rc = -1;
- }
- return rc;
-}
-
-
-/**
- * @brief Dequeues data from the transport object into a buffer.
- * @param transp handle to the transport object.
- * @param[out] buf buffer to copy to.
- * @param bufLen number of bytes to dequeue.
- * @return number of bytes dequeued on success, < 0 otherwise,
- */
-
-static inline int
-CommTransp_DequeueAtomic(CommTransp transp,
- void *buf,
- unsigned int bufLen)
-{
- int rc;
-
- CommTransp_DequeueReset(transp);
- rc = CommTransp_DequeueSegment(transp, buf, bufLen);
- if (CommTransp_DequeueCommit(transp)) {
- rc = -1;
- }
- return rc;
-}
-
-#endif // _COMM_TRANSP_IMPL_H_
diff --git a/arch/arm/mvp/commkm/comm_transp_mvp.c b/arch/arm/mvp/commkm/comm_transp_mvp.c
deleted file mode 100644
index f755de9..0000000
--- a/arch/arm/mvp/commkm/comm_transp_mvp.c
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Generic shared memory transport API.
- */
-#include <linux/wait.h>
-
-#include "comm_os.h"
-#include "comm_transp_impl.h"
-
-#include "mvp_types.h"
-#include "qp.h"
-
-
-/*
- * Opaque CommTransp structure. See comm_transp.h
- */
-
-struct CommTranspPriv {
- QPHandle *qp;
- CommTranspEvent event;
- unsigned int peerEvID;
- unsigned int writeSize;
- unsigned int readSize;
- uint32 backRef;
- CommOSWork work;
- CommOSAtomic raiseInline;
-};
-
-/*
- * Transport table object accounting
- */
-
-typedef struct TranspTableEntry {
- CommOSAtomic holds;
- CommTransp transp;
- CommOSWaitQueue wq;
-} TranspTableEntry;
-
-TranspTableEntry transpTable[QP_MAX_QUEUE_PAIRS];
-static CommOSSpinlock_Define(transpTableLock);
-
-/**
- * @brief Destroy the transport object
- * @param transp transport object to destroy
- * @sideeffects detaches from queue pair
- */
-
-static void
-DestroyTransp(CommTransp transp)
-{
- CommTranspID transpID;
- int32 rc;
-
- if (!transp) {
- CommOS_Debug(("Failed to close channel: Bad handle\n"));
- return;
- }
-
- CommOS_Log(("%s: Detaching channel [%u:%u]\n",
- __FUNCTION__,
- transp->qp->id.context,
- transp->qp->id.resource));
-
- transpID.d32[0] = transp->qp->id.context;
- transpID.d32[1] = transp->qp->id.resource;
-
-#if !defined(COMM_BUILDING_SERVER)
- /*
- * Tell the host to detach, will block in the host
- * until the host has unmapped memory. Once the
- * host has unmapped, it is safe to free.
- */
- CommTranspEvent_Raise(transp->peerEvID,
- &transpID,
- COMM_TRANSP_IO_DETACH);
-#endif
-
- rc = QP_Detach(transp->qp);
-
-#if defined(COMM_BUILDING_SERVER)
- /*
- * Wake up waiters now that unmapping is complete
- */
- CommOS_WakeUp(&transpTable[transp->backRef].wq);
-#endif
-
- CommOS_Kfree(transp);
- if (rc != QP_SUCCESS) {
- CommOS_Log(("%s: Failed to detach. rc: %d\n", __FUNCTION__, rc));
- } else {
- CommOS_Log(("%s: Channel detached.\n", __FUNCTION__));
- }
-}
-
-
-/**
- * @brief Initialize the transport object table
- */
-
-static void
-TranspTableInit(void)
-{
- uint32 i;
- CommOS_SpinLock(&transpTableLock);
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- CommOS_WriteAtomic(&transpTable[i].holds, -1);
- transpTable[i].transp = NULL;
- }
- CommOS_SpinUnlock(&transpTableLock);
-}
-
-
-/**
- * @brief Add a transport object into the table
- * @param transp handle to the transport object
- * @return 0 on success, -1 otherwise
- * @sideeffects increments entry refcount
- */
-
-static inline int32
-TranspTableAdd(CommTransp transp)
-{
- uint32 i;
-
- if (!transp) {
- return -1;
- }
-
- CommOS_SpinLock(&transpTableLock);
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- if ((transpTable[i].transp) == NULL) {
- transpTable[i].transp = transp;
- CommOS_WriteAtomic(&transpTable[i].holds, 1);
- CommOS_WaitQueueInit(&transpTable[i].wq);
- transp->backRef = i;
- break;
- }
- }
- CommOS_SpinUnlock(&transpTableLock);
-
- return 0;
-}
-
-/**
- * @brief retrieve a transport object and increment its ref count
- * @param id transport id to retrieve
- * @return transport object, or NULL if not found
- * @sideeffects increments entry ref count
- */
-
-static inline CommTransp
-TranspTableGet(CommTranspID *id)
-{
- CommTransp transp;
- uint32 i;
-
- if (!id) {
- return NULL;
- }
-
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- transp = transpTable[i].transp;
- if (transp &&
- (transp->qp->id.context == id->d32[0]) &&
- (transp->qp->id.resource == id->d32[1])) {
- CommOS_AddReturnAtomic(&transpTable[i].holds, 1);
- return transp;
- }
- }
- CommOS_Debug(("%s: couldn't find transport object\n", __FUNCTION__));
-
- return NULL;
-}
-
-/**
- * @brief Puts back a previously TranspGet-ed transport object.
- * @param transp the transport object.
- * @sideeffects decrements the transport reference count.
- * frees object if refcount now zero
- */
-
-static inline void
-TranspTablePut(CommTransp transp)
-{
- int32 holds;
- int32 backRef;
- if (!transp) {
- return;
- }
-
- backRef = transp->backRef;
- BUG_ON(backRef >= QP_MAX_QUEUE_PAIRS);
-
- holds = CommOS_SubReturnAtomic(&transpTable[backRef].holds, 1);
- if (holds > 0) {
- return;
- }
- BUG_ON(holds < 0);
-
- CommOS_SpinLock(&transpTableLock);
- CommOS_WriteAtomic(&transpTable[backRef].holds, -1);
- transpTable[backRef].transp = NULL;
- CommOS_SpinUnlock(&transpTableLock);
- DestroyTransp(transp);
-}
-
-
-/**
- * @brief Puts back a previously TranspGet-ed transport object.
- * @param transp the transport object.
- * @sideeffects decrements the transport reference count.
- * asserts that remaining count > 0
- */
-
-static inline void
-TranspTablePutNF(CommTransp transp)
-{
- int32 holds;
- int32 backRef;
- if (!transp) {
- return;
- }
-
- backRef = transp->backRef;
- BUG_ON(backRef >= QP_MAX_QUEUE_PAIRS);
-
- holds = CommOS_SubReturnAtomic(&transpTable[backRef].holds, 1);
- BUG_ON(holds <= 0);
-}
-
-
-/**
- * @brief Raises INOUT event in-line or out-of-band. Note that this function
- * expects the transport object to be held prior to being called.
- * @param arg work item of transport object.
- */
-
-static void
-RaiseEvent(CommOSWork *arg)
-{
-#if !defined(__linux__)
-#error "RaiseEvent() is only supported on linux. Port 'container_of'!"
-#endif
- CommTransp transp = container_of(arg, struct CommTranspPriv, work);
- CommTranspID transpID = {{
- .d32 = {
- [0] = transp->qp->id.context,
- [1] = transp->qp->id.resource
- }
- }};
-
- CommTranspEvent_Raise(transp->peerEvID,
- &transpID,
- COMM_TRANSP_IO_INOUT);
- TranspTablePut(transp);
-}
-
-
-/**
- * @brief Requests events be posted in-line after the function completes.
- * @param transp transport object.
- * @return current number of requests for inline event posting.
- * @sideeffects posts an event on the first transition to in-line processing.
- */
-
-unsigned int
-CommTransp_RequestInlineEvents(CommTransp transp)
-{
- unsigned int res = CommOS_AddReturnAtomic(&transp->raiseInline, 1);
- if (res == 1) {
- /* On the first (effective) transition, make sure an event is raised. */
-
- CommOS_AddReturnAtomic(&transpTable[transp->backRef].holds, 1);
- RaiseEvent(&transp->work);
- }
- return res;
-}
-
-
-/**
- * @brief Requests events be posted out-of-band after the function completes.
- * @param transp transport object.
- * @return current number of requests for inline event posting.
- */
-
-unsigned int
-CommTransp_ReleaseInlineEvents(CommTransp transp)
-{
- return CommOS_SubReturnAtomic(&transp->raiseInline, 1);
-}
-
-
-/*
- * Comm Offload server callbacks.
- */
-
-#if defined(COMM_BUILDING_SERVER)
-
-#define COMM_MAX_LISTENERS QP_MAX_LISTENERS
-
-static int32 NotifyCB(const QPInitArgs *args);
-static void DetachCB(void *data);
-
-static CommOSSpinlock_Define(listenersLock);
-static CommTranspListener listeners[COMM_MAX_LISTENERS];
-static uint32 numListeners = 0;
-
-
-/**
- * @brief Notify callback when guests attach to queue pairs. Notifies any
- * registered listeners (e.g. Comm layer).
- * @param args Initialization arguments used by the guest to initialize
- * its queue pair
- * @return 0 on success, <0 otherwise. see qp.h for error codes.
- */
-
-static int32
-NotifyCB(const QPInitArgs* args)
-{
- CommTranspInitArgs transpArgs;
- uint32 i;
- int32 rc = -1;
-
- if (!args) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- transpArgs.id.d32[0] = args->id.context;
- transpArgs.id.d32[1] = args->id.resource;
- transpArgs.capacity = args->capacity;
- transpArgs.type = args->type;
-
- CommOS_SpinLock(&listenersLock);
- for (i = 0; i < COMM_MAX_LISTENERS; i++) {
- if (listeners[i].probe &&
- (listeners[i].probe(&transpArgs, listeners[i].probeData) == 0)) {
- CommOS_Debug(("%s: Delivered notify event to listener %u\n",
- __FUNCTION__,
- i));
- rc = 0;
- break;
- }
- }
- CommOS_SpinUnlock(&listenersLock);
- return rc;
-}
-
-
-/**
- * @brief Detach callback when guests detach from queue pairs. Notifies
- * any registered listeners (e.g. CommComm layer).
- * @param data Transport object passed when the callback was registered
- */
-
-static void
-DetachCB(void *data)
-{
- CommTransp transp = data;
- if (!transp || !(transp->event.ioEvent)) {
- return;
- }
- CommOS_Debug(("%s: Guest detached from [%u:%u]\n",
- __FUNCTION__,
- transp->qp->id.context,
- transp->qp->id.resource));
- transp->event.ioEvent(transp, COMM_TRANSP_IO_DETACH, transp->event.ioEventData);
-}
-#endif
-
-
-/**
- * @brief Performs one-time initialization of mvp transport provider.
- * @return 0 on success, < 0 otherwise.
- */
-
-int
-CommTransp_Init(void)
-{
- int32 rc;
- TranspTableInit();
-
- rc = CommTranspEvent_Init();
-
-#if defined(COMM_BUILDING_SERVER)
- if (!rc) {
- QP_RegisterListener(NotifyCB);
- }
-#endif
- return rc;
-}
-
-
-/**
- * @brief Performs clean-up of mvp transport provider.
- */
-
-void
-CommTransp_Exit(void)
-{
- CommTranspEvent_Exit();
-#if defined(COMM_BUILDING_SERVER)
- QP_UnregisterListener(NotifyCB);
-#endif
-}
-
-#if defined(COMM_BUILDING_SERVER)
-
-/**
- * @brief Checks for a successful detach from Comm
- * @param arg1 back reference index for channel in transport table
- * @param arg2 ignored
- * @return 1 if detach completed, 0 otherwise
- */
-
-static int
-DetachCondition(void *arg1, void *arg2)
-{
- uint32 backRef = (uint32)arg1;
-
- return (CommOS_ReadAtomic(&transpTable[backRef].holds) == -1);
-}
-#endif
-
-
-/**
- * @brief Processes a raised signal event. This is a callback function called
- * from a comm_transp_ev plugin when a signal is received. Delivers an event
- * to one or more channels. If id->d32[1] == COMM_TRANSP_ID_32_ANY, the event
- * will be delivered to all registered channels associated with vmID
- * id->d32[0].
- * @param id identifies a transport object to signal.
- * @param event type of event.
- * @return 0 if delivered to at least one channel, -1 on failure.
- */
-
-int
-CommTranspEvent_Process(CommTranspID *id,
- CommTranspIOEvent event)
-{
- int rc = 0;
- unsigned int delivered = 0;
- unsigned int backRef;
- int i = 0;
-
- CommTransp transp;
- uint32 raiseOnAllChannels = (id->d32[1] == COMM_TRANSP_ID_32_ANY);
- uint32 channels = raiseOnAllChannels ? QP_MAX_QUEUE_PAIRS : 1;
-
- while (channels--) {
- if (raiseOnAllChannels) {
- id->d32[1] = i++;
- }
- transp = TranspTableGet(id);
- if (transp) {
- if (transp->event.ioEvent) {
- transp->event.ioEvent(transp, event, transp->event.ioEventData);
- }
- backRef = transp->backRef;
- TranspTablePut(transp);
-
-#if defined(COMM_BUILDING_SERVER)
- /*
- * Wait for unmap on IO_DETACH, return to monitor.
- */
- if (event == COMM_TRANSP_IO_DETACH) {
- unsigned long long timeout = 30000;
-
- rc = CommOS_Wait(&transpTable[backRef].wq,
- DetachCondition,
- (void*)backRef,
- NULL,
- &timeout);
- switch (rc) {
- case 1: // Memory successfully unmapped
- rc = 0;
- break;
- default: // Timed out or other error.
- return -1;
- }
- }
-#endif
- delivered++;
- }
- }
-
- rc = (delivered > 0) ? 0 : -1;
- return rc;
-}
-
-
-/**
- * @brief Register a listener to be notified when guests attach to the Comm
- * offload server
- * @param listener the listener to be notified
- * @return 0 on success, -1 on failure
- */
-
-int
-CommTransp_Register(const CommTranspListener *listener)
-{
- int32 rc = -1;
-#if defined(COMM_BUILDING_SERVER)
- uint32 i;
-
- if (!listener) {
- return -1;
- }
-
- CommOS_SpinLock(&listenersLock);
- for (i = 0; i < COMM_MAX_LISTENERS; i++) {
- if ((listeners[i].probe == NULL) &&
- (listeners[i].probeData == NULL)) {
- listeners[i] = *listener;
- numListeners++;
- rc = 0;
- CommOS_Debug(("%s: Registered listener %u\n", __FUNCTION__, i));
- break;
- }
- }
- CommOS_SpinUnlock(&listenersLock);
-#endif
- return rc;
-}
-
-
-/**
- * @brief Unregisters a listener from the transport event notification system
- * @param listener listener to unregister
- * @return 0 on success
- */
-
-void
-CommTransp_Unregister(const CommTranspListener *listener)
-{
-#if defined(COMM_BUILDING_SERVER)
- uint32 i;
-
- if (!listener || !listener->probe) {
- return;
- }
-
-
- CommOS_SpinLock(&listenersLock);
- for (i = 0; i < COMM_MAX_LISTENERS; i++) {
- if ((listeners[i].probe == listener->probe) &&
- (listeners[i].probeData == listener->probeData)) {
- listeners[i].probe = NULL;
- listeners[i].probeData = NULL;
- numListeners--;
- CommOS_Debug(("%s: Unregistered listener %u\n", __FUNCTION__, i));
- }
- }
- CommOS_SpinUnlock(&listenersLock);
-#endif
-}
-
-
-/**
- * @brief Allocates and initializes a transport object
- * @param[in,out] transp handle to the transport to allocate and initialize
- * @param transpArgs initialization arguments (see pvtcpTransp.h)
- * @param transpEvent event callback to be delivered when events occur (e.g.
- * detach events)
- * @return 0 on success, <0 otherwise. See qp.h for error codes.
- * @sideeffects Allocates memory
- */
-
-int
-CommTransp_Open(CommTransp *transp,
- CommTranspInitArgs *transpArgs,
- CommTranspEvent *transpEvent)
-{
- int32 rc = -1;
- QPHandle *qp = NULL;
- CommTransp transpOut = NULL;
- QPInitArgs qpInitArgs;
-
- if (!transp || !transpArgs) {
- return -1;
- }
-
- CommOS_Log(("%s: Attaching to [%u:%u]. Capacity: %u\n",
- __FUNCTION__,
- transpArgs->id.d32[1],
- transpArgs->id.d32[0],
- transpArgs->capacity));
-
- qpInitArgs.id.context = transpArgs->id.d32[0];
- qpInitArgs.id.resource = transpArgs->id.d32[1];
- qpInitArgs.capacity = transpArgs->capacity;
- qpInitArgs.type = transpArgs->type;
-
- if (!(transpOut = CommOS_Kmalloc(sizeof *transpOut))) {
- rc = -1;
- goto out;
- }
-
- /*
- * Attach to the queue pair
- */
- rc = QP_Attach(&qpInitArgs, &qp);
- if (rc < 0) {
- rc = -1;
- goto out;
- }
-
- transpOut->qp = qp;
-
- /*
- * Reassign ID so Comm knows what ID was actually given
- */
- transpArgs->id.d32[0] = qp->id.context;
- transpArgs->id.d32[1] = qp->id.resource;
-
- if (transpEvent) {
- transpOut->event = *transpEvent;
- } else {
- transpOut->event.ioEvent = NULL;
- transpOut->event.ioEventData = NULL;
- }
-
-#if defined(COMM_BUILDING_SERVER)
- CommOS_Debug(("%s: Registering detach CB on id %u...\n",
- __FUNCTION__, transpArgs->id.d32[1]));
- QP_RegisterDetachCB(transpOut->qp, DetachCB, transpOut);
-#endif
-
- transpOut->peerEvID = COMM_TRANSP_ID_32_ANY;
- transpOut->writeSize = 0;
- transpOut->readSize = 0;
- CommOS_InitWork(&transpOut->work, RaiseEvent);
- CommOS_WriteAtomic(&transpOut->raiseInline, 0);
-
- if (TranspTableAdd(transpOut)) {
- CommOS_Log(("%s: Exceeded max limit of transport objects!\n",
- __FUNCTION__));
- DestroyTransp(transpOut);
- rc = -1;
- goto out;
- }
-
- *transp = transpOut;
- rc = 0;
-
- CommOS_Log(("%s: Channel attached.\n", __FUNCTION__));
-
-out:
- if (rc && transpOut) {
- CommOS_Log(("%s: Failed to attach: %d\n", __FUNCTION__, rc));
- CommOS_Kfree(transpOut);
- }
-
- return rc;
-}
-
-
-/**
- * @brief Tear down the transport channel, destroy the object if the refcount
- * drops to zero
- * @param transp handle to the transport channel
- * @sideeffects decrements the entry's refcount
- */
-
-void
-CommTransp_Close(CommTransp transp) {
- if (!transp) {
- return;
- }
- CommOS_FlushAIOWork(&transp->work);
- TranspTablePut(transp);
-}
-
-
-/**
- * @brief Returns available space for enqueue, in bytes
- * @param transp handle to the transport object
- * @return available space in the queue for enqueue operations, <0
- * on error conditions. see qp.h for error codes.
- */
-
-int
-CommTransp_EnqueueSpace(CommTransp transp)
-{
- if (!transp) {
- return -1;
- }
- return QP_EnqueueSpace(transp->qp);
-}
-
-
-/**
- * @brief Discards any pending enqueues
- * @param transp handle to the transport object
- * @return 0 on success, <0 otherwise. see qp.h for error codes
- */
-
-int
-CommTransp_EnqueueReset(CommTransp transp)
-{
- if (!transp) {
- return -1;
- }
- transp->writeSize = 0;
- return QP_EnqueueReset(transp->qp);
-}
-
-
-/**
- * @brief Enqueues a segment of data into the transport object
- * @param transp handle to the transport object
- * @param buf data to enqueue
- * @param bufLen number of bytes to enqueue
- * @return number of bytes enqueued on success, <0 otherwise. see qp.h
- * for error codes
- */
-
-int
-CommTransp_EnqueueSegment(CommTransp transp,
- const void *buf,
- unsigned int bufLen)
-{
- int rc;
-
- if (!transp) {
- return -1;
- }
- rc = QP_EnqueueSegment(transp->qp, (void*)buf, bufLen);
- if (rc >= 0) {
- transp->writeSize += (unsigned int)rc;
- } else {
- transp->writeSize = 0;
- }
- return rc;
-}
-
-
-/**
- * @brief Commits any previous EnqueueSegment operations to the transport
- * object.
- * @param transp handle to the transport object.
- * @return 0 on success, < 0 otherwise.
- */
-
-int
-CommTransp_EnqueueCommit(CommTransp transp)
-{
- int rc;
-
- if (!transp) {
- return -1;
- }
-
- rc = QP_EnqueueCommit(transp->qp);
- if (rc >= 0) {
- const unsigned int fudge = 4;
- int writable = CommTransp_EnqueueSpace(transp);
-
- if ((writable >= 0) &&
- ((transp->writeSize + (unsigned int)writable + fudge) >=
- transp->qp->queueSize)) {
- /*
- * If bytes written since last commit + writable space 'almost'
- * equal write queue size, then signal. The 'almost' fudge factor
- * accounts for a possibly inaccurate CommTransp_EnqueueSpace()
- * return value. Most of the time, this is inconsequential. In
- * rare, borderline occasions, it results in a few extra signals.
- * The scheme essentially means this: if this is the first packet
- * to be write-committed, we signal. Otherwise, the remote end is
- * supposed to keep going for as long as it can read.
- *
- */
-
- BUG_ON(transp->backRef >= QP_MAX_QUEUE_PAIRS);
- CommOS_AddReturnAtomic(&transpTable[transp->backRef].holds, 1);
- if (CommOS_ReadAtomic(&transp->raiseInline)) {
- RaiseEvent(&transp->work);
- } else if (CommOS_ScheduleAIOWork(&transp->work)) {
- TranspTablePutNF(transp);
- }
- }
- } else {
- rc = -1;
- }
- transp->writeSize = 0;
- return rc;
-}
-
-
-/**
- * @brief Returns any available bytes for dequeue
- * @param transp handle to the transport object
- * @return available bytes for dequeue, <0 otherwise. see qp.h for error codes
- */
-
-int
-CommTransp_DequeueSpace(CommTransp transp)
-{
- if (!transp) {
- return -1;
- }
- return QP_DequeueSpace(transp->qp);
-}
-
-
-/**
- * @brief Discards any pending dequeues
- * @param transp handle to the transport object
- * @return 0 on success, <0 otherwise, see qp.h for error codes
- */
-
-int
-CommTransp_DequeueReset(CommTransp transp)
-{
- if (!transp) {
- return -1;
- }
- transp->readSize = 0;
- return QP_DequeueReset(transp->qp);
-}
-
-
-/**
- * @brief Dequeues a segment of data from the consumer queue into
- * a buffer
- * @param transp handle to the transport object
- * @param[out] buf buffer to copy to
- * @param bufLen number of bytes to dequeue
- * @return number of bytes dequeued on success, <0 otherwise,
- * see qp.h for error codes
- */
-
-int
-CommTransp_DequeueSegment(CommTransp transp,
- void *buf,
- unsigned bufLen)
-{
- int rc;
-
- if (!transp) {
- return -1;
- }
- rc = QP_DequeueSegment(transp->qp, buf, bufLen);
- if (rc >= 0) {
- transp->readSize += (unsigned int)rc;
- } else {
- transp->readSize = 0;
- }
- return rc;
-}
-
-
-/**
- * @brief Commits any previous DequeueSegment operations to the
- * transport object.
- * @param transp handle to the transport object.
- * @return 0 on success, < 0 otherwise.
- */
-
-int
-CommTransp_DequeueCommit(CommTransp transp)
-{
- int rc;
-
- if (!transp) {
- return -1;
- }
- rc = QP_DequeueCommit(transp->qp);
- if (rc >= 0) {
- int readable = CommTransp_DequeueSpace(transp);
- const unsigned int limit = transp->qp->queueSize / 2;
-
- if ((readable >= 0) &&
- (transp->readSize + (unsigned int)readable >= limit) &&
- ((unsigned int)readable < limit)) {
- /*
- * Minimize the number of likely 'peer write OK' signalling:
- * only do it, if reading crossed half-way down.
- *
- */
-
- BUG_ON(transp->backRef >= QP_MAX_QUEUE_PAIRS);
- CommOS_AddReturnAtomic(&transpTable[transp->backRef].holds, 1);
- if (CommOS_ReadAtomic(&transp->raiseInline)) {
- RaiseEvent(&transp->work);
- } else if (CommOS_ScheduleAIOWork(&transp->work)) {
- TranspTablePut(transp);
- }
- }
- } else {
- rc = -1;
- }
- /* coverity[deref_after_free] */
- transp->readSize = 0;
- return rc;
-}
-
-
-/**
- * @brief Notify any registered listeners for the given queue pair
- * @param notificationCenterID noop, unused on MVP
- * @param transpArgs initialization arguments used by the guest for this
- * channel
- * @sideeffects the host may attach to the queue pair
- */
-
-int
-CommTransp_Notify(const CommTranspID *notificationCenterID,
- CommTranspInitArgs *transpArgs)
-{
- QPInitArgs args;
-
- args.id.context = transpArgs->id.d32[0];
- args.id.resource = transpArgs->id.d32[1];
- args.capacity = transpArgs->capacity;
- args.type = transpArgs->type;
-
- CommOS_Debug(("%s: d32[0]: %u d32[1]: %u\n",
- __FUNCTION__,
- transpArgs->id.d32[0],
- transpArgs->id.d32[1]));
- QP_Notify(&args);
- return 0;
-}
diff --git a/arch/arm/mvp/commkm/fatalerror.h b/arch/arm/mvp/commkm/fatalerror.h
deleted file mode 100644
index 9676ff3..0000000
--- a/arch/arm/mvp/commkm/fatalerror.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief fatal error handlers. They all post fatal errors regardless of build
- * type.
- */
-
-#ifndef _FATALERROR_H
-#define _FATALERROR_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mvp_compiler.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum FECode {
- FECodeMisc, ///< generic FATAL() call of sorts
- FECodeOOM, ///< FATAL_OOM() call of sorts
- FECodeAssert, ///< ASSERT() call of sorts
- FECodeNR, ///< NOT_REACHED() call of sorts
- FECodeNI, ///< NOT_IMPLEMENTED() call of sorts
- FECodeNT, ///< NOT_TESTED() call of sorts
- FECodeCF ///< COMPILE_FAIL() call of sorts
-};
-typedef enum FECode FECode;
-
-#define FATAL() FatalError(__FILE__, __LINE__, FECodeMisc, 0, NULL)
-#define FATAL_IF(x) do { if (UNLIKELY(x)) FATAL(); } while (0)
-#define FATAL_OOM() FatalError(__FILE__, __LINE__, FECodeOOM, 0, NULL)
-#define FATAL_OOM_IF(x) do { if (UNLIKELY(x)) FATAL_OOM(); } while (0)
-
-extern _Bool FatalError_hit;
-
-void NORETURN FatalError(char const *file,
- int line,
- FECode feCode,
- int bugno,
- char const *fmt,
- ...) FORMAT(printf,5,6);
-
-#define FATALERROR_COMMON(printFunc, \
- printFuncV, \
- file, \
- line, \
- feCode, \
- bugno, \
- fmt) { \
- va_list ap; \
- \
- printFunc("FatalError: %s:%d, code %d, bugno %d\n", \
- file, line, feCode, bugno); \
- if (fmt != NULL) { \
- va_start(ap, fmt); \
- printFuncV(fmt, ap); \
- va_end(ap); \
- } \
- }
-
-#if defined IN_HOSTUSER || defined IN_GUESTUSER || defined IN_WORKSTATION
-
-#define FATALERROR_POSIX_USER \
-void \
-FatalError_VErrPrintf(const char *fmt, va_list ap) \
-{ \
- vfprintf(stderr, fmt, ap); \
-} \
-\
-void \
-FatalError_ErrPrintf(const char *fmt, ...) \
-{ \
- va_list ap; \
- va_start(ap, fmt); \
- FatalError_VErrPrintf(fmt, ap); \
- va_end(ap); \
-} \
-\
-void NORETURN \
-FatalError(char const *file, \
- int line, \
- FECode feCode, \
- int bugno, \
- const char *fmt, \
- ...) \
-{ \
- FATALERROR_COMMON(FatalError_ErrPrintf, FatalError_VErrPrintf, file, line, feCode, bugno, fmt); \
- exit(EXIT_FAILURE); \
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/arch/arm/mvp/commkm/include_check.h b/arch/arm/mvp/commkm/include_check.h
deleted file mode 100644
index 2eeafe7..0000000
--- a/arch/arm/mvp/commkm/include_check.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for Empty File Placeholder
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
diff --git a/arch/arm/mvp/commkm/mksck.h b/arch/arm/mvp/commkm/mksck.h
deleted file mode 100644
index e9e10bc..0000000
--- a/arch/arm/mvp/commkm/mksck.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#ifndef _MKSCK_H
-#define _MKSCK_H
-
-/**
- * @file
- *
- * @brief The monitor-kernel socket interface definitions.
- *
- * The monitor kernel socket interface was created for (what the name
- * says) communications between the monitor and host processes. On the
- * monitor side a special API is introduced, see mksck_vmm.h. On the
- * host side the API is the standard Berkeley socket interface. Host
- * process to host process or monitor to monitor communication is not
- * supported.
- *
- * A generic address consists of two 16 bit fields: the vm id and the
- * port id. Both hosts (vmx) and monitors (vmm) get their vm id
- * automatically. The host vm id is assigned at the time the host
- * process opens the mvpkm file descriptor, while the monitor vm id is
- * assigned when the vmx.c:SetupWorldSwitchPage() calls
- * Mvpkm_SetupIds(). As a vmx may create multiple monitors to service
- * an MP guest, a vmx vm id may be associated with multiple monitor vm
- * ids. A monitor id, however, has a single associated vmx host id,
- * the id of its canonical vmx.
- *
- * Sockets on the host get their addresses either by explicit user
- * call (the bind command) or implicitly by (issuing a send command
- * first). At an explicit bind the user may omit one or both fields by
- * providing MKSCK_VMID_UNDEF/MKSCK_PORT_UNDEF respectively. An
- * implicit bind behaves as if both fields were omitted in an explicit
- * bind. The default value of the vmid field is the vmid computed from
- * the thread group id while that of a port is a new number. It is not
- * invalid to bind a host process socket with a vm id different from
- * the vmid computed from the tgid.
- *
- * Sockets of the monitor are automatically assigned a vmid, that of their
- * monitor, at the time of their creation. The port id can be assigned by the
- * user or left to the implementation to assign an unused one (by specifying
- * MKSCK_PORT_UNDEF at @ref Mksck_Open).
- *
- * Host unconnected sockets may receive from any monitor sender, may send to any
- * monitor socket. A socket can be connected to a peer address, that enables the
- * use of the send command.
- *
- * One of many special predefined port (both host and monitor) is
- * MKSCK_PORT_MASTER. It is used for initialization.
- *
- * Monitor sockets have to send their peer address explicitly (by
- * Mksck_SetPeer()) or implicitly by receiving first. After the peer
- * is set, monitor sockets may send or receive only to/from their
- * peer.
- */
-
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "vmid.h"
-
-/*
- * The interface limits the size of transferable packets.
- */
-#define MKSCK_XFER_MAX 1024
-
-#define MKSCK_ADDR_UNDEF (uint32)0xffffffff
-
-#define MKSCK_PORT_UNDEF (uint16)0xffff
-#define MKSCK_PORT_MASTER (MKSCK_PORT_UNDEF-1)
-#define MKSCK_PORT_HOST_FB (MKSCK_PORT_UNDEF-2)
-#define MKSCK_PORT_BALLOON (MKSCK_PORT_UNDEF-3)
-#define MKSCK_PORT_HOST_HID (MKSCK_PORT_UNDEF-4)
-#define MKSCK_PORT_CHECKPOINT (MKSCK_PORT_UNDEF-5)
-#define MKSCK_PORT_COMM_EV (MKSCK_PORT_UNDEF-6)
-#define MKSCK_PORT_HIGH (MKSCK_PORT_UNDEF-7)
-
-#define MKSCK_VMID_UNDEF VMID_UNDEF
-#define MKSCK_VMID_HIGH (MKSCK_VMID_UNDEF-1)
-
-#define MKSCK_DETACH 3
-
-typedef uint16 Mksck_Port;
-typedef VmId Mksck_VmId;
-
-/**
- * @brief Page descriptor for typed messages. Each page describes a region of
- * the machine address space with base mpn and size 2^(12 + order) bytes.
- */
-typedef struct {
- uint32 mpn : 20; ///< Base MPN of region described by page
- uint32 order : 12; ///< Region is 2^(12 + order) bytes.
-} Mksck_PageDesc;
-
-/**
- * @brief Typed message template macro. Allows us to avoid having two message
- * types, one with page descriptor vector (for VMM), one without (for
- * VMX).
- *
- * @param type C type of uninterpreted component of the message (following the
- * page descriptor vector).
- * @param pages number of page descriptors in vector.
- */
-#define MKSCK_DESC_TYPE(type,pages) \
- struct { \
- type umsg; \
- Mksck_PageDesc page[pages]; \
- }
-
-/**
- * @brief The monitor kernel socket interface address format
- */
-typedef union {
- uint32 addr; ///< the address
- struct { /* The address is decomposed to two shorts */
- Mksck_Port port; ///< port unique within a vmid
- Mksck_VmId vmId; ///< unique vmid
- };
-} Mksck_Address;
-
-static inline uint32
-Mksck_AddrInit(Mksck_VmId vmId, Mksck_Port port)
-{
- Mksck_Address aa;
- aa.vmId = vmId;
- aa.port = port;
- return aa.addr;
-}
-#endif
diff --git a/arch/arm/mvp/commkm/mksck_sockaddr.h b/arch/arm/mvp/commkm/mksck_sockaddr.h
deleted file mode 100644
index 82df240..0000000
--- a/arch/arm/mvp/commkm/mksck_sockaddr.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Host user space definitions for mksck sockets.
- */
-
-#ifndef _MKSCK_SOCKADDR_H_
-#define _MKSCK_SOCKADDR_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mksck.h"
-
-/* no one ever uses DECnet anymore? */
-#define AF_MKSCK AF_DECnet
-#define PF_MKSCK PF_DECnet
-
-/* Address structure used by the host user socket interface. */
-struct sockaddr_mk {
- sa_family_t mk_family;
- Mksck_Address mk_addr;
-};
-
-#endif
diff --git a/arch/arm/mvp/commkm/mvp.h b/arch/arm/mvp/commkm/mvp.h
deleted file mode 100644
index a57f8cc..0000000
--- a/arch/arm/mvp/commkm/mvp.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief top-level include for all basic includes.
- * This file should not define anything of its own.
- */
-
-#ifndef _MVP_H
-#define _MVP_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mvp_compiler.h"
-#include "utils.h"
-#include "mvp_assert.h"
-#include "mvp_types.h"
-#include "platdefx.h"
-
-#endif
diff --git a/arch/arm/mvp/commkm/mvp_assert.h b/arch/arm/mvp/commkm/mvp_assert.h
deleted file mode 100644
index cbc5ed8..0000000
--- a/arch/arm/mvp/commkm/mvp_assert.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief ASSERT() and related macros.
- */
-
-#ifndef _MVP_ASSERT_H
-#define _MVP_ASSERT_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define ASSERT(_x) ASSERT_BUG((_x),0)
-
-#ifndef NDEBUG
-#define ASSERT_BUG(_x,_tkt) do { \
- if (UNLIKELY(!(_x))) { \
- FatalError(__FILE__, __LINE__, FECodeAssert, _tkt, NULL); \
- } \
-} while (0)
-
-#define ASSERTF(_x, ...) do { \
- if (UNLIKELY(!(_x))) { \
- FatalError(__FILE__, \
- __LINE__, \
- FECodeAssert, \
- 0, \
- __VA_ARGS__); \
- } \
-} while (0)
-#else
-
-#define ASSERT_BUG(_x,_tkt) (void)sizeof((int)(_x))
-#define ASSERTF(_x, ...) ASSERT_BUG(_x, 0)
-
-#endif
-
-/*
- * Compile-time assertions.
- *
- * ASSERT_ON_COMPILE does not use the common
- * switch (0) { case 0: case (e): ; } trick because some compilers (e.g. MSVC)
- * generate code for it.
- *
- * The implementation uses both enum and typedef because the typedef alone is
- * insufficient; gcc allows arrays to be declared with non-constant expressions
- * (even in typedefs, where it makes no sense).
- */
-#ifdef __COVERITY__
-#define ASSERT_ON_COMPILE(e) ASSERT(e)
-#else
-#define ASSERT_ON_COMPILE(e) \
- do { \
- enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
- typedef char AssertOnCompileFailed[AssertOnCompileMisused]; \
- } while (0)
-#endif
-
-/*
- * To put an ASSERT_ON_COMPILE() outside a function, wrap it
- * in MY_ASSERTS(). The first parameter must be unique in
- * each .c file where it appears. For example,
- *
- * MY_ASSERTS(FS3_INT,
- * ASSERT_ON_COMPILE(sizeof(FS3_DiskLock) == 128);
- * ASSERT_ON_COMPILE(sizeof(FS3_DiskLockReserved) == DISK_BLOCK_SIZE);
- * ASSERT_ON_COMPILE(sizeof(FS3_DiskBlock) == DISK_BLOCK_SIZE);
- * ASSERT_ON_COMPILE(sizeof(Hardware_DMIUUID) == 16);
- * )
- *
- * Caution: ASSERT() within MY_ASSERTS() is silently ignored.
- * The same goes for anything else not evaluated at compile time.
- */
-
-#define MY_ASSERTS(name, assertions) \
- static inline void name(void) { \
- assertions \
- }
-
-#define KNOWN_BUG(_tkt)
-
-#define NOT_IMPLEMENTED() NOT_IMPLEMENTED_JIRA(0)
-#define NOT_IMPLEMENTED_JIRA(_tkt,...) FatalError(__FILE__, __LINE__, FECodeNI, _tkt, NULL)
-
-#define NOT_IMPLEMENTED_IF(_x) NOT_IMPLEMENTED_IF_JIRA((_x),0)
-#define NOT_IMPLEMENTED_IF_JIRA(_x,_tkt,...) do { if (UNLIKELY(_x)) NOT_IMPLEMENTED_JIRA(_tkt); } while (0)
-/*
- * All sites tagged with this are @knownjira{MVP-1855}.
- */
-#define NOT_IMPLEMENTEDF(...) FatalError(__FILE__, __LINE__, FECodeNI, 0, __VA_ARGS__)
-
-#define NOT_REACHED() FatalError(__FILE__, __LINE__, FECodeNR, 0, NULL)
-
-#include "fatalerror.h"
-#include "nottested.h"
-
-#endif
diff --git a/arch/arm/mvp/commkm/mvp_compiler.h b/arch/arm/mvp/commkm/mvp_compiler.h
deleted file mode 100644
index 21af455..0000000
--- a/arch/arm/mvp/commkm/mvp_compiler.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Compiler-related definitions and directives.
- */
-
-#ifndef _MVP_COMPILER_H_
-#define _MVP_COMPILER_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#ifdef __GNUC__
-#include "mvp_compiler_gcc.h"
-#else /* __GNUC__ */
-#include "mvp_compiler_other.h"
-#endif /* __GNUC__ */
-
-/**
- * @brief Find last set bit.
- *
- * @param n unsigned 32-bit integer.
- *
- * @return 0 if n == 0 otherwise 32 - the number of leading zeroes in n.
- */
-#define FLS(n) (32 - CLZ(n))
-
-#endif /// ifndef _MVP_COMPILER_H_
diff --git a/arch/arm/mvp/commkm/mvp_compiler_gcc.h b/arch/arm/mvp/commkm/mvp_compiler_gcc.h
deleted file mode 100644
index fbc96e3..0000000
--- a/arch/arm/mvp/commkm/mvp_compiler_gcc.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief common definitions for GCC
- */
-
-#ifndef _MVP_COMPILER_GCC_H
-#define _MVP_COMPILER_GCC_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @brief Count leading zeroes.
- *
- * @param n unsigned 32-bit integer.
- *
- * @return 32 if n == 0 otherwise 31 - the bit position of the most significant 1
- * in n.
- */
-#ifdef __COVERITY__
-static inline int
-CLZ(unsigned int n)
-{
- unsigned int r = 0;
-
- while (n) {
- r++;
- n >>= 1;
- }
-
- return 32 - r;
-}
-#else
-#define CLZ(n) __builtin_clz(n)
-#endif
-
-#define PACKED __attribute__ ((packed))
-#define ALLOC __attribute__ ((malloc, warn_unused_result))
-#define UNUSED __attribute__ ((unused))
-#define PURE __attribute__ ((pure))
-#define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
-#define FORMAT(x,y,z) __attribute__ ((format(x,y,z)))
-#define LIKELY(x) __builtin_expect(!!(x), 1)
-#define UNLIKELY(x) __builtin_expect((x), 0)
-
-/*
- * For debug builds, we want to omit __attribute__((noreturn)) so that gcc will
- * keep stack linkages and then we will have useful core dumps. For non-debug
- * builds, we don't care about the stack frames and want the little bit of
- * optimization that noreturn gives us.
- */
-#if defined(__COVERITY__) || !defined(MVP_DEBUG)
-#define NORETURN __attribute__((noreturn))
-#else
-#define NORETURN
-#endif
-
-#endif
diff --git a/arch/arm/mvp/commkm/mvp_types.h b/arch/arm/mvp/commkm/mvp_types.h
deleted file mode 100644
index ba5c04c..0000000
--- a/arch/arm/mvp/commkm/mvp_types.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief basic type definitions.
- * These may need to be conditionalized for different compilers/platforms.
- */
-
-#ifndef _MVPTYPES_H
-#define _MVPTYPES_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint32;
-typedef unsigned long long uint64;
-
-typedef signed char int8;
-typedef short int16;
-typedef int int32;
-typedef long long int64;
-
-typedef uint32 CVA; // whatever we are compiling the code as
-typedef uint32 GVA; // guest virtual addresses
-typedef uint32 MVA; // monitor virtual addresses
-typedef uint32 HKVA; // host kernel virtual addresses
-typedef uint32 HUVA; // host user virtual addresses
-typedef uint64 PA; // (guest) physical addresses (40-bit)
-typedef uint32 MA; // (host) machine addresses
-
-typedef uint32 PPN; // PA/PAGE_SIZE
-typedef uint32 MPN; // MA/PAGE_SIZE
-
-typedef uint64 cycle_t;
-
-/**
- * @brief Page segment.
- *
- * Specifies a segment within a single page.
- */
-typedef struct {
- uint16 off;
- uint16 len;
-} PageSeg;
-
-/*
- * GCC's argument checking for printf-like functions
- *
- * fmtPos is the position of the format string argument, beginning at 1
- * varPos is the position of the variable argument, beginning at 1
- */
-
-#if defined(__GNUC__)
-# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos)))
-#else
-# define PRINTF_DECL(fmtPos, varPos)
-#endif
-
-#if defined(__GNUC__)
-# define SCANF_DECL(fmtPos, varPos) __attribute__((__format__(__scanf__, fmtPos, varPos)))
-#else
-# define SCANF_DECL(fmtPos, varPos)
-#endif
-
-#endif /* _MVPTYPES_H */
diff --git a/arch/arm/mvp/commkm/mvpkm_comm_ev.h b/arch/arm/mvp/commkm/mvpkm_comm_ev.h
deleted file mode 100644
index b220a9b..0000000
--- a/arch/arm/mvp/commkm/mvpkm_comm_ev.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief mvpkm kernel hooks for comm event signaling
- */
-
-#ifndef _MVPKM_COMM_EV_H
-#define _MVPKM_COMM_EV_H
-
-extern int (*CommTranspEvProcess)(CommTranspID* id, CommTranspIOEvent event);
-
-/**
- * @brief Forward any guest signal requests to the commkm module
- * @param id transport channel id
- * @param event comm event type
- */
-
-static inline void
-Mvpkm_CommEvSignal(CommTranspID *id, CommTranspIOEvent event)
-{
- if (CommTranspEvProcess) {
- CommTranspEvProcess(id, event);
- }
-}
-
-void
-Mvpkm_CommEvRegisterProcessCB(int (*commProcessFunc)(CommTranspID*,
- CommTranspIOEvent));
-void Mvpkm_CommEvUnregisterProcessCB(void);
-
-
-
-#endif
diff --git a/arch/arm/mvp/commkm/nottested.h b/arch/arm/mvp/commkm/nottested.h
deleted file mode 100644
index c5c1e26..0000000
--- a/arch/arm/mvp/commkm/nottested.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief NOT_TESTED() and related.
- */
-
-#ifndef _NOTTESTED_H
-#define _NOTTESTED_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include <stdbool.h>
-
-#ifdef NOT_TESTED_ENABLED
-#define NotTestedEnabled true
-#else
-#define NotTestedEnabled false
-#endif
-
-#define NOT_TESTED() NOT_TESTED_JIRA(0)
-#define NOT_TESTED_JIRA(_tkt,...) NotTested(_tkt, __FILE__, __LINE__)
-
-void NotTested(int tkt, char const *file, int line);
-
-#endif
diff --git a/arch/arm/mvp/commkm/platdefx.h b/arch/arm/mvp/commkm/platdefx.h
deleted file mode 100644
index 42953e6..0000000
--- a/arch/arm/mvp/commkm/platdefx.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Basic platform definitions needed various places.
- */
-
-#ifndef _PLATDEFX_H
-#define _PLATDEFX_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define PAGE_ORDER 12
-
-#ifndef PAGE_SIZE
-#define PAGE_SIZE (1UL << PAGE_ORDER)
-#endif
-#if PAGE_SIZE != 4096
-#error bad page size PAGE_SIZE
-#endif
-
-#define PA_2_PPN(_pa) ((_pa) / PAGE_SIZE)
-#define PPN_2_PA(_ppn) ((_ppn) * PAGE_SIZE)
-
-#define VMM_DOMAIN 0x0
-#define VMM_DOMAIN_NO_ACCESS 0x3
-#define VMM_DOMAIN_CLIENT 0x1
-#define VMM_DOMAIN_MANAGER 0x4
-
-#define INVALID_CVA (-(CVA)1)
-#define INVALID_GVA (-(GVA)1)
-#define INVALID_MVA (-(MVA)1)
-#define INVALID_HKVA (-(HKVA)1)
-#define INVALID_HUVA (-(HUVA)1)
-
-#define INVALID_MPN (((MPN)-1) >> ARM_L2D_SMALL_ORDER)
-#define INVALID_PPN (((PPN)-1) >> ARM_L2D_SMALL_ORDER)
-
-#endif
diff --git a/arch/arm/mvp/commkm/qp.h b/arch/arm/mvp/commkm/qp.h
deleted file mode 100644
index d4a50ec..0000000
--- a/arch/arm/mvp/commkm/qp.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP Queue Pairs function and structure declarations
- *
- * MVP Queue Pairs:
- *
- * Queue pairs are intended to be a generic bulk data transport mechanism
- * between the guest and host kernels. The queue pair abstraction is based
- * on two ring buffers (queues) placed on a shared memory region mapped
- * into both guest and host kernel address spaces.
- *
- * NOTE: Queue pairs are SINGLE-READER, SINGLE-WRITER. Any caller is
- * responsible for multi-reader/writer serialization!!!
- *
- * There are a maximum of QP_MAX_QUEUE_PAIRS in the system, with a maximum
- * size of QP_MAX_CAPACITY per pair. Each queue pair is identified by
- * an ID.
- *
- * Each peer follows a producer-consumer model in which one side is the
- * producer on one queue, and the other side is the consumer on that queue
- * (and vice-versa for its pair).
- *
- * Data is enqueued and dequeued into the pair in transactional stages,
- * meaning each enqueue/dequeue can be followed by zero or more
- * enqueue/dequeues, but the enqueue/dequeue is not visible to the peer
- * until it has been committed with the *Commit() function.
- * In PVTCP, for example, this is used to enqueue a short header, then
- * followed by 'segments' of iovecs, then followed by a commit. This
- * model prevents a peer from reading the header, expecting a payload,
- * but not being able to read the payload because it hasn't been
- * enqueued yet.
- *
- * Queue Pair setup:
- *
- * Before data can be passed, the guest and host kernel must perform
- * the following connection handshake:
- *
- * 1). A host kernel service registers a listener with the queue pair
- * subsystem with a callback to be called when guests create
- * and attach to a shared memory region.
- *
- * 2). Guest initiates an QP_Attach() operation to a shared memory region
- * keyed by ID. This step allocates memory, maps it into the host
- * address space, and optionally notifies any host services who are
- * listening for attach requests from the guest (see previous step).
- * Host listeners are provided with a copy of the initialization
- * arguments used by the guest (id, size, service type). All registered
- * listeners are iterated over until one of them handles the attach
- * request and acknowledges with QP_SUCCESS.
- *
- * 3). The registered host callback is called, notifying the host that
- * the guest has attached.
- *
- * 4). The host can now QP_Attach() to the shared memory region with the same
- * arguments as the guest. The queue pair is now well formed and enqueues
- * and dequeues can proceed on either side.
- *
- * Queue Pair teardown:
- *
- * 1). As before, teardowns are initiated by the guest. Hosts can register
- * a callback to be called upon detach. Guests initiate a teardown
- * through a call to QP_Detach().
- *
- * 2). Registered hosts are notified through the aforementioned callback.
- * 3). The host service can call QP_Detach() at its own leisure. Memory
- * is freed, the queue pair is destroyed.
- *
- * If at any point the guest unexpectedly shuts down, the host will be
- * notified at monitor shutdown time. Memory is freed, and the queue
- * pair is destroyed.
- *
- */
-
-#ifndef _QP_H
-#define _QP_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-//#define QP_DEBUG 1
-
-typedef enum QPState {
- QP_STATE_FREE = 0x1, ///< No peers, not memory-backed
- QP_STATE_CONNECTED, ///< Both peers attached , memory backed
- QP_STATE_GUEST_ATTACHED, ///< Guest allocated memory, host not yet attached
- QP_STATE_MAX // leave this at the end!
-} QPState;
-
-typedef struct QPId {
- uint32 context;
- uint32 resource;
-} QPId;
-
-/*
- * Initialization arguments for each queue pair
- */
-typedef struct QPInitArgs {
- QPId id; ///< Shared memory region ID
- uint32 capacity; ///< Total size of shared region in bytes
- uint32 type; ///< Type of queue pair (PVTCP, other)...
-} QPInitArgs;
-
-/*
- * Placed on the shared region, two per region
- */
-typedef struct QHandle {
- volatile uint32 head; ///< queue head offset
- volatile uint32 tail; ///< queue tail offset
- volatile uint32 phantom_head; ///< queue shadow head offset
- volatile uint32 phantom_tail; ///< queue shadow tail offset
- uint8 data[0]; ///< start of data, runs off
- // the struct
-} QHandle;
-
-/*
- * Local to each peer
- */
-typedef struct QPHandle {
- QPId id; ///< shared memory region ID
- uint32 capacity; ///< size of region in bytes
- QHandle *produceQ; ///< producer queue
- QHandle *consumeQ; ///< consumer queue
- uint32 queueSize; ///< size of each queue in bytes
- uint32 type; ///< type of queue pair
-
- /*
- * Following fields unused by guest
- */
- QPState state;
- void (*peerDetachCB)(void* data); ///< detach notification callback
- void *detachData; ///< data for the detach cb
- struct page **pages; ///< page pointers for shared region
-} QPHandle;
-
-/*
- * QP Error codes
- */
-#define QP_SUCCESS 0
-#define QP_ERROR_NO_MEM (-1)
-#define QP_ERROR_INVALID_HANDLE (-2)
-#define QP_ERROR_INVALID_ARGS (-3)
-#define QP_ERROR_ALREADY_ATTACHED (-4)
-
-/*
- * Hard-coded limits
- */
-#define QP_MIN_CAPACITY (PAGE_SIZE * 2)
-#define QP_MAX_CAPACITY (1024*1024) // 1M
-#define QP_MAX_QUEUE_PAIRS 32
-#define QP_MAX_ID QP_MAX_QUEUE_PAIRS
-#define QP_MAX_LISTENERS QP_MAX_QUEUE_PAIRS
-#define QP_MAX_PAGES (QP_MAX_CAPACITY/PAGE_SIZE) // 256 pages
-
-#define QP_INVALID_ID 0xFFFFFFFF
-#define QP_INVALID_SIZE 0xFFFFFFFF
-#define QP_INVALID_REGION 0xFFFFFFFF
-#define QP_INVALID_TYPE 0xFFFFFFFF
-
-#ifdef __KERNEL__
-/**
- * @brief Utility function to sanity check arguments
- * @param args argument structure to check
- * @return true if arguments are sane, false otherwise
- */
-static inline
-_Bool QP_CheckArgs(QPInitArgs *args)
-{
- if (!args ||
- !is_power_of_2(args->capacity) ||
- (args->capacity < QP_MIN_CAPACITY) ||
- (args->capacity > QP_MAX_CAPACITY) ||
- !(args->id.resource < QP_MAX_ID || args->id.resource == QP_INVALID_ID) ||
- (args->type == QP_INVALID_TYPE)) {
- return false;
- } else {
- return true;
- }
-}
-#endif
-
-
-/**
- * @brief Utility function to sanity check a queue pair handle
- * @param qp handle to the queue pair
- * @return true if the handle is sane, false otherwise
- */
-static inline
-_Bool QP_CheckHandle(QPHandle *qp)
-{
-#ifdef MVP_DEBUG
- if (!(qp) ||
- !(qp->produceQ) ||
- !(qp->consumeQ) ||
- (qp->state >= (uint32)QP_STATE_MAX) ||
- !(qp->queueSize < (QP_MAX_CAPACITY/2))) {
- return false;
- } else {
- return true;
- }
-#else
- return true;
-#endif
-}
-
-
-/**
- * @brief Initializes an invalid handle
- * @param[in, out] qp handle to the queue pair
- */
-static inline void
-QP_MakeInvalidQPHandle(QPHandle *qp)
-{
- if (!qp) {
- return;
- }
-
- qp->id.context = QP_INVALID_ID;
- qp->id.resource = QP_INVALID_ID;
- qp->capacity = QP_INVALID_SIZE;
- qp->produceQ = NULL;
- qp->consumeQ = NULL;
- qp->queueSize = QP_INVALID_SIZE;
- qp->type = QP_INVALID_TYPE;
- qp->state = QP_STATE_FREE;
- qp->peerDetachCB = NULL;
- qp->detachData = NULL;
-}
-
-/*
- * Host only
- */
-typedef int32 (*QPListener)(const QPInitArgs*);
-int32 QP_RegisterListener(const QPListener);
-int32 QP_UnregisterListener(const QPListener);
-int32 QP_RegisterDetachCB(QPHandle *qp, void (*callback)(void*), void *data);
-
-
-/*
- * Host and guest specific implementations, see qp_host.c and qp_guest.c
- */
-int32 QP_Attach(QPInitArgs *args, QPHandle** qp);
-int32 QP_Detach(QPHandle* qp);
-int32 QP_Notify(QPInitArgs *args);
-
-/*
- * Common implementation, see qp_common.c
- */
-int32 QP_EnqueueSpace(QPHandle *qp);
-int32 QP_EnqueueSegment(QPHandle *qp, const void *buf, size_t length);
-int32 QP_EnqueueCommit(QPHandle *qp);
-int32 QP_EnqueueReset(QPHandle *qp);
-
-static inline int32
-QP_EnqueueAtomic(QPHandle *qp, const void *buf, size_t length)
-{
- int32 rc;
- QP_EnqueueReset(qp);
- rc = QP_EnqueueSegment(qp, buf, length);
- if (rc < 0) {
- return rc;
- } else {
- QP_EnqueueCommit(qp);
- }
- return rc;
-}
-
-int32 QP_DequeueSpace(QPHandle *qp);
-int32 QP_DequeueSegment(QPHandle *qp, const void *buf, size_t length);
-int32 QP_DequeueReset(QPHandle *qp);
-int32 QP_DequeueCommit(QPHandle *qp);
-
-static inline int32
-QP_DequeueAtomic(QPHandle *qp, const void *buf, size_t length)
-{
- int32 rc;
- QP_DequeueReset(qp);
- rc = QP_DequeueSegment(qp, buf, length);
- if (rc < 0) {
- return rc;
- } else {
- QP_DequeueCommit(qp);
- }
- return rc;
-}
-
-/*
- * HVC methods and signatures
- */
-#define MVP_QP_SIGNATURE 0x53525051 ///< 'QPRS'
-#define MVP_QP_ATTACH (MVP_OBJECT_CUSTOM_BASE + 0) ///< attach to a queue pair
-#define MVP_QP_DETACH (MVP_OBJECT_CUSTOM_BASE + 1) ///< detach from a queue pair
-#define MVP_QP_NOTIFY (MVP_OBJECT_CUSTOM_BASE + 2) ///< notify host of attach
-#define MVP_QP_LAST (MVP_OBJECT_CUSTOM_BASE + 3) ///< Number of methods
-
-/*
- * Debug macros
- */
-#ifdef QP_DEBUG
- #ifdef IN_MONITOR
- #define QP_DBG(...) Log(__VA_ARGS__)
- #else
- #define QP_DBG(...) printk(KERN_INFO __VA_ARGS__)
- #endif
-#else
- #define QP_DBG(...)
-#endif
-
-#endif
diff --git a/arch/arm/mvp/commkm/utils.h b/arch/arm/mvp/commkm/utils.h
deleted file mode 100644
index b5f1e18..0000000
--- a/arch/arm/mvp/commkm/utils.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief General architecture-independent definitions, typedefs, and macros.
- */
-
-#ifndef _UTILS_H
-#define _UTILS_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define MAX_FILENAME 128
-
-// Round address up to given size boundary
-// Note: ALIGN() conflicts with Linux
-
-#define MVP_ALIGN(_v, _n) (((_v) + (_n) - 1) & -(_n))
-
-#define ALIGNVA(_addr, _size) MVP_ALIGN(_addr, _size)
-
-#define alignof(t) offsetof(struct { char c; typeof(t) x; }, x)
-
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#define KB(_X_) ((_X_)*1024U)
-#define MB(_X_) (KB(_X_)*1024)
-#define GB(_X_) (MB(_X_)*1024)
-
-#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
-
-/*
- * x in [low,high)
- * args evaluated once
- */
-#define RANGE(x,low,high) \
- ({ \
- typeof(x) _x = (x); \
- typeof(x) _low = (typeof(x))(low); \
- typeof(x) _high =(typeof(x))(high); \
- (_Bool)( (_low <= _x) && (_x < _high)); \
- })
-
-#define OBJECTS_PER_PAGE(_type) (PAGE_SIZE / sizeof(_type))
-
-#define MA_2_MPN(_ma) ((MPN)((_ma) / PAGE_SIZE))
-#define MPN_2_MA(_mpn) ((MA)((_mpn) * PAGE_SIZE))
-
-#define VA_2_VPN(_va) ((_va) / PAGE_SIZE)
-#define VPN_2_vA(_vpn) ((_vpn) * PAGE_SIZE)
-
-/*
- * The following convenience macro can be used in a following situation
- *
- * send(..., &foo, sizeof(foo)) --> send(..., PTR_N_SIZE(foo))
- */
-
-#define PTR_N_SIZE(_var) &(_var), sizeof(_var)
-
-
-/*
- *
- * BIT-PULLING macros
- *
- */
-#define MVP_BIT(val,n) ( ((val)>>(n))&1)
-#define MVP_BITS(val,m,n) (((val)<<(31-(n))) >> ((31-(n))+(m)) )
-#define MVP_EXTRACT_FIELD(w, m, n) MVP_BITS((w), (m), ((m) + (n) - 1))
-#define MVP_MASK(m, n) (MVP_EXTRACT_FIELD(~(uint32)0U, (m), (n)) << (m))
-#define MVP_UPDATE_FIELD(old_val, field_val, m, n) \
- (((old_val) & ~MVP_MASK((m), (n))) | (MVP_EXTRACT_FIELD((field_val), 0, (n)) << (m)))
-
-/*
- *
- * 64BIT-PULLING macros
- *
- */
-#define MVP_BITS64(val,m,n) (((val)<<(63-(n))) >> ((63-(n))+(m)) )
-#define MVP_EXTRACT_FIELD64(w, m, n) MVP_BITS64((w), (m), ((m) + (n) - 1))
-#define MVP_MASK64(m, n) (MVP_EXTRACT_FIELD64(~(uint64)0ULL, (m), (n)) << (m))
-#define MVP_UPDATE_FIELD64(old_val, field_val, m, n) \
- (((old_val) & ~MVP_MASK64((m), (n))) | (MVP_EXTRACT_FIELD64(((uint64)(field_val)), 0ULL, (n)) << (m)))
-
-/*
- *
- * BIT-CHANGING macros
- *
- */
-#define MVP_SETBIT(val,n) ((val)|=(1<<(n)))
-#define MVP_CLRBIT(val,n) ((val)&=(~(1<<(n))))
-
-/*
- * Fixed bit-width sign extension.
- */
-#define MVP_SIGN_EXTEND(val,width) \
- (((val) ^ (1 << ((width) - 1))) - (1 << ((width) - 1)))
-
-
-/*
- * Assembler helpers.
- */
-#define _MVP_HASH #
-#define MVP_HASH() _MVP_HASH
-
-#define _MVP_STRINGIFY(...) #__VA_ARGS__
-#define MVP_STRINGIFY(...) _MVP_STRINGIFY(__VA_ARGS__)
-
-#ifndef __ASSEMBLER__
-
-#include <stddef.h>
-#include <stdbool.h>
-
-/*
- * Constant equivalents of build-flags.
- *
- * Test these when possible instead of using #ifdef so that your code
- * gets parsed.
- */
-#ifdef MVP_DEBUG
-static const _Bool mvpDebug = true;
-#else
-static const _Bool mvpDebug = false;
-#endif
-
-#ifdef MVP_STATS
-static const _Bool mvpStats = true;
-#else
-static const _Bool mvpStats = false;
-#endif
-
-#ifdef MVP_DEVEL
-static const _Bool mvpDevel = true;
-#else
-static const _Bool mvpDevel = false;
-#endif
-
-#endif
-
-#endif
diff --git a/arch/arm/mvp/commkm/vmid.h b/arch/arm/mvp/commkm/vmid.h
deleted file mode 100644
index f24a650..0000000
--- a/arch/arm/mvp/commkm/vmid.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#ifndef _VMID_H
-#define _VMID_H
-
-/**
- * @file
- *
- * @brief The vmid definition
- */
-
-
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define VMID_UNDEF (uint16)0xffff
-typedef uint16 VmId;
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/COPYING b/arch/arm/mvp/mvpkm/COPYING
deleted file mode 100644
index 10828e0..0000000
--- a/arch/arm/mvp/mvpkm/COPYING
+++ /dev/null
@@ -1,341 +0,0 @@
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/arch/arm/mvp/mvpkm/Kbuild b/arch/arm/mvp/mvpkm/Kbuild
deleted file mode 100644
index 7b2dc10..0000000
--- a/arch/arm/mvp/mvpkm/Kbuild
+++ /dev/null
@@ -1,32 +0,0 @@
-# Warning: autogenerated
-obj-m := mvpkm.o
-mvpkm-objs := check_kconfig.o cpufreq_kernel.o mksck_kernel.o montimer_kernel.o mutex_kernel.o mvpkm_comm_ev.o mvpkm_main.o qp_host_kernel.o qp_common.o mksck_shared.o vfp_switch.o
-
-ccflags-y += -fno-pic -fno-dwarf2-cfi-asm -march=armv7-a -D__linux__
-ccflags-y += -mfpu=neon -DLIB_ARM_VERSION=7 -DIN_MODULE -DGPLED_CODE
-ccflags-y += --std=gnu89 -O2 -g2 -ggdb -mapcs -fno-optimize-sibling-calls -mno-sched-prolog
-ccflags-$(CONFIG_VMWARE_MVP_DEBUG) += -DMVP_DEBUG
-
-asflags-y += -mfpu=neon -DLIB_ARM_VERSION=7 -DIN_MODULE -DGPLED_CODE
-asflags-y += -mfloat-abi=softfp
-
-# Detect MD5SUM executable
-HOST_OS := $(shell uname -s)
-ifeq ($(HOST_OS),Darwin)
- MD5SUM_EXEC := md5
-else
- MD5SUM_EXEC := md5sum
-endif
-
-LOWMEMKILLER_PATH := $(srctree)/drivers/staging/android/lowmemorykiller.c
-ifeq ($(wildcard $(LOWMEMKILLER_PATH)),)
-$(error "Unable to find lowmemorykiller.c at $(LOWMEMKILLER_PATH)")
-endif
-LOWMEMKILLER_MD5 := $(shell $(MD5SUM_EXEC) $(LOWMEMKILLER_PATH) | cut -f1 -d\ )
-LOWMEMKILLER_SUPPORT := $(srctree)/arch/arm/mvp/mvpkm/lowmemkiller_variant.sh
-LOWMEMKILLER_SHRINK_MD5 := $(shell $(SHELL) $(LOWMEMKILLER_SUPPORT) $(LOWMEMKILLER_PATH) | cut -f1 -d\ )
-LOWMEMKILLER_VARIANT := $(shell $(SHELL) $(LOWMEMKILLER_SUPPORT) $(LOWMEMKILLER_PATH) | cut -f2 -d\ )
-ccflags-y += \
- -DLOWMEMKILLER_VARIANT=$(LOWMEMKILLER_VARIANT) \
- -DLOWMEMKILLER_SHRINK_MD5=$(LOWMEMKILLER_SHRINK_MD5) \
- -DLOWMEMKILLER_MD5=$(LOWMEMKILLER_MD5)
diff --git a/arch/arm/mvp/mvpkm/Makefile b/arch/arm/mvp/mvpkm/Makefile
deleted file mode 100644
index 16eb389..0000000
--- a/arch/arm/mvp/mvpkm/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-# Warning: autogenerated
diff --git a/arch/arm/mvp/mvpkm/actions.h b/arch/arm/mvp/mvpkm/actions.h
deleted file mode 100644
index 0e89892..0000000
--- a/arch/arm/mvp/mvpkm/actions.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Bit definitions for instrBActions.
- */
-
-#ifndef _ACTIONS_H
-#define _ACTIONS_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define L2_ACTION_GDB 0 ///< drop into guest debugger GDB
-#define L2_ACTION_MKSCK 1 ///< scan the mksck pipes for incoming messages
-#define L2_ACTION_ABORT 2 ///< abort the monitor cleanly
-#define L2_ACTION_HALT 3 ///< halt the monitor
-#define L2_ACTION_FIQ 6 ///< the VCPU's FIQ pin is active
-#define L2_ACTION_IRQ 7 ///< the VCPU's IRQ pin is active
-#define L2_ACTION_CKPT 8 ///< do a checkpoint
-#define L2_ACTION_WFI 9 ///< wait for interrupt
-#define L2_ACTION_TIMER 10 ///< timer event
-#define L2_ACTION_BALLOON 11 ///< balloon trigger
-
-#define ACTION_GDB (1 << L2_ACTION_GDB)
-#define ACTION_MKSCK (1 << L2_ACTION_MKSCK)
-#define ACTION_ABORT (1 << L2_ACTION_ABORT)
-#define ACTION_HALT (1 << L2_ACTION_HALT)
-#define ACTION_IRQ (1 << L2_ACTION_IRQ)
-#define ACTION_FIQ (1 << L2_ACTION_FIQ)
-#define ACTION_CKPT (1 << L2_ACTION_CKPT)
-#define ACTION_WFI (1 << L2_ACTION_WFI)
-#define ACTION_TIMER (1 << L2_ACTION_TIMER)
-#define ACTION_BALLOON (1 << L2_ACTION_BALLOON)
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/arm_as_macros.h b/arch/arm/mvp/mvpkm/arm_as_macros.h
deleted file mode 100644
index 5a0b7fc..0000000
--- a/arch/arm/mvp/mvpkm/arm_as_macros.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Macro definitions meta-ops to be used in assembler files
- *
- * This header contains asm macro definitions to be used in asm
- * files only. This is intended to be the equivalent of arm_gcc_inline.h
- */
-
-#ifndef _ARM_AS_MACROS_H_
-#define _ARM_AS_MACROS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "coproc_defs.h"
-
-/**
- * @name The following macros re-arrange the order of the mcr/mrc operands
- * making it suitable to be used with the macros defined in coproc_defs.h
- *
- * @par For example
- * mcr_p15 DOMAIN_CONTROL, r3
- * @par replaces
- * mcr p15, 0, r3, c3, c0, 0
- * @{
- */
-.macro mcr_p15 op1, op2, op3, op4, reg, cond=al
- mcr\cond p15, \op1, \reg, \op2, \op3, \op4
-.endm
-
-.macro mrc_p15 op1, op2, op3, op4, reg, cond=al
- mrc\cond p15, \op1, \reg, \op2, \op3, \op4
-.endm
-
-.macro mcrr_p15 op1, op2, reg1, reg2
- mcrr p15, \op1, \reg1, \reg2, \op2
-.endm
-
-.macro mrrc_p15 op1, op2, reg1, reg2
- mrrc p15, \op1, \reg1, \reg2, \op2
-.endm
-/*@}*/
-
-/**
- * @name Our toolchain does not include support for the VE instructions yet.
- * @{
- */
-.macro hvc imm16
- .word ARM_INSTR_HVC_A1_ENC(\imm16)
-.endm
-
-.macro eret
- .word ARM_INSTR_ERET_A1_ENC(ARM_INSTR_COND_AL)
-.endm
-
-.macro msr_ext rm, rn
- .word ARM_INSTR_MSR_EXT_A1_ENC(ARM_INSTR_COND_AL, \rm, \rn)
-.endm
-
-.macro mrs_ext rd, rm
- .word ARM_INSTR_MRS_EXT_A1_ENC(ARM_INSTR_COND_AL, \rd, \rm)
-.endm
-/*@}*/
-
-#endif /// ifndef _ARM_AS_MACROS_H_
diff --git a/arch/arm/mvp/mvpkm/arm_defs.h b/arch/arm/mvp/mvpkm/arm_defs.h
deleted file mode 100644
index 2c39f6a..0000000
--- a/arch/arm/mvp/mvpkm/arm_defs.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Umbrella header file for all ARM-related definitions. By
- * including this you gain access to all such definitions in
- * lib/arm and are guaranteed a stable include.
- */
-
-#ifndef _ARM_DEFS_H_
-#define _ARM_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define ARM_V4 4
-#define ARM_V5 5
-#define ARM_V6 6
-#define ARM_V7 7
-#define ARM_V8 8
-
-#include "coproc_defs.h"
-#include "exc_defs.h"
-#include "instr_defs.h"
-#include "mmu_defs.h"
-#include "lpae_defs.h"
-#include "ve_defs.h"
-#include "psr_defs.h"
-
-#endif /// _ARM_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/arm_gcc_inline.h b/arch/arm/mvp/mvpkm/arm_gcc_inline.h
deleted file mode 100644
index 33ffe69..0000000
--- a/arch/arm/mvp/mvpkm/arm_gcc_inline.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief GCC inline stubs for ARM assembler instructions.
- */
-
-#ifndef _ARM_GCC_INLINE_H_
-#define _ARM_GCC_INLINE_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "coproc_defs.h"
-
-/*
- * Macros for accessing CP10.
- */
-#define _ARM_CP10_MRCMCR_STR(_op1,_cr1,_cr2,_op2,_var) \
- " p10, " #_op1 ","#_var"," #_cr1 "," #_cr2 "," #_op2 "\n\t"
-
-#define _ARM_MRC_CP10(_op1,_cr1,_cr2,_op2,_var) \
- asm volatile ("mrc" _ARM_CP10_MRCMCR_STR(_op1,_cr1,_cr2,_op2,%0) \
- : "=r" (_var) )
-
-#define ARM_MRC_CP10(_cp_reg,_var) _ARM_MRC_CP10(_cp_reg,_var)
-
-#define _ARM_MCR_CP10(_op1,_cr1,_cr2,_op2,_val) \
- asm volatile ("mcr" _ARM_CP10_MRCMCR_STR(_op1,_cr1,_cr2,_op2,%0) \
- : \
- : "r" (_val) )
-
-#define ARM_MCR_CP10(_cp_reg,_val) _ARM_MCR_CP10(_cp_reg,_val)
-
-
-/*
- * Macros for accessing CP15.
- */
-#define _ARM_CP15_MRCMCR_STR(_op1,_cr1,_cr2,_op2,_var) \
- " p15, " #_op1 ","#_var"," #_cr1 "," #_cr2 "," #_op2 "\n\t"
-
-#define ARM_CP15_MRCMCR_STR(_cp_reg,_var) _ARM_CP15_MRCMCR_STR(_cp_reg,_var)
-
-#ifdef __COVERITY__
-static uint32 __cp15;
-#define _ARM_MRC_CP15(_op1,_cr1,_cr2,_op2,_var) \
- (_var) = (uint32)__cp15
-#else
-#define _ARM_MRC_CP15(_op1,_cr1,_cr2,_op2,_var) \
- asm volatile ("mrc" _ARM_CP15_MRCMCR_STR(_op1,_cr1,_cr2,_op2,%0) \
- : "=r" (_var) \
- : \
- : "memory")
-#endif
-
-#define ARM_MRC_CP15(_cp_reg,_var) _ARM_MRC_CP15(_cp_reg,_var)
-
-
-#ifdef __COVERITY__
-#define _ARM_MCR_CP15(_op1,_cr1,_cr2,_op2,_val) \
- __cp15 = (_val)
-#else
-#define _ARM_MCR_CP15(_op1,_cr1,_cr2,_op2,_val) \
- asm volatile ("mcr" _ARM_CP15_MRCMCR_STR(_op1,_cr1,_cr2,_op2,%0) \
- : \
- : "r" (_val)\
- : "memory")
-#endif
-
-#define ARM_MCR_CP15(_cp_reg,_val) _ARM_MCR_CP15(_cp_reg,_val)
-
-#define _ARM_MRRC_CP15(_op,_cr,_val1,_val2) \
- asm volatile ("mrrc p15, " #_op ",%0,%1," #_cr "\n\t" \
- : "=r" (_val1), "=r" (_val2) \
- : \
- : "memory")
-
-#define ARM_MRRC_CP15(_cp_reg,_val1,_val2) _ARM_MRRC_CP15(_cp_reg,_val1,_val2)
-
-#define ARM_MRRC64_CP15(_cp_reg,_val) \
- _ARM_MRRC_CP15(_cp_reg,_val,*((uint8 *)&(_val) + 4))
-
-#define _ARM_MCRR_CP15(_op,_cr,_val1,_val2) \
- asm volatile ("mcrr p15, " #_op ",%0,%1," #_cr "\n\t" \
- : \
- : "r" (_val1), "r" (_val2) \
- : "memory")
-
-#define ARM_MCRR_CP15(_cp_reg,_val1,_val2) _ARM_MCRR_CP15(_cp_reg,_val1,_val2)
-
-#define ARM_MCRR64_CP15(_cp_reg,_val) \
- _ARM_MCRR_CP15(_cp_reg,_val,*((uint8 *)&(_val) + 4))
-
-#define DMB() asm volatile ("dmb" : : : "memory")
-#define DSB() asm volatile ("dsb" : : : "memory")
-#define ISB() asm volatile ("isb" : : : "memory")
-
-/**
- * @name 64-bit multiplies
- * @{
- */
-
-// rdhi:rdlo = rm * rs + rdhi + rdlo
-#define ARM_UMAAL(rdlo,rdhi,rm,rs) asm ("umaal %0,%1,%2,%3" \
- : "+r" (rdlo), "+r" (rdhi) \
- : "r" (rm), "r" (rs))
-
-// rdhi:rdlo += rm * rs
-#define ARM_UMLAL(rdlo,rdhi,rm,rs) asm ("umlal %0,%1,%2,%3" \
- : "+r" (rdlo), "+r" (rdhi) \
- : "r" (rm), "r" (rs))
-
-// rdhi:rdlo = rm * rs
-#define ARM_UMULL(rdlo,rdhi,rm,rs) asm ("umull %0,%1,%2,%3" \
- : "=r" (rdlo), "=r" (rdhi) \
- : "r" (rm), "r" (rs))
-/*@}*/
-
-/**
- * @brief Disable interrupts (IRQ + FIQ)
- *
- * @return CPSR status prior to disabling - suitable for passing to
- * ARM_RestoreInterrupts() to restore IRQ/FIQ levels to
- * pre-call values
- */
-static inline uint32
-ARM_DisableInterrupts(void)
-{
- register uint32 status;
-
- asm volatile ("mrs %0, cpsr \n\t"
- "orr r1, %0, %1 \n\t"
- "msr cpsr_c, r1 \n\t"
- : "=&r" (status)
- : "i" (ARM_PSR_I | ARM_PSR_F)
- : "r1", "memory");
-
- return status;
-}
-
-/**
- * @brief Restore interrupts
- *
- * @param status return value from a previous call to ARM_DisableInterrupts()
- */
-static inline void
-ARM_RestoreInterrupts(uint32 status)
-{
- asm volatile ("msr cpsr_c, %0 \n\t" : : "r" (status) : "memory");
-}
-
-/**
- * @brief Read current CPSR value
- *
- * @return current CPSR value
- */
-static inline uint32
-ARM_ReadCPSR(void)
-{
- uint32 status;
-
- asm volatile ("mrs %0, cpsr \n\t" : "=r" (status));
-
- return status;
-}
-
-/**
- * @brief Read current stack pointer
- *
- * @return stack pointer value
- */
-static inline uint32
-ARM_ReadSP(void)
-{
- uint32 sp;
-
- asm volatile ("mov %0, sp \n\t" : "=r" (sp));
-
- return sp;
-}
-
-#endif /// ifndef _ARM_GCC_INLINE_H_
diff --git a/arch/arm/mvp/mvpkm/arm_inline.h b/arch/arm/mvp/mvpkm/arm_inline.h
deleted file mode 100644
index 3689a7f..0000000
--- a/arch/arm/mvp/mvpkm/arm_inline.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Inline stubs for ARM assembler instructions.
- */
-
-#ifndef _ARM_INLINE_H_
-#define _ARM_INLINE_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "arm_types.h"
-#include "arm_defs.h"
-
-/*
- * Compiler specific include - we get the actual inline assembler macros here.
- */
-#include "arm_gcc_inline.h"
-
-/*
- * Some non-compiler specific helper functions for inline assembler macros
- * included above.
- */
-
-/**
- * @brief Predicate giving whether interrupts are currently enabled
- *
- * @return TRUE if enabled, FALSE otherwise
- */
-static inline _Bool
-ARM_InterruptsEnabled(void)
-{
- return !(ARM_ReadCPSR() & ARM_PSR_I);
-}
-
-/**
- * @brief Read current TTBR0 base machine address
- *
- * @return machine address given by translation table base register 0
- */
-static inline MA
-ARM_ReadTTBase0(void)
-{
- MA ttbase;
-
- ARM_MRC_CP15(TTBASE0_POINTER, ttbase);
-
- return ttbase & ARM_CP15_TTBASE_MASK;
-}
-
-/**
- * @brief Read VFP/Adv.SIMD Extension System Register
- *
- * @param specReg which VFP/Adv. SIMD Extension System Register
- *
- * @return Read value
- */
-static inline uint32
-ARM_ReadVFPSystemRegister(uint8 specReg)
-{
- uint32 value = 0;
-
- /*
- * VMRS is the instruction used to read VFP System Registers.
- * VMRS is the new UAL-syntax equivalent for the FMRX instruction.
- * At the end of the day, all these are just synonyms for MRC
- * instructions on CP10, as the VFP system registers sit in CP10
- * and MRC is the Co-processor register read instruction.
- * We use the primitive MRC synonym for VMRS here as VMRS/FMRX
- * don't seem to be working when used inside asm volatile blocks,
- * as, for some reason, the inline assembler seems to be setting
- * the VFP mode to soft-float. Moreover, we WANT the monitor code
- * to be compiled with soft-float so that the compiler doesn't use
- * VFP instructions for the monitor's own use, such as for 64-bit
- * integer operations, etc., since we pass-through the use of the
- * underlying hardware's VFP/SIMD state to the guest.
- */
-
- switch (specReg) {
- case ARM_VFP_SYSTEM_REG_FPSID:
- ARM_MRC_CP10(VFP_FPSID, value);
- break;
- case ARM_VFP_SYSTEM_REG_MVFR0:
- ARM_MRC_CP10(VFP_MVFR0, value);
- break;
- case ARM_VFP_SYSTEM_REG_MVFR1:
- ARM_MRC_CP10(VFP_MVFR1, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPEXC:
- ARM_MRC_CP10(VFP_FPEXC, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPSCR:
- ARM_MRC_CP10(VFP_FPSCR, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPINST:
- ARM_MRC_CP10(VFP_FPINST, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPINST2:
- ARM_MRC_CP10(VFP_FPINST2, value);
- break;
- default:
- NOT_IMPLEMENTED_JIRA(1849);
- break;
- }
-
- return value;
-}
-
-/**
- * @brief Write to VFP/Adv.SIMD Extension System Register
- *
- * @param specReg which VFP/Adv. SIMD Extension System Register
- * @param value desired value to be written to the System Register
- */
-static inline void
-ARM_WriteVFPSystemRegister(uint8 specReg, uint32 value)
-{
- /*
- * VMSR is the instruction used to write to VFP System Registers.
- * VMSR is the new UAL-syntax equivalent for the FMXR instruction.
- * At the end of the day, all these are just synonyms for MCR
- * instructions on CP10, as the VFP system registers sit in CP10
- * and MCR is the Co-processor register write instruction.
- * We use the primitive MCR synonym for VMSR here as VMSR/FMXR
- * don't seem to be working when used inside asm volatile blocks,
- * as, for some reason, the inline assembler seems to be setting
- * the VFP mode to soft-float. Moreover, we WANT the monitor code
- * to be compiled with soft-float so that the compiler doesn't use
- * VFP instructions for the monitor's own use, such as for 64-bit
- * integer operations, etc., since we pass-through the use of the
- * underlying hardware's VFP/SIMD state to the guest.
- */
-
- switch (specReg) {
- case ARM_VFP_SYSTEM_REG_FPEXC:
- ARM_MCR_CP10(VFP_FPEXC, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPSCR:
- ARM_MCR_CP10(VFP_FPSCR, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPINST:
- ARM_MCR_CP10(VFP_FPINST, value);
- break;
- case ARM_VFP_SYSTEM_REG_FPINST2:
- ARM_MCR_CP10(VFP_FPINST2, value);
- break;
- default:
- NOT_IMPLEMENTED_JIRA(1849);
- break;
- }
-}
-
-#endif /// ifndef _ARM_INLINE_H_
diff --git a/arch/arm/mvp/mvpkm/arm_types.h b/arch/arm/mvp/mvpkm/arm_types.h
deleted file mode 100644
index 2075860..0000000
--- a/arch/arm/mvp/mvpkm/arm_types.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Umbrella header file for all ARM-related types.
- */
-
-#ifndef _ARM_TYPES_H_
-#define _ARM_TYPES_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "exc_types.h"
-#include "mmu_types.h"
-#include "lpae_types.h"
-
-#endif /// _ARM_TYPES_H_
diff --git a/arch/arm/mvp/mvpkm/atomic.h b/arch/arm/mvp/mvpkm/atomic.h
deleted file mode 100644
index 987860f..0000000
--- a/arch/arm/mvp/mvpkm/atomic.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief bus-atomic operators.
- *
- * The 'atm' argument is the atomic memory cell being operated on and the
- * remainder of the arguments are the values being applied to the atomic cell
- * which is assumed to be located in shared normal memory. The operation is
- * both atomic and visible to the default share-ability domain upon completion.
- *
- * The design of each macro is such that the compiler should check types
- * correctly. For those macros that return a value, the return type should be
- * the same as the 'atm' argument (with the exception of ATOMIC_SETIF which
- * returns an int value of 0 or 1).
- *
- * Those names ending in 'M' return the modified value of 'atm'.
- * Those names ending in 'O' return the original value of 'atm'.
- * Those names ending in 'V' return void (ie, nothing).
- */
-
-#ifndef _ATOMIC_H
-#define _ATOMIC_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#include "include_check.h"
-
-/*
- * Wrap type 't' in an atomic struct.
- * Eg, 'static ATOMIC(uint8) counter;'.
- *
- * The function macros use the atm_Normal member to clone the atom's type
- * when the volatile semantic is not required. They use the atm_Volatl member
- * when the volatile semantic is required.
- */
-#define ATOMIC(t) union { t atm_Normal; t volatile atm_Volatl; }
-
-/*
- * Static atomic variable initialization.
- * Eg, 'static ATOMIC(uint8) counter = ATOMIC_INI(35);'.
- */
-#define ATOMIC_INI(v) { .atm_Normal = v }
-
-/*
- * Some commonly used atomic types.
- */
-typedef ATOMIC(int32) AtmSInt32 __attribute__ ((aligned (4)));
-typedef ATOMIC(uint32) AtmUInt32 __attribute__ ((aligned (4)));
-typedef ATOMIC(uint64) AtmUInt64 __attribute__ ((aligned (8)));
-
-/*
- * Architecture-dependent implementations.
- */
-#if defined(__COVERITY__)
-#include "atomic_coverity.h"
-#elif defined(__arm__)
-#include "atomic_arm.h"
-#elif defined(__i386) || defined(__x86_64)
-#include "atomic_x86.h"
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/atomic_arm.h b/arch/arm/mvp/mvpkm/atomic_arm.h
deleted file mode 100644
index 447aa55..0000000
--- a/arch/arm/mvp/mvpkm/atomic_arm.h
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief bus-atomic operators, ARM implementation.
- * Do not include directly, include 'atomic.h' instead.
- * Memory where the atomic reside must be shared.
- *
- * These operations assume that the exclusive access monitor is cleared during
- * abort entry but they do not assume that cooperative scheduling (e.g. Linux
- * schedule()) clears the monitor and hence the use of "clrex" when required.
- */
-
-#ifndef _ATOMIC_ARM_H
-#define _ATOMIC_ARM_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#include "include_check.h"
-
-#include "mvp_assert.h"
-
-/**
- * @brief Atomic Add
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return the original value of 'atm'
- */
-#define ATOMIC_ADDO(atm,modval) ATOMIC_OPO_PRIVATE(atm,modval,add)
-
-/**
- * @brief Atomic Add
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return nothing
- */
-#define ATOMIC_ADDV(atm,modval) ATOMIC_OPV_PRIVATE(atm,modval,add)
-
-/**
- * @brief Atomic And
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return the original value of 'atm'
- */
-#define ATOMIC_ANDO(atm,modval) ATOMIC_OPO_PRIVATE(atm,modval,and)
-
-/**
- * @brief Atomic And
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return nothing
- */
-#define ATOMIC_ANDV(atm,modval) ATOMIC_OPV_PRIVATE(atm,modval,and)
-
-/**
- * @brief Retrieve an atomic value
- * @param atm atomic cell to operate on
- * @return the value of 'atm'
- */
-#define ATOMIC_GETO(atm) ({ \
- typeof((atm).atm_Normal) _oldval; \
- switch (sizeof _oldval) { \
- case 4: \
- asm volatile ("ldrex %0, [%1]\n" \
- "clrex" \
- : "=&r" (_oldval) \
- : "r" (&((atm).atm_Volatl))); \
- break; \
- case 8: \
- asm volatile ("ldrexd %0, %H0, [%1]\n" \
- "clrex" \
- : "=&r" (_oldval) \
- : "r" (&((atm).atm_Volatl))); \
- break; \
- default: \
- FATAL(); \
- } \
- _oldval; \
-})
-
-/**
- * @brief Atomic Or
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return the original value of 'atm'
- */
-#define ATOMIC_ORO(atm,modval) ATOMIC_OPO_PRIVATE(atm,modval,orr)
-
-/**
- * @brief Atomic Or
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return nothing
- */
-#define ATOMIC_ORV(atm,modval) ATOMIC_OPV_PRIVATE(atm,modval,orr)
-
-/**
- * @brief Atomic Conditional Write, ie,
- * set 'atm' to 'newval' iff it was 'oldval'.
- * @param atm atomic cell to operate on
- * @param newval value to possibly write to atomic cell
- * @param oldval value that atomic cell must equal
- * @return 0 if failed; 1 if successful
- */
-#define ATOMIC_SETIF(atm,newval,oldval) ({ \
- int _failed; \
- typeof((atm).atm_Normal) _newval = newval; \
- typeof((atm).atm_Normal) _oldval = oldval; \
- ASSERT_ON_COMPILE(sizeof _newval == 4); \
- asm volatile ("1: ldrex %0, [%1] \n" \
- " cmp %0, %2 \n" \
- " mov %0, #2 \n" \
- " IT eq \n" \
- " strexeq %0, %3, [%1] \n" \
- " cmp %0, #1 \n" \
- " beq 1b \n" \
- " clrex" \
- : "=&r" (_failed) \
- : "r" (&((atm).atm_Volatl)), \
- "r" (_oldval), \
- "r" (_newval) \
- : "cc", "memory"); \
- !_failed; \
-})
-
-
-/**
- * @brief Atomic Write (unconditional)
- * @param atm atomic cell to operate on
- * @param newval value to write to atomic cell
- * @return the original value of 'atm'
- */
-#define ATOMIC_SETO(atm,newval) ({ \
- int _failed; \
- typeof((atm).atm_Normal) _newval = newval; \
- typeof((atm).atm_Normal) _oldval; \
- switch (sizeof _newval) { \
- case 4: \
- asm volatile ("1: ldrex %0, [%2]\n" \
- " strex %1, %3, [%2]\n" \
- " teq %1, #0\n" \
- " bne 1b" \
- : "=&r" (_oldval), \
- "=&r" (_failed) \
- : "r" (&((atm).atm_Volatl)), \
- "r" (_newval) \
- : "cc", "memory"); \
- break; \
- case 8: \
- asm volatile ("1: ldrexd %0, %H0, [%2]\n" \
- " strexd %1, %3, %H3, [%2]\n"\
- " teq %1, #0\n" \
- " bne 1b" \
- : "=&r" (_oldval), \
- "=&r" (_failed) \
- : "r" (&((atm).atm_Volatl)), \
- "r" (_newval) \
- : "cc", "memory"); \
- break; \
- default: \
- FATAL(); \
- } \
- _oldval; \
-})
-
-/**
- * @brief Atomic Write (unconditional)
- * @param atm atomic cell to operate on
- * @param newval value to write to atomic cell
- * @return nothing
- */
-#define ATOMIC_SETV(atm,newval) do { ATOMIC_SETO((atm),(newval)); } while (0)
-
-/**
- * @brief Atomic Subtract
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return the original value of 'atm'
- */
-#define ATOMIC_SUBO(atm,modval) ATOMIC_OPO_PRIVATE(atm,modval,sub)
-
-/**
- * @brief Atomic Subtract
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @return nothing
- */
-#define ATOMIC_SUBV(atm,modval) ATOMIC_OPV_PRIVATE(atm,modval,sub)
-
-/**
- * @brief Atomic Generic Binary Operation
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @param op ARM instruction (add, and, orr, etc)
- * @return the original value of 'atm'
- */
-#define ATOMIC_OPO_PRIVATE(atm,modval,op) ({ \
- int _failed; \
- typeof((atm).atm_Normal) _modval = modval; \
- typeof((atm).atm_Normal) _oldval; \
- typeof((atm).atm_Normal) _newval; \
- ASSERT_ON_COMPILE(sizeof _modval == 4); \
- asm volatile ("1: ldrex %0, [%3]\n" \
- #op " %1, %0, %4\n" \
- " strex %2, %1, [%3]\n" \
- " teq %2, #0\n" \
- " bne 1b" \
- : "=&r" (_oldval), \
- "=&r" (_newval), \
- "=&r" (_failed) \
- : "r" (&((atm).atm_Volatl)), \
- "r" (_modval) \
- : "memory"); \
- _oldval; \
-})
-
-/**
- * @brief Atomic Generic Binary Operation
- * @param atm atomic cell to operate on
- * @param modval value to apply to atomic cell
- * @param op ARM instruction (add, and, orr, etc)
- * @return nothing
- */
-#define ATOMIC_OPV_PRIVATE(atm,modval,op) do { \
- int _failed; \
- typeof((atm).atm_Normal) _modval = modval; \
- typeof((atm).atm_Normal) _sample; \
- ASSERT_ON_COMPILE(sizeof _modval == 4); \
- asm volatile ("1: ldrex %0, [%2]\n" \
- #op " %0, %3\n" \
- " strex %1, %0, [%2]\n" \
- " teq %1, #0\n" \
- " bne 1b" \
- : "=&r" (_sample), \
- "=&r" (_failed) \
- : "r" (&((atm).atm_Volatl)), \
- "r" (_modval) \
- : "memory"); \
-} while (0)
-
-/**
- * @brief Single-copy atomic word write.
- *
- * ARMv7 defines world-aligned word writes to be single-copy atomic. See
- * A3-26 ARM DDI 0406A.
- *
- * @param p word aligned location to write to
- * @param val word-sized value to write to p
- */
-#define ATOMIC_SINGLE_COPY_WRITE32(p,val) \
- do { \
- ASSERT(sizeof(val) == 4); \
- ASSERT((MVA)(p) % sizeof(val) == 0); \
- asm volatile("str %0, [%1]" \
- : \
- : "r" (val), "r" (p) \
- : "memory"); \
- } while (0);
-
-
-/**
- * @brief Single-copy atomic word read.
- *
- * ARMv7 defines world-aligned word reads to be single-copy atomic. See
- * A3-26 ARM DDI 0406A.
- *
- * @param p word aligned location to read from
- *
- * @return word-sized value from p
- */
-#define ATOMIC_SINGLE_COPY_READ32(p) ({ \
- ASSERT((MVA)(p) % sizeof(uint32) == 0); \
- uint32 _val; \
- asm volatile("ldr %0, [%1]" \
- : "=r" (_val) \
- : "r" (p) \
- ); \
- _val; \
-})
-
-/**
- * @brief Single-copy atomic double word write.
- *
- * LPAE defines double world-aligned double word writes to be single-copy
- * atomic. See 6.7 ARM PRD03-GENC-008469 13.0.
- *
- * @param p double word aligned location to write to
- * @param val double word-sized value to write to p
- */
-#define ATOMIC_SINGLE_COPY_WRITE64(p,val) \
- do { \
- ASSERT(sizeof(val) == 8); \
- ASSERT((MVA)(p) % sizeof(val) == 0); \
- asm volatile("mov r0, %0 \n" \
- "mov r1, %1 \n" \
- "strd r0, r1, [%2]" \
- : \
- : "r" ((uint32)(val)), \
- "r" (((uint64)(val)) >> 32),\
- "r" (p) \
- : "r0", "r1", "memory"); \
- } while (0);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/check_kconfig.c b/arch/arm/mvp/mvpkm/check_kconfig.c
deleted file mode 100644
index bab1b6e..0000000
--- a/arch/arm/mvp/mvpkm/check_kconfig.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- * @brief Check for required kernel configuration
- *
- * Check to make sure that the kernel options that the MVP hypervisor requires
- * have been enabled in the kernel that this kernel module is being built
- * against.
- */
-#include <linux/version.h>
-
-/*
- * Minimum kernel version
- * - network namespace support is only really functional starting in 2.6.29
- * - Android Gingerbread requires 2.6.35
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
-#error "MVP requires a host kernel newer than 2.6.35"
-#endif
-
-/* module loading ability */
-#ifndef CONFIG_MODULES
-#error "MVP requires kernel loadable module support be enabled (CONFIG_MODULES)"
-#endif
-#ifndef CONFIG_MODULE_UNLOAD
-#error "MVP requires kernel module unload support be enabled (CONFIG_MODULE_UNLOAD)"
-#endif
-
-/* sysfs */
-#ifndef CONFIG_SYSFS
-#error "MVP requires sysfs support (CONFIG_SYSFS)"
-#endif
-
-/* network traffic isolation */
-#ifndef CONFIG_NAMESPACES
-#error "MVP networking support requires namespace support (CONFIG_NAMESPACES)"
-#endif
-#ifndef CONFIG_NET_NS
-#error "MVP networking support requires Network Namespace support to be enabled (CONFIG_NET_NS)"
-#endif
-
-/* TCP/IP networking */
-#ifndef CONFIG_INET
-#error "MVP networking requires IPv4 support (CONFIG_INET)"
-#endif
-#ifndef CONFIG_IPV6
-#error "MVP networking requires IPv6 support (CONFIG_IPV6)"
-#endif
-
-/* VPN support */
-#if !defined(CONFIG_TUN) && !defined(CONFIG_TUN_MODULE)
-#error "MVP VPN support requires TUN device support (CONFIG_TUN)"
-#endif
-
-#if !defined(CONFIG_NETFILTER) && !defined(PVTCP_DISABLE_NETFILTER)
-#error "MVP networking support requires netfilter support (CONFIG_NETFILTER)"
-#endif
-
-/* Force /proc/config.gz support for eng/userdebug builds */
-#ifdef MVP_DEBUG
-#if !defined(CONFIG_IKCONFIG) || !defined(CONFIG_IKCONFIG_PROC)
-#error "MVP kernel /proc/config.gz support required for debuggability (CONFIG_IKCONFIG_PROC)"
-#endif
-#endif
-
-/* Sanity check we're only dealing with the memory hotplug + migrate and/or
- * compaction combo */
-#ifdef CONFIG_MIGRATION
-#if defined(CONFIG_NUMA) || defined(CONFIG_CPUSETS) || defined(CONFIG_MEMORY_FAILURE)
-#error "MVP not tested with migration features other than CONFIG_MEMORY_HOTPLUG and CONFIG_COMPACTION"
-#endif
-#endif
diff --git a/arch/arm/mvp/mvpkm/comm_os.h b/arch/arm/mvp/mvpkm/comm_os.h
deleted file mode 100644
index cf858f6..0000000
--- a/arch/arm/mvp/mvpkm/comm_os.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Cross-platform base type definitions and function declarations.
- * Includes OS-specific base type definitions and function declarations.
- */
-
-#ifndef _COMM_OS_H_
-#define _COMM_OS_H_
-
-/* For-ever timeout constant (in milliseconds). */
-#define COMM_OS_4EVER_TO ((unsigned long long)(~0UL >> 1))
-
-/* Condition function prototype. Returns 1: true, 0: false, < 0: error code. */
-typedef int (*CommOSWaitConditionFunc)(void *arg1, void *arg2);
-
-/* Dispatch function prototype. Called by input (dispatch) kernel threads. */
-typedef unsigned int (*CommOSDispatchFunc)(void);
-
-/* Module initialization and exit callback functions. */
-extern int (*commOSModInit)(void *args);
-extern void (*commOSModExit)(void);
-
-/* Macro to assign Init and Exit callbacks. */
-#define COMM_OS_MOD_INIT(init, exit) \
- int (*commOSModInit)(void *args) = init; \
- void (*commOSModExit)(void) = exit
-
-
-/*
- * OS-specific implementations must provide the following:
- * 1. Types:
- * CommOSAtomic
- * CommOSSpinlock
- * CommOSMutex
- * CommOSWaitQueue
- * CommOSWork
- * CommOSWorkFunc
- * CommOSList
- * CommOSModule
- * struct kvec
- *
- * 2. Definition, initializers:
- * CommOSSpinlock_Define()
- *
- * 3. Functions:
- * void CommOS_Debug(const char *format, ...);
- * void CommOS_Log(const char *format, ...);
- * void CommOS_WriteAtomic(CommOSAtomic *atomic, int val);
- * int CommOS_ReadAtomic(CommOSAtomic *atomic);
- * int CommOS_AddReturnAtomic(CommOSAtomic *atomic, int val);
- * int CommOS_SubReturnAtomic(CommOSAtomic *atomic, int val);
- * void CommOS_SpinlockInit(CommOSSpinlock *lock);
- * void CommOS_SpinLockBH(CommOSSpinlock *lock);
- * int CommOS_SpinTrylockBH(CommOSSpinlock *lock);
- * void CommOS_SpinUnlockBH(CommOSSpinlock *lock);
- * void CommOS_SpinLock(CommOSSpinlock *lock);
- * int CommOS_SpinTrylock(CommOSSpinlock *lock);
- * void CommOS_SpinUnlock(CommOSSpinlock *lock);
- * void CommOS_MutexInit(CommOSMutex *mutex);
- * void CommOS_MutexLock(CommOSMutex *mutex);
- * int CommOS_MutexLockUninterruptible(CommOSMutex *mutex);
- * int CommOS_MutexTrylock(CommOSMutex *mutex);
- * void CommOS_MutexUnlock(CommOSMutex *mutex);
- * void CommOS_WaitQueueInit(CommOSWaitQueue *wq);
- * CommOS_DoWait(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc cond,
- * void *condArg1,
- * void *condArg2,
- * unsigned long long *timeoutMillis,
- * int interruptible);
- * int CommOS_Wait(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc func,
- * void *funcArg1,
- * void *funcArg2,
- * unsigned long long *timeoutMillis);
- * int CommOS_WaitUninterruptible(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc func,
- * void *funcArg1,
- * void *funcArg2,
- * unsigned long long *timeoutMillis);
- * void CommOS_WakeUp(CommOSWaitQueue *wq);
- * void *CommOS_KmallocNoSleep(unsigned int size);
- * void *CommOS_Kmalloc(unsigned int size);
- * void CommOS_Kfree(void *arg);
- * void CommOS_Yield(void);
- * unsigned long long CommOS_GetCurrentMillis(void);
- * void CommOS_ListInit(CommOSList *list);
- * int CommOS_ListEmpty(CommOSList *list);
- * void CommOS_ListAdd(CommOSList *list, CommOSList *listElem);
- * void CommOS_ListAddTail(CommOSList *list, CommOSList *listElem);
- * void int CommOS_ListDel(CommOSList *listElem);
- * Macros:
- * CommOS_ListForEach(*list, *item, itemListFieldName);
- * CommOS_ListForEachSafe(*list, *item, *tmp, itemListFieldName);
- * void CommOS_ListSplice(CommOSList *list, CommOSList *listToAdd);
- * void CommOS_ListSpliceTail(CommOSList *list, CommOSList *listToAdd);
- * CommOSModule CommOS_ModuleSelf(void);
- * int CommOS_ModuleGet(CommOSModule module);
- * void CommOS_ModulePut(CommOSModule module);
- * void CommOS_MemBarrier(void);
- *
- * These cannot be defined here: a) non-pointer type definitions need size
- * information, and b) functions may or may not be inlined, or macros may
- * be used instead.
- */
-
-
-#ifdef __linux__
-#include "comm_os_linux.h"
-#else
-#error "Unsupported OS"
-#endif
-
-/* Functions to start and stop the dispatch and aio kernel threads. */
-void CommOS_StopIO(void);
-void CommOS_ScheduleDisp(void);
-void CommOS_InitWork(CommOSWork *work, CommOSWorkFunc func);
-int CommOS_ScheduleAIOWork(CommOSWork *work);
-void CommOS_FlushAIOWork(CommOSWork *work);
-
-int
-CommOS_StartIO(const char *dispatchTaskName,
- CommOSDispatchFunc dispatchHandler,
- unsigned int interval,
- unsigned int maxCycles,
- const char *aioTaskName);
-
-
-#endif /* _COMM_OS_H_ */
diff --git a/arch/arm/mvp/mvpkm/comm_os_linux.h b/arch/arm/mvp/mvpkm/comm_os_linux.h
deleted file mode 100644
index c9d4f26..0000000
--- a/arch/arm/mvp/mvpkm/comm_os_linux.h
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Contains linux-specific type definitions and function declarations
- */
-
-#ifndef _COMM_OS_LINUX_H_
-#define _COMM_OS_LINUX_H_
-
-#include <linux/types.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-#error "Kernel versions lower than 2.6.20 are not supported"
-#endif
-
-#include <linux/kernel.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-
-/*
- * Type definitions.
- */
-
-typedef atomic_t CommOSAtomic;
-typedef spinlock_t CommOSSpinlock;
-typedef struct mutex CommOSMutex;
-typedef wait_queue_head_t CommOSWaitQueue;
-typedef struct delayed_work CommOSWork;
-typedef void (*CommOSWorkFunc)(CommOSWork *work);
-typedef struct list_head CommOSList;
-typedef struct module *CommOSModule;
-
-
-/*
- * Initializers.
- */
-
-#define CommOSSpinlock_Define DEFINE_SPINLOCK
-
-
-#define COMM_OS_DOLOG(...) printk(KERN_INFO __VA_ARGS__)
-
-
-/**
- * @brief Logs given arguments in debug builds.
- */
-
-#if defined(COMM_OS_DEBUG)
- #define CommOS_Debug(args) COMM_OS_DOLOG args
-#else
- #define CommOS_Debug(args)
-#endif
-
-
-/**
- * @brief Logs given arguments.
- */
-
-#define CommOS_Log(args) COMM_OS_DOLOG args
-
-
-/**
- * @brief Logs function name and location.
- */
-
-#if defined(COMM_OS_TRACE)
-#define TRACE(ptr) \
- do { \
- CommOS_Debug(("%p:%s: at [%s:%d] with arg ptr [0x%p].\n", current, \
- __FUNCTION__, __FILE__, __LINE__, (ptr))); \
- } while (0)
-#else
-#define TRACE(ptr)
-#endif
-
-
-/**
- * @brief Write atomic variable
- * @param[in,out] atomic variable to write
- * @param val new value
- */
-
-static inline void
-CommOS_WriteAtomic(CommOSAtomic *atomic,
- int val)
-{
- atomic_set(atomic, val);
-}
-
-
-/**
- * @brief Reads atomic variable
- * @param atomic variable to read
- * @return value
- */
-
-static inline int
-CommOS_ReadAtomic(CommOSAtomic *atomic)
-{
- return atomic_read(atomic);
-}
-
-
-/**
- * @brief Atomically add value to atomic variable, return new value.
- * @param[in,out] atomic variable
- * @param val value to add
- * @return new value
- */
-
-static inline int
-CommOS_AddReturnAtomic(CommOSAtomic *atomic,
- int val)
-{
- return atomic_add_return(val, atomic);
-}
-
-
-/**
- * @brief Atomically substract value from atomic variable, return new value.
- * @param[in,out] atomic variable
- * @param val value to substract
- * @return new value
- */
-
-static inline int
-CommOS_SubReturnAtomic(CommOSAtomic *atomic,
- int val)
-{
- return atomic_sub_return(val, atomic);
-}
-
-
-/**
- * @brief Initializes a given lock.
- * @param[in,out] lock lock to initialize
- */
-
-static inline void
-CommOS_SpinlockInit(CommOSSpinlock *lock)
-{
- spin_lock_init(lock);
-}
-
-
-/**
- * @brief Locks given lock and disables bottom half processing.
- * @param[in,out] lock lock to lock
- */
-
-static inline void
-CommOS_SpinLockBH(CommOSSpinlock *lock)
-{
- spin_lock_bh(lock);
-}
-
-
-/**
- * @brief Attempts to lock the given lock and disable BH processing.
- * @param[in,out] lock lock to lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_SpinTrylockBH(CommOSSpinlock *lock)
-{
- return !spin_trylock_bh(lock);
-}
-
-
-/**
- * @brief Unlocks given lock and re-enables BH processing.
- * @param[in,out] lock lock to unlock
- */
-
-static inline void
-CommOS_SpinUnlockBH(CommOSSpinlock *lock)
-{
- spin_unlock_bh(lock);
-}
-
-
-/**
- * @brief Locks the given lock.
- * @param[in,out] lock lock to lock
- */
-
-static inline void
-CommOS_SpinLock(CommOSSpinlock *lock)
-{
- spin_lock(lock);
-}
-
-
-/**
- * @brief Attempts to lock the given lock.
- * @param[in,out] lock lock to try-lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_SpinTrylock(CommOSSpinlock *lock)
-{
- return !spin_trylock(lock);
-}
-
-
-/**
- * @brief Unlocks given lock.
- * @param[in,out] lock lock to unlock
- */
-
-static inline void
-CommOS_SpinUnlock(CommOSSpinlock *lock)
-{
- spin_unlock(lock);
-}
-
-
-/**
- * @brief Initializes given mutex.
- * @param[in,out] mutex mutex to initialize
- */
-
-static inline void
-CommOS_MutexInit(CommOSMutex *mutex)
-{
- mutex_init(mutex);
-}
-
-
-/**
- * @brief Acquires mutex.
- * @param[in,out] mutex mutex to lock
- * @return zero if successful, non-zero otherwise (interrupted)
- */
-
-static inline int
-CommOS_MutexLock(CommOSMutex *mutex)
-{
- return mutex_lock_interruptible(mutex);
-}
-
-
-/**
- * @brief Acquires mutex in uninterruptible mode.
- * @param[in,out] mutex mutex to lock
- */
-
-static inline void
-CommOS_MutexLockUninterruptible(CommOSMutex *mutex)
-{
- mutex_lock(mutex);
-}
-
-
-/**
- * @brief Attempts to acquire given mutex.
- * @param[in,out] mutex mutex to try-lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_MutexTrylock(CommOSMutex *mutex)
-{
- return !mutex_trylock(mutex);
-}
-
-
-/**
- * @brief Releases a given mutex.
- * @param[in,out] mutex mutex to unlock
- */
-
-static inline void
-CommOS_MutexUnlock(CommOSMutex *mutex)
-{
- mutex_unlock(mutex);
-}
-
-
-/**
- * @brief Initializes a wait queue.
- * @param[in,out] wq workqueue to initialize
- */
-
-static inline void
-CommOS_WaitQueueInit(CommOSWaitQueue *wq)
-{
- init_waitqueue_head(wq);
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * - a signal is pending
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @param interruptible enable/disable signal pending check
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, if a signal is pending or other error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_DoWait(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis,
- int interruptible)
-{
- int rc;
- DEFINE_WAIT(wait);
- long timeout;
-#if defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- long tmpTimeout;
- long retTimeout;
- const unsigned int interval = 50;
-#endif
-
- if (!timeoutMillis) {
- return -1;
- }
- if ((rc = cond(condArg1, condArg2)) != 0) {
- return rc;
- }
-
-#if defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- timeout = msecs_to_jiffies(interval < *timeoutMillis ?
- interval : (unsigned int)*timeoutMillis);
- retTimeout = msecs_to_jiffies((unsigned int)(*timeoutMillis));
-
- for (; retTimeout >= 0; ) {
- prepare_to_wait(wq, &wait,
- (interruptible?TASK_INTERRUPTIBLE:TASK_UNINTERRUPTIBLE));
- if ((rc = cond(condArg1, condArg2))) {
- break;
- }
- if (interruptible && signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if ((tmpTimeout = schedule_timeout(timeout))) {
- retTimeout -= (timeout - tmpTimeout);
- } else {
- retTimeout -= timeout;
- }
- if (retTimeout < 0) {
- retTimeout = 0;
- }
- }
- finish_wait(wq, &wait);
- if (rc == 0) {
- rc = cond(condArg1, condArg2);
- if (rc && (retTimeout == 0)) {
- retTimeout = 1;
- }
- }
- *timeoutMillis = (unsigned long long)jiffies_to_msecs(retTimeout);
-#else // !defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- timeout = msecs_to_jiffies((unsigned int)(*timeoutMillis));
-
- for (;;) {
- prepare_to_wait(wq, &wait,
- (interruptible?TASK_INTERRUPTIBLE:TASK_UNINTERRUPTIBLE));
- if ((rc = cond(condArg1, condArg2)) != 0) {
- break;
- }
- if (interruptible && signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if ((timeout = schedule_timeout(timeout)) == 0) {
- rc = 0;
- break;
- }
- }
- finish_wait(wq, &wait);
- if (rc == 0) {
- rc = cond(condArg1, condArg2);
- if (rc && (timeout == 0)) {
- timeout = 1;
- }
- }
- *timeoutMillis = (unsigned long long)jiffies_to_msecs(timeout);
-#endif
-
- return rc;
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * - a signal is pending
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, if a signal is pending or other error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_Wait(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis)
-{
- return CommOS_DoWait(wq, cond, condArg1, condArg2, timeoutMillis, 1);
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_WaitUninterruptible(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis)
-{
- return CommOS_DoWait(wq, cond, condArg1, condArg2, timeoutMillis, 0);
-}
-
-
-/**
- * @brief Wakes up task(s) waiting on the given wait queue.
- * @param[in,out] wq wait queue.
- */
-
-static inline void
-CommOS_WakeUp(CommOSWaitQueue *wq)
-{
- wake_up(wq);
-}
-
-
-/**
- * @brief Allocates kernel memory of specified size; does not sleep.
- * @param size size to allocate.
- * @return Address of allocated memory or NULL if the allocation fails.
- */
-
-static inline void *
-CommOS_KmallocNoSleep(unsigned int size)
-{
- return kmalloc(size, GFP_ATOMIC);
-}
-
-
-/**
- * @brief Allocates kernel memory of specified size; may sleep.
- * @param size size to allocate.
- * @return Address of allocated memory or NULL if the allocation fails.
- */
-
-static inline void *
-CommOS_Kmalloc(unsigned int size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-
-/**
- * @brief Frees previously allocated kernel memory.
- * @param obj object to free.
- */
-
-static inline void
-CommOS_Kfree(void *obj)
-{
- if (obj) {
- kfree(obj);
- }
-}
-
-
-/**
- * @brief Yields the current cpu to other runnable tasks.
- */
-
-static inline void
-CommOS_Yield(void)
-{
- cond_resched();
-}
-
-
-/**
- * @brief Gets the current time in milliseconds.
- * @return Current time in milliseconds, with precision of at most one tick.
- */
-
-static inline unsigned long long
-CommOS_GetCurrentMillis(void)
-{
- return (unsigned long long)jiffies_to_msecs(jiffies);
-}
-
-
-/**
- * @brief Initializes given list.
- * @param list list to initialize.
- */
-
-static inline void
-CommOS_ListInit(CommOSList *list)
-{
- INIT_LIST_HEAD(list);
-}
-
-
-/**
- * @brief Tests if list is empty.
- * @param list list to test.
- * @return non-zero if empty, zero otherwise.
- */
-
-#define CommOS_ListEmpty(list) list_empty((list))
-
-
-/**
- * @brief Adds given element to beginning of list.
- * @param list list to add to.
- * @param elem element to add.
- */
-
-#define CommOS_ListAdd(list, elem) list_add((elem), (list))
-
-
-/**
- * @brief Adds given element to end of list.
- * @param list list to add to.
- * @param elem element to add.
- */
-
-#define CommOS_ListAddTail(list, elem) list_add_tail((elem), (list))
-
-
-/**
- * @brief Deletes given element from its list.
- * @param elem element to delete.
- */
-
-#define CommOS_ListDel(elem) \
- do { \
- list_del((elem)); \
- INIT_LIST_HEAD((elem)); \
- } while (0)
-
-
-/**
- * @brief Iterates over a list.
- * @param list list to iterate over.
- * @param[out] item stores next element.
- * @param itemListFieldName name in the item structure storing the list head.
- */
-
-#define CommOS_ListForEach(list, item, itemListFieldName) \
- list_for_each_entry((item), (list), itemListFieldName)
-
-
-/**
- * @brief Iterates safely over a list.
- * @param list list to iterate over.
- * @param[out] item stores next element. May be deleted in the loop.
- * @param[out] tmpItem saves iteration element.
- * @param itemListFieldName name in the item structure storing the list head.
- */
-
-#define CommOS_ListForEachSafe(list, item, tmpItem, itemListFieldName) \
- list_for_each_entry_safe((item), (tmpItem), (list), itemListFieldName)
-
-
-/**
- * @brief Combines two lists, adds second list to beginning of first one.
- * @param list list to add to.
- * @param list2 list to add.
- */
-
-#define CommOS_ListSplice(list, list2) list_splice((list2), (list))
-
-
-/**
- * @brief Combines two lists, adds second list to end of first one.
- * @param list list to add to.
- * @param list2 list to add.
- */
-
-#define CommOS_ListSpliceTail(list, list2) list_splice_tail((list2), (list))
-
-
-/**
- * @brief Gets current module handle.
- * @return module handle.
- */
-
-static inline CommOSModule
-CommOS_ModuleSelf(void)
-{
- return THIS_MODULE;
-}
-
-
-/**
- * @brief Retains module.
- * @param[in,out] module to retain.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-CommOS_ModuleGet(CommOSModule module)
-{
- int rc = 0;
-
- if (!module) {
- goto out;
- }
- if (!try_module_get(module)) {
- rc = -1;
- }
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Releases module.
- * @param[in,out] module to release.
- */
-
-static inline void
-CommOS_ModulePut(CommOSModule module)
-{
- if (module) {
- module_put(module);
- }
-}
-
-
-/**
- * @brief Inserts r/w memory barrier.
- */
-
-#define CommOS_MemBarrier smp_mb
-
-#endif /* _COMM_OS_LINUX_H_ */
diff --git a/arch/arm/mvp/mvpkm/comm_transp.h b/arch/arm/mvp/mvpkm/comm_transp.h
deleted file mode 100644
index a90eb40..0000000
--- a/arch/arm/mvp/mvpkm/comm_transp.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Generic shared memory transport API.
- */
-
-#ifndef _COMM_TRANSP_H_
-#define _COMM_TRANSP_H_
-
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/*
- * Common shared memory identifier.
- * External handle that makes sense to both hypervisor and guest.
- */
-
-#define COMM_TRANSP_ID_8_ANY ((unsigned char)-1)
-#define COMM_TRANSP_ID_32_ANY ((unsigned int)-1)
-#define COMM_TRANSP_ID_64_ANY ((unsigned long long)-1)
-
-
-typedef struct CommTranspID {
- union {
- unsigned char d8[8];
- unsigned int d32[2];
- unsigned long long d64;
- };
-} CommTranspID;
-
-
-/* Basic initialization arguments. */
-
-typedef enum CommTranspInitMode {
- COMM_TRANSP_INIT_CREATE = 0x0,
- COMM_TRANSP_INIT_ATTACH = 0x1
-} CommTranspInitMode;
-
-typedef struct CommTranspInitArgs {
- unsigned int capacity; // Shared memory capacity.
- unsigned int type; // Type / implementation using this area.
- CommTranspID id; // ID (name) of shared memory area.
- CommTranspInitMode mode; // Init mode (above).
-} CommTranspInitArgs;
-
-
-/**
- * @brief Generate a type id from description (protocol) string. This function
- * uses djb2, a string hashing algorithm by Dan Bernstein.
- * (see http://www.cse.yorku.ca/~oz/hash.html)
- * @param str string to hash
- * @return 32-bit hash value
- */
-
-static inline unsigned int
-CommTransp_GetType(const char *str)
-{
- unsigned int hash = 5381;
- int c;
-
- while ((c = *str++)) {
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
- }
- return hash;
-}
-
-#endif // _COMM_TRANSP_H_
diff --git a/arch/arm/mvp/mvpkm/comm_transp_impl.h b/arch/arm/mvp/mvpkm/comm_transp_impl.h
deleted file mode 100644
index 6438ac9..0000000
--- a/arch/arm/mvp/mvpkm/comm_transp_impl.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Generic shared memory transport private API.
- */
-
-#ifndef _COMM_TRANSP_IMPL_H_
-#define _COMM_TRANSP_IMPL_H_
-
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "comm_transp.h"
-
-
-/* Shared memory opaque descriptor/handle. Only meaningful locally. */
-
-typedef struct CommTranspPriv *CommTransp;
-
-
-/* Asynchronous signaling initialization arguments. */
-
-typedef enum CommTranspIOEvent {
- COMM_TRANSP_IO_DETACH = 0x0,
- COMM_TRANSP_IO_IN = 0x1,
- COMM_TRANSP_IO_OUT = 0x2,
- COMM_TRANSP_IO_INOUT = 0x3
-} CommTranspIOEvent;
-
-typedef struct CommTranspEvent {
- void (*ioEvent)(CommTransp transp, CommTranspIOEvent event, void *data);
- void *ioEventData;
-} CommTranspEvent;
-
-
-/*
- * Mechanism to detect and optionally attach to, created shared memory regions.
- */
-
-typedef struct CommTranspListener {
- int (*probe)(CommTranspInitArgs *transpArgs, void *probeData);
- void *probeData;
-} CommTranspListener;
-
-
-
-/*
- * Function prototypes.
- */
-
-int CommTranspEvent_Init(void);
-void CommTranspEvent_Exit(void);
-int CommTranspEvent_Process(CommTranspID *transpID, CommTranspIOEvent event);
-int
-CommTranspEvent_Raise(unsigned int peerEvID,
- CommTranspID *transpID,
- CommTranspIOEvent event);
-
-int CommTransp_Init(void);
-void CommTransp_Exit(void);
-
-int CommTransp_Register(const CommTranspListener *listener);
-void CommTransp_Unregister(const CommTranspListener *listener);
-int
-CommTransp_Notify(const CommTranspID *notificationCenterID,
- CommTranspInitArgs *transpArgs);
-
-int
-CommTransp_Open(CommTransp *transp,
- CommTranspInitArgs *transpArgs,
- CommTranspEvent *transpEvent);
-void CommTransp_Close(CommTransp transp);
-
-int CommTransp_EnqueueSpace(CommTransp transp);
-int CommTransp_EnqueueReset(CommTransp transp);
-int CommTransp_EnqueueCommit(CommTransp transp);
-int
-CommTransp_EnqueueSegment(CommTransp transp,
- const void *buf,
- unsigned int bufLen);
-
-int CommTransp_DequeueSpace(CommTransp transp);
-int CommTransp_DequeueReset(CommTransp transp);
-int CommTransp_DequeueCommit(CommTransp transp);
-int
-CommTransp_DequeueSegment(CommTransp transp,
- void *buf,
- unsigned int bufLen);
-
-unsigned int CommTransp_RequestInlineEvents(CommTransp transp);
-unsigned int CommTransp_ReleaseInlineEvents(CommTransp transp);
-
-
-/**
- * @brief Enqueues data into the transport object, data is available for
- * reading immediately.
- * @param transp handle to the transport object.
- * @param buf bytes to enqueue.
- * @param bufLen number of bytes to enqueue.
- * @return number of bytes enqueued on success, < 0 otherwise.
- */
-
-static inline int
-CommTransp_EnqueueAtomic(CommTransp transp,
- const void *buf,
- unsigned int bufLen)
-{
- int rc;
-
- CommTransp_EnqueueReset(transp);
- rc = CommTransp_EnqueueSegment(transp, buf, bufLen);
- if (CommTransp_EnqueueCommit(transp)) {
- rc = -1;
- }
- return rc;
-}
-
-
-/**
- * @brief Dequeues data from the transport object into a buffer.
- * @param transp handle to the transport object.
- * @param[out] buf buffer to copy to.
- * @param bufLen number of bytes to dequeue.
- * @return number of bytes dequeued on success, < 0 otherwise,
- */
-
-static inline int
-CommTransp_DequeueAtomic(CommTransp transp,
- void *buf,
- unsigned int bufLen)
-{
- int rc;
-
- CommTransp_DequeueReset(transp);
- rc = CommTransp_DequeueSegment(transp, buf, bufLen);
- if (CommTransp_DequeueCommit(transp)) {
- rc = -1;
- }
- return rc;
-}
-
-#endif // _COMM_TRANSP_IMPL_H_
diff --git a/arch/arm/mvp/mvpkm/coproc_defs.h b/arch/arm/mvp/mvpkm/coproc_defs.h
deleted file mode 100644
index 26218cf..0000000
--- a/arch/arm/mvp/mvpkm/coproc_defs.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Constant definitions for ARM CP15 coprocessor registers.
- *
- * Derived from tweety hypervisor/src/armv6/trango_macros.inc file
- */
-
-#ifndef _COPROC_DEFS_H_
-#define _COPROC_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @name CP10 registers.
- *
- * MCR/MRC format: @code #define <name> <opcode_1>, <CRn>, <CRm>, <opcode_2> @endcode
- * @{
- */
-#define VFP_FPSID 7, c0, c0, 0
-#define VFP_MVFR0 7, c7, c0, 0
-#define VFP_MVFR1 7, c6, c0, 0
-#define VFP_FPEXC 7, c8, c0, 0
-#define VFP_FPSCR 7, c1, c0, 0
-#define VFP_FPINST 7, c9, c0, 0
-#define VFP_FPINST2 7, c10, c0, 0
-/*@}*/
-
-
-/**
- * @name CP15 registers.
- *
- * MCR/MRC format: @code #define <name> <opcode_1>, <CRn>, <CRm>, <opcode_2> @endcode
- * MCRR format: @code #define <name> <opcode>, <CRm>@endcode
- * @{
- */
-#define ID_CODE 0, c0, c0, 0
-#define CACHE_TYPE 0, c0, c0, 1
-#define MPIDR 0, c0, c0, 5
-#define CACHE_SIZE_ID 1, c0, c0, 0
-#define CACHE_LEVEL_ID 1, c0, c0, 1
-#define CACHE_SIZE_SELECTION 2, c0, c0, 0
-#define MEM_MODEL_FEATURE_0 0, c0, c1, 4
-#define CONTROL_REGISTER 0, c1, c0, 0
-#define TTBASE0_POINTER 0, c2, c0, 0
-#define TTBASE1_POINTER 0, c2, c0, 1
-#define TTCONTROL 0, c2, c0, 2
-#define DOMAIN_CONTROL 0, c3, c0, 0
-#define DATA_FAULT_STATUS 0, c5, c0, 0
-#define INST_FAULT_STATUS 0, c5, c0, 1
-#define AUX_DATA_FAULT_STATUS 0, c5, c1, 0
-#define AUX_INST_FAULT_STATUS 0, c5, c1, 1
-#define DATA_FAULT_ADDRESS 0, c6, c0, 0
-#define INST_FAULT_ADDRESS 0, c6, c0, 2
-#define WAIT_FOR_INTERRUPT 0, c7, c0, 4
-#define PHYSICAL_ADDRESS 0, c7, c4, 0
-#define ICACHE_INVALIDATE_POU 0, c7, c5, 0
-#define ICACHE_INVALIDATE_MVA_POU 0, c7, c5, 1
-#define ICACHE_INVALIDATE_INDEX 0, c7, c5, 2
-#define BTAC_INVALIDATE 0, c7, c5, 6
-#define BTAC_INVALIDATE_MVA 0, c7, c5, 7
-#define DCACHE_INVALIDATE 0, c7, c6, 0
-#define DCACHE_INVALIDATE_MVA_POC 0, c7, c6, 1
-#define DCACHE_INVALIDATE_INDEX 0, c7, c6, 2
-#define UCACHE_INVALIDATE 0, c7, c7, 0
-#define V2P_CURRENT_PRIV_READ 0, c7, c8, 0
-#define V2P_CURRENT_PRIV_WRITE 0, c7, c8, 1
-#define V2P_CURRENT_USER_READ 0, c7, c8, 2
-#define V2P_CURRENT_USER_WRITE 0, c7, c8, 3
-#define V2P_OTHER_PRIV_READ 0, c7, c8, 4
-#define V2P_OTHER_PRIV_WRITE 0, c7, c8, 5
-#define V2P_OTHER_USER_READ 0, c7, c8, 6
-#define V2P_OTHER_USER_WRITE 0, c7, c8, 7
-#define DCACHE_CLEAN 0, c7, c10, 0
-#define DCACHE_CLEAN_MVA_POC 0, c7, c10, 1
-#define DCACHE_CLEAN_INDEX 0, c7, c10, 2
-#define DCACHE_CLEAN_MVA_POU 0, c7, c11, 1
-#define DCACHE_CLEAN_INVALIDATE 0, c7, c14, 0
-#define DCACHE_CLEAN_INVALIDATE_MVA_POC 0, c7, c14, 1
-#define DCACHE_CLEAN_INVALIDATE_INDEX 0, c7, c14, 2
-#define ITLB_INVALIDATE_ALL 0, c8, c5, 0
-#define ITLB_INVALIDATE_SINGLE 0, c8, c5, 1
-#define ITLB_INVALIDATE_ASID 0, c8, c5, 2
-#define DTLB_INVALIDATE_ALL 0, c8, c6, 0
-#define DTLB_INVALIDATE_SINGLE 0, c8, c6, 1
-#define DTLB_INVALIDATE_ASID 0, c8, c6, 2
-#define UTLB_INVALIDATE_ALL 0, c8, c7, 0
-#define UTLB_INVALIDATE_SINGLE 0, c8, c7, 1
-#define UTLB_INVALIDATE_ASID 0, c8, c7, 2
-#define TLB_LOCKDOWN 0, c10, c0, 0
-#define PRIMARY_REGION_REMAP 0, c10, c2, 0
-#define MAIR0 PRIMARY_REGION_REMAP
-#define NORMAL_MEMORY_REMAP 0, c10, c2, 1
-#define MAIR1 NORMAL_MEMORY_REMAP
-#define VECTOR_BASE 0, c12, c0, 0
-#define INTERRUPT_STATUS 0, c12, c1, 0
-#define CONTEXT_ID 0, c13, c0, 1
-#define TID_USER_RW 0, c13, c0, 2
-#define TID_USER_RO 0, c13, c0, 3
-#define TID_PRIV_RW 0, c13, c0, 4
-#define CLEAR_FAULT_IN_EFSR 7, c15, c0, 1
-#define VBAR 0, c12, c0, 0
-
-/*
- * ARMv7 performance counters' registers (MVP related)
- * - ARM Architecture Reference Manual v7-A and v7-R: DDI0406B
- * - Cortex-A8 TRM, rev.r1p1: DDI0344B
- */
-#define PERF_MON_CONTROL_REGISTER 0, c9, c12, 0
-#define CYCLE_COUNT 0, c9, c13, 0
-#define PERF_MON_COUNT_SET 0, c9, c12, 1
-#define PERF_MON_COUNT_CLR 0, c9, c12, 2
-#define PERF_MON_FLAG_RDCLR 0, c9, c12, 3
-#define PERF_MON_EVENT_SELECT 0, c9, c12, 5
-#define PERF_MON_EVENT_TYPE 0, c9, c13, 1
-#define PERF_MON_EVENT_COUNT 0, c9, c13, 2
-#define PERF_MON_INTEN_SET 0, c9, c14, 1
-#define PERF_MON_INTEN_CLR 0, c9, c14, 2
-
-#define COPROC_ACCESS_CONTROL 0, c1, c0, 2
-#define NON_SECURE_ACCESS_CONTROL 0, c1, c1, 2
-
-#define HYP_CFG 4, c1, c1, 0
-#define HYP_DEBUG_CONTROL 4, c1, c1, 1
-#define HYP_COPROC_TRAP 4, c1, c1, 2
-#define HYP_SYS_TRAP 4, c1, c1, 3
-#define VIRT_TCR 4, c2, c1, 2
-#define HYP_SYNDROME 4, c5, c2, 0
-#define HYP_DATA_FAULT_ADDRESS 4, c6, c0, 0
-#define HYP_INST_FAULT_ADDRESS 4, c6, c0, 2
-#define HYP_IPA_FAULT_ADDRESS 4, c6, c0, 4
-#define UTLB_INVALIDATE_ALL_HYP 4, c8, c7, 0
-#define UTLB_INVALIDATE_SINGLE_HYP 4, c8, c7, 1
-#define UTLB_INVALIDATE_ALL_NS_NON_HYP 4, c8, c7, 4
-
-#define EXT_TTBR0 0, c2
-#define EXT_TTBR1 1, c2
-#define HYP_TTBR 4, c2
-#define VIRT_TTBR 6, c2
-#define EXT_PHYSICAL_ADDRESS 0, c7
-/*@}*/
-
-/**
- * @name CP15 configuration control register bits.
- * @{
- */
-#define ARM_CP15_CNTL_M (1 << 0)
-#define ARM_CP15_CNTL_A (1 << 1)
-#define ARM_CP15_CNTL_C (1 << 2)
-#define ARM_CP15_CNTL_B (1 << 7)
-#define ARM_CP15_CNTL_Z (1 << 11)
-#define ARM_CP15_CNTL_I (1 << 12)
-#define ARM_CP15_CNTL_V (1 << 13)
-#define ARM_CP15_CNTL_U (1 << 22)
-#define ARM_CP15_CNTL_VE (1 << 24)
-#define ARM_CP15_CNTL_EE (1 << 25)
-#define ARM_CP15_CNTL_TRE (1 << 28)
-#define ARM_CP15_CNTL_AFE (1 << 29)
-#define ARM_CP15_CNTL_TE (1 << 30)
-
-/*@}*/
-
-/**
- * @brief Initial System Control Register (SCTLR) value.
- *
- * Magic described on B3-97 ARM DDI 0406B, it's the power-on
- * value, e.g. caches/MMU/alignment checking/TEX remap etc. disabled.
- */
-#define ARM_CP15_CNTL_INIT 0x00c50078
-
-/**
- * @name System control coprocessor primary registers.
- * Each primary register is backed by potentially multiple
- * physical registers in the vCPU CP15 register file.
- * @{
- */
-#define ARM_CP15_CRN_ID 0 ///< Processor ID, cache, TCM and TLB type
-#define ARM_CP15_CRN_CNTL 1 ///< System configuration bits
-#define ARM_CP15_CRN_PT 2 ///< Page table control
-#define ARM_CP15_CRN_DACR 3 ///< Domain access control
-#define ARM_CP15_CRN_F_STATUS 5 ///< Fault status
-#define ARM_CP15_CRN_F_ADDR 6 ///< Fault address
-#define ARM_CP15_CRN_CACHE 7 ///< Cache/write buffer control
-#define ARM_CP15_CRN_TLB 8 ///< TLB control
-#define ARM_CP15_CRN_REMAP 10 ///< Memory Remap registers
-#define ARM_CP15_CRN_SER 12 ///< Security Extension registers
-#define ARM_CP15_CRN_PID 13 ///< Process ID
-#define ARM_CP15_CRN_TIMER 14 ///< Architecture timers
-
-#define ARM_CP15_CRM_INVALIDATE_D_CACHE_RANGE 6
-#define ARM_CP15_CRM_CLEAN_AND_INVALIDATE_D_CACHE_RANGE 14
-/*@}*/
-
-/**
- * @name ARMv7 performance counter control/status register bits (MVP related)
- * INTEN: counters overflow interrupt enable
- * CNTEN: counters enable
- * @{
- */
-#define ARMV7_PMNC_E (1 << 0)
-#define ARMV7_PMNC_INTEN_P0 (1 << 0)
-#define ARMV7_PMNC_INTEN_P1 (1 << 1)
-#define ARMV7_PMNC_INTEN_P2 (1 << 2)
-#define ARMV7_PMNC_INTEN_P3 (1 << 3)
-#define ARMV7_PMNC_INTEN_C (1 << 31)
-#define ARMV7_PMNC_INTEN_MASK 0x8000000f
-#define ARMV7_PMNC_CNTEN_P0 (1 << 0)
-#define ARMV7_PMNC_CNTEN_P1 (1 << 1)
-#define ARMV7_PMNC_CNTEN_P2 (1 << 2)
-#define ARMV7_PMNC_CNTEN_P3 (1 << 3)
-#define ARMV7_PMNC_CNTEN_C (1 << 31)
-#define ARMV7_PMNC_FLAG_P0 (1 << 0)
-#define ARMV7_PMNC_FLAG_P1 (1 << 1)
-#define ARMV7_PMNC_FLAG_P2 (1 << 2)
-#define ARMV7_PMNC_FLAG_P3 (1 << 3)
-#define ARMV7_PMNC_FLAG_C (1 << 31)
-/*@}*/
-
-/**
- * @name TTBR masks.
- * See B4.9.2 ARM DDI 0100I and B3.12.24 ARM DDI 0406A.
- * @{
- */
-#define ARM_CP15_TTBASE_MASK MVP_MASK(14, 18)
-#define ARM_CP15_TTBASE_SPLIT_MASK(ttbcrn) MVP_MASK(14-ttbcrn, 18+ttbcrn)
-#define ARM_CP15_TTATTRIB_MASK MVP_MASK(0, 6)
-/*@}*/
-
-/**
- * @name ARM fault status register encoding/decoding.
- * See B4.6 and B4.9.6 in ARM DDI 0100I.
- * @{
- */
-#define ARM_CP15_FSR_STATUS_POS 0
-#define ARM_CP15_FSR_STATUS_POS2 10
-#define ARM_CP15_FSR_DOMAIN_POS 4
-#define ARM_CP15_FSR_WR_POS 11
-
-#define ARM_CP15_FSR_STATUS_LEN 4
-#define ARM_CP15_FSR_DOMAIN_LEN 4
-
-#define ARM_CP15_FSR_STATUS_DEBUG_EVENT 0x2
-#define ARM_CP15_FSR_STATUS_ALIGNMENT 0x1
-#define ARM_CP15_FSR_STATUS_ICACHE_MAINT 0x4
-#define ARM_CP15_FSR_STATUS_TRANSLATION_SECT 0x5
-#define ARM_CP15_FSR_STATUS_TRANSLATION_PAGE 0x7
-#define ARM_CP15_FSR_STATUS_DOMAIN_SECT 0x9
-#define ARM_CP15_FSR_STATUS_DOMAIN_PAGE 0xb
-#define ARM_CP15_FSR_STATUS_PERMISSION_SECT 0xd
-#define ARM_CP15_FSR_STATUS_PERMISSION_PAGE 0xf
-#define ARM_CP15_FSR_STATUS_ACCESS_FLAG_SECT 0x3
-#define ARM_CP15_FSR_STATUS_ACCESS_FLAG_PAGE 0x6
-#define ARM_CP15_FSR_STATUS_SYNC_EXT_ABORT 0x8
-#define ARM_CP15_FSR_STATUS_ASYNC_EXT_ABORT 0x16
-/*@}*/
-
-/**
- * @brief Generate ARM fault status register value.
- *
- * @param fs status from Table B4-1. Only implemented for fs <= 0xf.
- * @param domain domain accessed when abort occurred.
- * @param write write access caused abort.
- */
-#define ARM_CP15_FSR(fs,domain,write) \
- (((fs) << ARM_CP15_FSR_STATUS_POS) | \
- ((domain) << ARM_CP15_FSR_DOMAIN_POS) | \
- ((write) ? (1 << ARM_CP15_FSR_WR_POS) : 0))
-
-#define ARM_CP15_FSR_STATUS(r) \
- (MVP_EXTRACT_FIELD((r), ARM_CP15_FSR_STATUS_POS, ARM_CP15_FSR_STATUS_LEN) | \
- (MVP_BIT((r), ARM_CP15_FSR_STATUS_POS2) << ARM_CP15_FSR_STATUS_LEN))
-#define ARM_CP15_FSR_DOMAIN(r) \
- MVP_EXTRACT_FIELD((r), ARM_CP15_FSR_DOMAIN_POS, ARM_CP15_FSR_DOMAIN_LEN)
-#define ARM_CP15_FSR_WR(r) \
- MVP_BIT((r), ARM_CP15_FSR_WR_POS)
-/*@}*/
-
-/*
- * This should mask out the major and minor revision numbers.
- * As per http://infocenter.arm.com/help/topic/com.arm.doc.ddi0211k/I65012.html
- */
-#define ARM_CP15_MAIN_ID_NOREVISION_MASK 0xFF0FFFF0
-
-// 2-8 ARM DDI 0151C
-#define ARM_CP15_MAIN_ID_920_T 0x41129200
-// 3-18 ARM DDI 0211H
-#define ARM_CP15_MAIN_ID_1136J_S 0x4107B362
-
-/* Coprocessor Access Control Register */
-#define CPACR_ASEDIS (1 << 31)
-#define CPACR_D32DIS (1 << 30)
-#define CPACR_CP10_MASK (0x3 << (10*2))
-#define CPACR_CP10_CP11_MASK ( (0x3 << (10*2)) | (0x3 << (11*2)) )
-#define CPACR_CP10_CP11_PRIV_ONLY ( (0x1 << (10*2)) | (0x1 << (11*2)) )
- /* 2-bit access permission per Co-Proc */
-
-/**
- * @name ARM VFP/Adv. SIMD Extension System Registers
- * @{
- */
-#define ARM_VFP_SYSTEM_REG_FPSID 0x0
-#define ARM_VFP_SYSTEM_REG_FPSCR 0x1
-#define ARM_VFP_SYSTEM_REG_MVFR1 0x6
-#define ARM_VFP_SYSTEM_REG_MVFR0 0x7
-#define ARM_VFP_SYSTEM_REG_FPEXC 0x8
-#define ARM_VFP_SYSTEM_REG_FPINST 0x9
-#define ARM_VFP_SYSTEM_REG_FPINST2 0xa
-
-#define ARM_VFP_SYSTEM_REG_FPEXC_EX (1 << 31)
-#define ARM_VFP_SYSTEM_REG_FPEXC_EN (1 << 30)
-#define ARM_VFP_SYSTEM_REG_FPEXC_FP2V (1 << 28)
-
-#define ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_BIT (0)
-#define ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK (0xf << ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_BIT)
-/*@}*/
-
-/**
- * @name ARM Multi Processor ID Register (MPIDR) decoding
- * @{
- */
-#define ARM_CP15_MPIDR_MP (0x1 << 31)
-#define ARM_CP15_MPIDR_U (0x1 << 30)
-/*@}*/
-
-#endif /// ifndef _COPROC_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/cpufreq_kernel.c b/arch/arm/mvp/mvpkm/cpufreq_kernel.c
deleted file mode 100644
index 4ba71f2..0000000
--- a/arch/arm/mvp/mvpkm/cpufreq_kernel.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP host kernel cpufreq related
- *
- * Track CPU frequency changes.
- */
-
-#include <linux/module.h>
-#include <linux/notifier.h>
-#include <linux/cpu.h>
-#include <linux/cpufreq.h>
-#include <linux/rwsem.h>
-#include <linux/smp.h>
-
-#include "mvp.h"
-#include "cpufreq_kernel.h"
-#include "mvp_timer.h"
-
-DEFINE_PER_CPU(struct TscToRate64Cb, tscToRate64);
-
-
-/**
- * @brief Return current CPU frequency
- * @param cpu CPU number
- * @return CPU frequency in Hz
- *
- * When CPU_FREQ is not available, it uses hardcoded frequencies.
- */
-static uint32
-GetCpuFrequency(unsigned int cpu)
-{
- unsigned int counterKHZ;
-
-#ifdef CONFIG_CPU_FREQ
- counterKHZ = cpufreq_quick_get(cpu);
- if (counterKHZ == 0) {
- counterKHZ = cpufreq_get(cpu);
- FATAL_IF(counterKHZ == 0);
- }
-#elif defined(MVP_HOST_BOARD_ve)
- /**
- * @knownjira{MVP-143}
- * We're only using this under the simulator, and it's almost non perceptible to
- * provide a fixed TSC frequency as the instructions / second executed widely
- * varies depending over time. While we resolve this issue we can use the
- * BogoMIPS reported at boot for now.
- */
- KNOWN_BUG(MVP-143);
- counterKHZ = 125e3;
- printk(KERN_INFO "mvpkm: CPU_FREQ not available, forcing TSC to %d KHz\n", counterKHZ);
-#elif defined(MVP_HOST_BOARD_panda)
- counterKHZ = 1e6;
-#else
- /*
- * If the kernel can't tell us and we have no further host knowledge,
- * time to die.
- */
-#error "host TSC frequency unknown."
-#endif
-
- return counterKHZ * 1000;
-}
-
-/**
- * @brief Compute TSC to RATE64 ratio
- * @param cpuFreq TSC frequency in Hz
- * @param[out] ttr tscToRate64 pointer
- */
-static void
-TscToRate64(uint32 cpuFreq, struct TscToRate64Cb *ttr)
-{
- uint32 shift;
- uint64 mult;
-
- /*
- * A little bit of math !
- *
- * We need here to convert the TSC value to our RATE64 timebase.
- *
- * In other words:
- *
- * tsc * MVP_TIMER_RATE64
- * rate64 = ----------------------
- * cpuFreq
- *
- * But we are limited by CPU performance (does not divide easily), CPU
- * instruction set, and CPU register file width. To fit performance
- * requirement, the math becomes:
- *
- * rate64 = (cpuFreq * mult) >> shift
- *
- * To respect instruction set, both cpuFreq and mult must be 32-bit
- * numbers. Thus (cpuFreq * mult) will be a 64-bit number.
- *
- *
- * Log2 rate64 = Log2 cpuFreq + Log2 mult - shift
- *
- * shift = Log2 mult + Log2 cpuFreq - Log2 rate64
- *
- * && Log2 mult < 32
- *
- * => shift < 32 + Log2 cpuFreq - Log2 rate64
- *
- * rate64 << shift
- * => mult = ---------------
- * cpuFreq
- *
- * (rate64 << shift) must be a 64-bit number:
- *
- * Log2 rate64 + shift < 64
- *
- * => shift < 64 - Log2 rate64
- *
- * While cpuFreq is lower than 2^32 Hz, we have:
- *
- * shift < 32 + Log2 cpuFreq - Log2 rate64 < 64 - Log2 rate64
- *
- * As (31 - CLZ32 x) <= Log2 x < (32 - CLZ32 x):
- *
- * 31 - CLZ32 cpuFreq <= Log2 cpuFreq &&
- *
- * CLZ32 rate64 - 32 < - Log2 rate64
- *
- * 31 + CLZ32 rate64 - CLZ32 cpuFreq < 32 + Log2 cpuFreq - Log2 rate64
- *
- * As we want shift to be as great as possible:
- *
- * => shift = 31 + CLZ32 rate64 - CLZ32 cpuFreq
- *
- * rate64 << shift
- * && mult = ---------------
- * cpuFreq
- *
- *
- */
-
- /* CLZ(MVP_TIMER_RATE64) is optimized by compiler in a constant */
- shift = 31 + CLZ(MVP_TIMER_RATE64) - CLZ(cpuFreq);
- mult = MVP_TIMER_RATE64;
- mult <<= shift;
- do_div(mult, cpuFreq);
-
- /* verify Log2 mult < 32 */
- ASSERT(mult < (1ULL<<32));
-
- /* update global variables */
- ttr->mult = mult;
- ttr->shift = shift;
-}
-
-/**
- * @brief Compute TSC to RATE64 ratio for the current cpu
- * @param info TSC frequency in Hz
- * @sideeffect Update local cpu tscToRate64
- */
-static void
-TscToRate64IPI(void *info)
-{
- uint32 cpuFreq = (uint32)info;
-
- TscToRate64(cpuFreq, &__get_cpu_var(tscToRate64));
-}
-
-/**
- * @brief Handle cpufreq transition notifications.
- * @param nb Notifier block
- * @param val Notified event
- * @param data Linux cpufreq_freqs info
- * @return NOTIFY_OK
- *
- * @note A frequency change can fail in which case PRECHANGE and POSTCHANGE
- * will not be paired and you get any number of PRECHANGE and maybe never a
- * POSTCHANGE (i.e. there is not enough battery voltage available to support a
- * high frequency).
- * @note This is called once per cpu core that is changing but not always on
- * the core that is changing.
- */
-static int
-CpuFreqNotifier(struct notifier_block *nb,
- unsigned long val,
- void *data)
-{
- struct cpufreq_freqs *freq = data;
- bool updateRequired;
-
- /* ASSUMPTION: Only freq. increases can fail and that it is ok to tell the
- * guest a higher frequency than it really is but not the other way around
- * as that just leads to time "jumping" forward in the guest not backwards.
- */
- updateRequired = (val == CPUFREQ_PRECHANGE && freq->new > freq->old) ||
- (val == CPUFREQ_POSTCHANGE && freq->new < freq->old);
-
- /* Call TscToRate64() on the correct CPU core so that locking is not
- * required. This also has the side-effect of forcing any currently running
- * vCPU's to worldswitch back to the host and correctly update the world
- * switch page.
- */
- if (updateRequired) {
- uint32 hz = freq->new * 1000;
- smp_call_function_single(freq->cpu, TscToRate64IPI, (void *)hz, false);
- }
-
- return NOTIFY_OK;
-}
-
-/**
- * @brief Notifier block for cpufreq transitions
- */
-static struct notifier_block cpuFreqNotifierBlock = {
- .notifier_call = CpuFreqNotifier
-};
-
-/**
- * @brief Handle cpuUp notifications.
- * @param nb Notifier block
- * @param action Notified action, e.g., CPU_ONLINE
- * @param hcpu cpu no
- * @return NOTIFY_OK
- */
-static int
-CpuUpNotifier(struct notifier_block *nb,
- unsigned long action,
- void *hcpu)
-{
- long cpu = (long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- /* The new CPU core is not yet executing normal tasks, so it is safe
- * to update it's scaling factors from a different core. */
- TscToRate64(GetCpuFrequency(cpu), &per_cpu(tscToRate64, cpu));
- break;
- default:
- /*
- * Ignore all other action notifications,
- * such as CPU_UP_PREPARE, CPU_UP_CANCELED,
- * CPU_DOWN_PREPARE, CPU_DOWN_FAILED,
- * CPU_DYING, CPU_DEAD, CPU_POST_DEAD, etc.
- * as they are irrelevant here.
- */
- break;
- }
-
- return NOTIFY_OK;
-}
-
-/**
- * @brief Notifier block for cpus going online
- */
-static struct notifier_block cpuUpNotifierBlock = {
- .notifier_call = CpuUpNotifier
-};
-
-/**
- * @brief Initialize TSC ratio and register cpufreq transitions.
- */
-void
-CpuFreq_Init(void)
-{
- int ret;
- int cpu;
-
- /* register callback on frequency change */
- ret = cpufreq_register_notifier(&cpuFreqNotifierBlock,
- CPUFREQ_TRANSITION_NOTIFIER);
- FATAL_IF(ret < 0);
-
- /* register callback on cpu core online */
- ret = register_cpu_notifier(&cpuUpNotifierBlock);
- FATAL_IF(ret < 0);
-
- /* Make sure that things are correctly initialized. */
- for_each_online_cpu(cpu) {
- TscToRate64(GetCpuFrequency(cpu), &per_cpu(tscToRate64, cpu));
- }
-}
-
-/**
- * @brief Exit cpufreq, unregister cpufreq transitions
- */
-void
-CpuFreq_Exit(void)
-{
- cpufreq_unregister_notifier(&cpuFreqNotifierBlock,
- CPUFREQ_TRANSITION_NOTIFIER);
- unregister_cpu_notifier(&cpuUpNotifierBlock);
-}
diff --git a/arch/arm/mvp/mvpkm/cpufreq_kernel.h b/arch/arm/mvp/mvpkm/cpufreq_kernel.h
deleted file mode 100644
index a84b6dd..0000000
--- a/arch/arm/mvp/mvpkm/cpufreq_kernel.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The monitor-kernel socket interface kernel-only definitions.
- */
-
-#ifndef _CPUFREQ_KERNEL_H
-#define _CPUFREQ_KERNEL_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/* Scaling factors to convert CPU clock cycles to Rate64 value */
-struct TscToRate64Cb {
- uint32 mult;
- uint32 shift;
-};
-
-/* It is assumed that this is only accessed from the current CPU core and not
- * "across cores" */
-DECLARE_PER_CPU(struct TscToRate64Cb, tscToRate64);
-
-void CpuFreq_Init(void);
-void CpuFreq_Exit(void);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/exc_defs.h b/arch/arm/mvp/mvpkm/exc_defs.h
deleted file mode 100644
index 1d5d063..0000000
--- a/arch/arm/mvp/mvpkm/exc_defs.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Exception-related definitions. See A2.6 ARM DDI 0100I.
- */
-
-#ifndef _EXC_DEFS_H_
-#define _EXC_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define EXC_VECTOR_SIZE 0x20
-
-#define EXC_RESET_VECTOR_OFFSET 0x00
-#define EXC_UNDEFINED_VECTOR_OFFSET 0x04
-#define EXC_SWI_VECTOR_OFFSET 0x08
-#define EXC_PREFETCH_ABORT_VECTOR_OFFSET 0x0c
-#define EXC_DATA_ABORT_VECTOR_OFFSET 0x10
-#define EXC_HYP_VECTOR_OFFSET 0x14
-#define EXC_IRQ_VECTOR_OFFSET 0x18
-#define EXC_FIQ_VECTOR_OFFSET 0x1c
-
-#define EXC_ARM_UNDEFINED_SAVED_PC_OFFSET 4
-#define EXC_ARM_SWI_SAVED_PC_OFFSET 4
-#define EXC_ARM_PREFETCH_ABORT_SAVED_PC_OFFSET 4
-#define EXC_ARM_DATA_ABORT_SAVED_PC_OFFSET 8
-#define EXC_ARM_IRQ_SAVED_PC_OFFSET 4
-#define EXC_ARM_FIQ_SAVED_PC_OFFSET 4
-
-#define EXC_THUMB_UNDEFINED_SAVED_PC_OFFSET 2
-#define EXC_THUMB_SWI_SAVED_PC_OFFSET 2
-#define EXC_THUMB_PREFETCH_ABORT_SAVED_PC_OFFSET 4
-#define EXC_THUMB_DATA_ABORT_SAVED_PC_OFFSET 8
-#define EXC_THUMB_IRQ_SAVED_PC_OFFSET 4
-#define EXC_THUMB_FIQ_SAVED_PC_OFFSET 4
-
-#define EXC_SAVED_PC_OFFSET(exc, cpsr) \
- (((cpsr) & ARM_PSR_T) ? EXC_THUMB_##exc##_SAVED_PC_OFFSET : \
- EXC_ARM_##exc##_SAVED_PC_OFFSET)
-
-#endif /// _EXC_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/exc_types.h b/arch/arm/mvp/mvpkm/exc_types.h
deleted file mode 100644
index ba835e5..0000000
--- a/arch/arm/mvp/mvpkm/exc_types.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Exception-related types. See A2.6 ARM DDI 0100I.
- */
-
-#ifndef _EXC_TYPES_H_
-#define _EXC_TYPES_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @brief ARM hardware exception enumeration. EXC_NONE is added to provide
- * a distinguished value to flag non-exception states.
- */
-typedef enum {
- EXC_NONE,
- EXC_RESET,
- EXC_UNDEFINED,
- EXC_SWI,
- EXC_PREFETCH_ABORT,
- EXC_DATA_ABORT,
- EXC_IRQ,
- EXC_FIQ
-} ARM_Exception;
-
-#endif /// _EXC_TYPES_H_
diff --git a/arch/arm/mvp/mvpkm/exitstatus.h b/arch/arm/mvp/mvpkm/exitstatus.h
deleted file mode 100644
index c53827a..0000000
--- a/arch/arm/mvp/mvpkm/exitstatus.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Exit Status values
- */
-
-#ifndef _EXITSTATUS_H
-#define _EXITSTATUS_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_HOSTUSER
-#include "include_check.h"
-
-
-#define _EXIT_STATUS_DEF \
- _EXIT_STATUS_ITEM(Success, 0) \
- _EXIT_STATUS_ITEM(ReturnToHost, 1) \
- _EXIT_STATUS_ITEM(GuestExit, 2) \
- _EXIT_STATUS_ITEM(HostRequest, 3) \
- _EXIT_STATUS_ITEM(VMXFatalError, 4) \
- _EXIT_STATUS_ITEM(VMMFatalError, 5) \
- _EXIT_STATUS_ITEM(MVPDFatalError, 6) \
- _EXIT_STATUS_ITEM(VPNFatalError, 7) \
- _EXIT_STATUS_ITEM(VMXFindCause, 8)
-
-
-enum ExitStatus {
-#define _EXIT_STATUS_ITEM(name,num) ExitStatus##name = num,
-_EXIT_STATUS_DEF
-#undef _EXIT_STATUS_ITEM
-};
-
-typedef enum ExitStatus ExitStatus;
-
-#ifndef __cplusplus
-static const char * ExitStatusName[] UNUSED = {
-#define _EXIT_STATUS_ITEM(name,num) [ExitStatus##name] = #name,
-_EXIT_STATUS_DEF
-#undef _EXIT_STATUS_ITEM
-};
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/fatalerror.h b/arch/arm/mvp/mvpkm/fatalerror.h
deleted file mode 100644
index 58e1f98..0000000
--- a/arch/arm/mvp/mvpkm/fatalerror.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief fatal error handlers. They all post fatal errors regardless of build
- * type.
- */
-
-#ifndef _FATALERROR_H
-#define _FATALERROR_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mvp_compiler.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum FECode {
- FECodeMisc, ///< generic FATAL() call of sorts
- FECodeOOM, ///< FATAL_OOM() call of sorts
- FECodeAssert, ///< ASSERT() call of sorts
- FECodeNR, ///< NOT_REACHED() call of sorts
- FECodeNI, ///< NOT_IMPLEMENTED() call of sorts
- FECodeNT, ///< NOT_TESTED() call of sorts
- FECodeCF ///< COMPILE_FAIL() call of sorts
-};
-typedef enum FECode FECode;
-
-#define FATAL() FatalError(__FILE__, __LINE__, FECodeMisc, 0, NULL)
-#define FATAL_IF(x) do { if (UNLIKELY(x)) FATAL(); } while (0)
-#define FATAL_OOM() FatalError(__FILE__, __LINE__, FECodeOOM, 0, NULL)
-#define FATAL_OOM_IF(x) do { if (UNLIKELY(x)) FATAL_OOM(); } while (0)
-
-extern _Bool FatalError_hit;
-
-void NORETURN FatalError(char const *file,
- int line,
- FECode feCode,
- int bugno,
- char const *fmt,
- ...) FORMAT(printf,5,6);
-
-#define FATALERROR_COMMON(printFunc, \
- printFuncV, \
- file, \
- line, \
- feCode, \
- bugno, \
- fmt) { \
- va_list ap; \
- \
- printFunc("FatalError: %s:%d, code %d, bugno %d\n", \
- file, line, feCode, bugno); \
- if (fmt != NULL) { \
- va_start(ap, fmt); \
- printFuncV(fmt, ap); \
- va_end(ap); \
- } \
- }
-
-#if defined IN_HOSTUSER || defined IN_GUESTUSER || defined IN_WORKSTATION
-
-#define FATALERROR_POSIX_USER \
-void \
-FatalError_VErrPrintf(const char *fmt, va_list ap) \
-{ \
- vfprintf(stderr, fmt, ap); \
-} \
-\
-void \
-FatalError_ErrPrintf(const char *fmt, ...) \
-{ \
- va_list ap; \
- va_start(ap, fmt); \
- FatalError_VErrPrintf(fmt, ap); \
- va_end(ap); \
-} \
-\
-void NORETURN \
-FatalError(char const *file, \
- int line, \
- FECode feCode, \
- int bugno, \
- const char *fmt, \
- ...) \
-{ \
- FATALERROR_COMMON(FatalError_ErrPrintf, FatalError_VErrPrintf, file, line, feCode, bugno, fmt); \
- exit(EXIT_FAILURE); \
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/include_check.h b/arch/arm/mvp/mvpkm/include_check.h
deleted file mode 100644
index 2eeafe7..0000000
--- a/arch/arm/mvp/mvpkm/include_check.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for Empty File Placeholder
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
diff --git a/arch/arm/mvp/mvpkm/instr_defs.h b/arch/arm/mvp/mvpkm/instr_defs.h
deleted file mode 100644
index ce6b1c9..0000000
--- a/arch/arm/mvp/mvpkm/instr_defs.h
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief ARM instruction encoding/decoding macros.
- */
-
-#ifndef _INSTR_DEFS_H_
-#define _INSTR_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "utils.h"
-
-/**
- * @name ARM register synonyms.
- * @{
- */
-#define ARM_REG_R0 0
-#define ARM_REG_R1 1
-#define ARM_REG_R2 2
-#define ARM_REG_R3 3
-#define ARM_REG_R4 4
-#define ARM_REG_R5 5
-#define ARM_REG_R6 6
-#define ARM_REG_R7 7
-#define ARM_REG_R8 8
-#define ARM_REG_R9 9
-#define ARM_REG_R10 10
-#define ARM_REG_FP 11
-#define ARM_REG_IP 12
-#define ARM_REG_SP 13
-#define ARM_REG_LR 14
-#define ARM_REG_PC 15
-/*@}*/
-
-/**
- * @name Data-processing + load/store instruction register field decoding.
- *
- * @note The following constants and masks used to fetch register operands
- * are meant to be used in strictly the following sets of instructions:
- * data processing instructions and load/store instructions.
- * If you want to fetch the RN, RD, RS and RM fields for some other
- * type of instructions, please verify before using -- you may have
- * to introduce special constants just for those sets of instructions.
- * For instance, all the multiply and signed multiply instructions have
- * RN and RD reversed. So, @b BEWARE !
- *
- * @{
- */
-#define ARM_INSTR_RN_BIT_POS 16
-#define ARM_INSTR_RD_BIT_POS 12
-#define ARM_INSTR_RS_BIT_POS 8
-#define ARM_INSTR_RM_BIT_POS 0
-
-#define ARM_INSTR_RN_LENGTH 4
-#define ARM_INSTR_RD_LENGTH 4
-#define ARM_INSTR_RS_LENGTH 4
-#define ARM_INSTR_RM_LENGTH 4
-
-#define ARM_INSTR_RN(r) \
- MVP_EXTRACT_FIELD((r), ARM_INSTR_RN_BIT_POS, ARM_INSTR_RN_LENGTH)
-#define ARM_INSTR_RD(r) \
- MVP_EXTRACT_FIELD((r), ARM_INSTR_RD_BIT_POS, ARM_INSTR_RD_LENGTH)
-#define ARM_INSTR_RS(r) \
- MVP_EXTRACT_FIELD((r), ARM_INSTR_RS_BIT_POS, ARM_INSTR_RS_LENGTH)
-#define ARM_INSTR_RM(r) \
- MVP_EXTRACT_FIELD((r), ARM_INSTR_RM_BIT_POS, ARM_INSTR_RM_LENGTH)
-
-#define ARM_INSTR_RN_SHIFT(word) ((word) << ARM_INSTR_RN_BIT_POS)
-#define ARM_INSTR_RD_SHIFT(word) ((word) << ARM_INSTR_RD_BIT_POS)
-#define ARM_INSTR_RS_SHIFT(word) ((word) << ARM_INSTR_RS_BIT_POS)
-#define ARM_INSTR_RM_SHIFT(word) ((word) << ARM_INSTR_RM_BIT_POS)
-
-#define ARM_INSTR_RN_MASK (~(ARM_INSTR_RN_SHIFT(0xf)))
-#define ARM_INSTR_RD_MASK (~(ARM_INSTR_RD_SHIFT(0xf)))
-#define ARM_INSTR_RS_MASK (~(ARM_INSTR_RS_SHIFT(0xf)))
-#define ARM_INSTR_RM_MASK (~(ARM_INSTR_RM_SHIFT(0xf)))
-/*@}*/
-
-/**
- * @name Condition field -- common bit layout across all ARM instructions.
- * @{
- */
-#define ARM_INSTR_COND(instr) (MVP_EXTRACT_FIELD(instr, 28, 4))
-
-#define ARM_INSTR_COND_EQ 0x0 ///< Equal
-#define ARM_INSTR_COND_NE 0x1 ///< Not equal
-#define ARM_INSTR_COND_CS 0x2 ///< Carry set/unsigned higher or same
-#define ARM_INSTR_COND_CC 0x3 ///< Carry clear/unsigned lower
-#define ARM_INSTR_COND_MI 0x4 ///< Minus/negative
-#define ARM_INSTR_COND_PL 0x5 ///< Plus/positive or zero
-#define ARM_INSTR_COND_VS 0x6 ///< Overflow
-#define ARM_INSTR_COND_VC 0x7 ///< No overflow
-#define ARM_INSTR_COND_HI 0x8 ///< Unsigned higher
-#define ARM_INSTR_COND_LS 0x9 ///< Unsigned lower or same
-#define ARM_INSTR_COND_GE 0xa ///< Signed greater than or equal
-#define ARM_INSTR_COND_LT 0xb ///< Signed less than
-#define ARM_INSTR_COND_GT 0xc ///< Signed greater than
-#define ARM_INSTR_COND_LE 0xd ///< Signed less than or equal
-#define ARM_INSTR_COND_AL 0xe ///< Always (unconditional)
-#define ARM_INSTR_COND_NV 0xf ///< Invalid
-/*@}*/
-
-/**
- * @name Load/store instruction decoding.
- * @{
- */
-
-/*
- * I bit indicating Register(1)/Immediate(0) addressing modes.
- */
-#define ARM_INSTR_LDST_IBIT(instr) (MVP_BIT(instr, 25))
-
-/*
- * U bit indicating whether the offset is added to the base (U == 1)
- * or is subtracted from the base (U == 0).
- */
-#define ARM_INSTR_LDST_UBIT(instr) (MVP_BIT(instr, 23))
-
-/*
- * B bit indicating byte(1)/word(0).
- */
-#define ARM_INSTR_LDST_BBIT(instr) (MVP_BIT(instr, 22))
-
-/*
- * L bit indicating ld(1)/st(0).
- */
-#define ARM_INSTR_LDST_LBIT(instr) (MVP_BIT(instr, 20))
-
-/*
- * Shifter operand.
- */
-#define ARM_INSTR_LDST_SHIFTER_OPERAND(instr) (MVP_EXTRACT_FIELD(instr, 0, 12))
-
-/*
- * Immediate offset (12-bits wide) for load/store.
- */
-#define ARM_INSTR_LDST_IMMEDIATE(instr) (MVP_EXTRACT_FIELD(instr, 0, 12))
-
-/*
- * Register List for multiple ld/st.
- */
-#define ARM_INSTR_LDMSTM_REGLIST(instr) (MVP_EXTRACT_FIELD(instr, 0, 16))
-
-/*
- * Immediate Offset for Miscellaneous ld/st instructions.
- */
-#define ARM_INSTR_MISC_LDST_IMM_OFFSET(instr) \
- ((MVP_EXTRACT_FIELD(instr, 8, 4) << 4) | MVP_EXTRACT_FIELD(instr, 0, 4))
-
-/*@}*/
-
-/**
- * @name Thumb ldrt/strt instruction decoding.
- * @{
- */
-
-/*
- * L bit indicating ld(1)/st(0).
- */
-#define ARM_THUMB_INSTR_LDST_LBIT(instr) (MVP_BIT(instr, 20))
-
-/*
- * W bit indicating word(1)/byte(0).
- */
-#define ARM_THUMB_INSTR_LDST_WBIT(instr) (MVP_BIT(instr, 22))
-
-/*
- * Immediate offset (8-bits wide) for load/store.
- */
-#define ARM_THUMB_INSTR_LDST_IMMEDIATE(instr) (MVP_EXTRACT_FIELD(instr, 0, 8))
-
-/*@}*/
-
-/**
- * @name ARM instruction opcodes.
- * @{
- */
-#define ARM_OP_BR_A1 0x0a000000
-#define ARM_OP_BX_A1 0x012fff10
-#define ARM_OP_LDR_LIT_A1 0x051f0000
-#define ARM_OP_MOV_A1 0x01a00000
-#define ARM_OP_MOVW_A2 0x03000000
-#define ARM_OP_MOVT_A1 0x03400000
-#define ARM_OP_MRS_A1 0x01000000
-#define ARM_OP_MSR_T1 0x8000f380
-#define ARM_OP_MSR_A1 0x0120f000
-#define ARM_OP_HVC_A1 0x01400070
-#define ARM_OP_ERET_T1 0x8f00f3de
-#define ARM_OP_ERET_A1 0x0160006e
-
-/*
- * Set SYSm[5] = 1 for VE MSR/MRS, see p77-78 ARM PRD03-GENC-008353 10.0.
- */
-#define ARM_OP_MRS_EXT_A1 (ARM_OP_MRS_A1 | (1 << 9))
-#define ARM_OP_MSR_EXT_T1 (ARM_OP_MSR_T1 | (1 << 21))
-#define ARM_OP_MSR_EXT_A1 (ARM_OP_MSR_A1 | (1 << 9))
-
-#define ARM_OP_I 0x02000000
-#define ARM_OP_S 0x00100000
-#define ARM_OP_W 0x00200000
-/*@}*/
-
-/**
- * @name ARM instruction class - see Figure A3-1 ARM DDI 0100I.
- * @{
- */
-#define ARM_INSTR_CLASS(instr) MVP_BITS(instr, 25, 27)
-
-#define ARM_INSTR_CLASS_BRANCH 0x5
-/*@}*/
-
-/**
- * @name ARM instruction opcode - see Figure A3-1 ARM DDI 0100I. Does not
- * include extension bits 4-7.
- * @{
- */
-#define ARM_INSTR_OPCODE(instr) MVP_EXTRACT_FIELD(instr, 20, 8)
-
-#define ARM_INSTR_OPCODE_EQ(instr1, instr2) \
- (ARM_INSTR_OPCODE(instr1) == ARM_INSTR_OPCODE(instr2))
-/*@}*/
-
-/**
- * @brief Extract the offset in a branch instruction - i.e., the least
- * significant 24 bits sign extended.
- */
-#define ARM_INSTR_BRANCH_TARGET(inst) (((int32)(inst) << 8) >> 6)
-
-/**
- * @brief Check if a potential branch target is outside the encodable distance.
- */
-#define ARM_INSTR_BRANCH_TARGET_OVERFLOWS(v) ((v) + (1 << 25) >= (1<< 26))
-
-/**
- * @brief Modify branch instruction encoding 'ins' with 'offset' as the
- * new target.
- */
-#define ARM_INSTR_BRANCH_UPDATE_OFFSET(ins, offset) \
- (((ins) & MVP_MASK(24, 8)) | (((offset) >> 2) & MVP_MASK(0, 24)))
-
-/**
- * @brief B instruction encoding - see A8.6.16 ARM DDI 0406A.
- */
-#define ARM_INSTR_BR_ENC(cond, offset) \
- (((cond) << 28) | ARM_OP_BR_A1 | MVP_BITS(((uint32)offset) >> 2, 0, 23))
-
-/**
- * @brief BX instruction encoding
- */
-#define ARM_INSTR_BX_ENC(cond, rm) \
- (((cond) << 28) | ARM_OP_BX_A1 | (rm))
-
-/**
- * @brief LDR +literal instruction encoding - see ARM8.6.59 DDI 0506A.
- */
-#define ARM_INSTR_LDR_LIT_ADD_ENC(cond, reg, offset) \
- (((cond) << 28) | ARM_OP_LDR_LIT_A1 | (1 << 23) | ((reg) << 12) | (offset))
-
-/**
- * @brief Generate encoding of the instruction mov rd, rn.
- */
-#define ARM_INSTR_MOV_A1_ENC(cond, rd, rn) \
- ((((cond) << 28) | ARM_OP_MOV_A1 | ((rd) << 12) | (rn)))
-
-/**
- * @name Encoding/decoding of MOVT/W instructions.
- * @{
- */
-#define ARM_INSTR_MOVTW_IMMED(instr) \
- (MVP_BITS(instr, 0, 11) | (MVP_BITS(instr, 16, 19) << 12))
-
-#define ARM_INSTR_MOVW_A2_ENC(cond,rd,immed) \
- (((cond) << 28) | ARM_OP_MOVW_A2 | (MVP_BITS(immed, 12, 15) << 16) | \
- ((rd) << 12) | MVP_BITS(immed, 0, 11))
-
-#define ARM_INSTR_MOVT_A1_ENC(cond,rd,immed) \
- (((cond) << 28) | ARM_OP_MOVT_A1 | \
- (MVP_BITS(((immed) >> 16), 12, 15) << 16) | \
- ((rd) << 12) | MVP_BITS(((immed) >> 16), 0, 11))
-/*@}*/
-
-/**
- * @brief BKPT instruction encoding - see A4.1.7 ARM DDI 0100I.
- */
-#define ARM_INSTR_BKPT_ENC(immed) \
- (0xe1200070 | \
- MVP_EXTRACT_FIELD(immed, 0, 4) | \
- (MVP_EXTRACT_FIELD(immed, 4, 12) << 8))
-
-/**
- * @name VE instruction encodings - see section 13 ARM PRD03-GENC-008353 10.0.
- * @{
- */
-#define ARM_INSTR_HVC_A1_ENC(immed) \
- ((ARM_INSTR_COND_AL << 28) | ARM_OP_HVC_A1 | \
- MVP_EXTRACT_FIELD(immed, 0, 4) | \
- (MVP_EXTRACT_FIELD(immed, 4, 12) << 8))
-
-#define ARM_INSTR_ERET_A1_ENC(cond) \
- (((cond) << 28) | ARM_OP_ERET_A1)
-
-/*
- * R=0
- */
-#define ARM_REG_R8_USR 0
-#define ARM_REG_R9_USR 1
-#define ARM_REG_R10_USR 2
-#define ARM_REG_R11_USR 3
-#define ARM_REG_R12_USR 4
-#define ARM_REG_SP_USR 5
-#define ARM_REG_LR_USR 6
-#define ARM_REG_R8_FIQ 8
-#define ARM_REG_R9_FIQ 9
-#define ARM_REG_R10_FIQ 10
-#define ARM_REG_FP_FIQ 11
-#define ARM_REG_IP_FIQ 12
-#define ARM_REG_SP_FIQ 13
-#define ARM_REG_LR_FIQ 14
-#define ARM_REG_LR_IRQ 16
-#define ARM_REG_SP_IRQ 17
-#define ARM_REG_LR_SVC 18
-#define ARM_REG_SP_SVC 19
-#define ARM_REG_LR_ABT 20
-#define ARM_REG_SP_ABT 21
-#define ARM_REG_LR_UND 22
-#define ARM_REG_SP_UND 23
-#define ARM_REG_LR_MON 28
-#define ARM_REG_SP_MON 29
-#define ARM_REG_ELR_HYP 30
-#define ARM_REG_SP_HYP 31
-
-/*
- * R=1
- */
-#define R_EXTEND(x) ((1 << 5) | (x))
-#define ARM_REG_SPSR_FIQ R_EXTEND(ARM_REG_LR_FIQ)
-#define ARM_REG_SPSR_IRQ R_EXTEND(ARM_REG_LR_IRQ)
-#define ARM_REG_SPSR_SVC R_EXTEND(ARM_REG_LR_SVC)
-#define ARM_REG_SPSR_ABT R_EXTEND(ARM_REG_LR_ABT)
-#define ARM_REG_SPSR_UND R_EXTEND(ARM_REG_LR_UND)
-#define ARM_REG_SPSR_MON R_EXTEND(ARM_REG_LR_MON)
-#define ARM_REG_SPSR_HYP R_EXTEND(ARM_REG_ELR_HYP)
-
-#define ARM_INSTR_MSR_EXT_T1_ENC(rm,rn) \
- (ARM_OP_MSR_EXT_T1 | (MVP_BIT(rm, 5) << 4) | \
- (MVP_BIT(rm, 4) << 20) | (MVP_EXTRACT_FIELD(rm, 0, 4) << 24) | ((rn) << 0))
-
-#define ARM_INSTR_MSR_EXT_A1_ENC(cond,rm,rn) \
- (((cond) << 28) | ARM_OP_MSR_EXT_A1 | (MVP_BIT(rm, 5) << 22) | \
- (MVP_BIT(rm, 4) << 8) | (MVP_EXTRACT_FIELD(rm, 0, 4) << 16) | ((rn) << 0))
-
-#define ARM_INSTR_MRS_EXT_A1_ENC(cond,rd,rm) \
- (((cond) << 28) | ARM_OP_MRS_EXT_A1 | (MVP_BIT(rm, 5) << 22) | \
- (MVP_BIT(rm, 4) << 8) | (MVP_EXTRACT_FIELD(rm, 0, 4) << 16) | ((rd) << 12))
-/*@}*/
-
-/**
- * @name ARM MCR/MRC/MCRR instruction decoding.
- * @{
- */
-#define ARM_INSTR_COPROC_CR_LEN 4
-#define ARM_INSTR_COPROC_CR_MAX (1 << ARM_INSTR_COPROC_CR_LEN)
-#define ARM_INSTR_COPROC_OPCODE_LEN 3
-#define ARM_INSTR_COPROC_OPCODE_MAX (1 << ARM_INSTR_COPROC_OPCODE_LEN)
-
-#define ARM_INSTR_COPROC_CRM(instr) MVP_EXTRACT_FIELD(instr, 0, 4)
-#define ARM_INSTR_COPROC_CRN(instr) MVP_EXTRACT_FIELD(instr, 16, 4)
-#define ARM_INSTR_COPROC_OPCODE1(instr) MVP_EXTRACT_FIELD(instr, 21, 3)
-#define ARM_INSTR_COPROC_OPCODE2(instr) MVP_EXTRACT_FIELD(instr, 5, 3)
-#define ARM_INSTR_COPROC_OPCODE(instr) MVP_EXTRACT_FIELD(instr, 4, 4)
-#define ARM_INSTR_COPROC_CPNUM(instr) MVP_EXTRACT_FIELD(instr, 8, 4)
-/*@}*/
-
-/**
- * @name ARM VMRS/VMSR instruction decoding -- See VMRS (B6.1.14)
- * and VMSR (B6.1.15) in ARM DDI 0406B.
- * @{
- */
-#define ARM_INSTR_IS_VMRS(instr) ((MVP_EXTRACT_FIELD(instr, 0, 12) == 0xa10) && \
- (ARM_INSTR_OPCODE(instr) == 0xef))
-
-#define ARM_INSTR_IS_VMSR(instr) ((MVP_EXTRACT_FIELD(instr, 0, 12) == 0xa10) && \
- (ARM_INSTR_OPCODE(instr) == 0xee))
-
-#define ARM_INSTR_VMRS_SPECREG(instr) MVP_EXTRACT_FIELD(instr, 16, 4)
-#define ARM_INSTR_VMRS_RT(instr) MVP_EXTRACT_FIELD(instr, 12, 4)
-
-#define ARM_INSTR_VMSR_SPECREG(instr) MVP_EXTRACT_FIELD(instr, 16, 4)
-#define ARM_INSTR_VMSR_RT(instr) MVP_EXTRACT_FIELD(instr, 12, 4)
-/*@}*/
-
-/**
- * @name ARM SWP{B} instruction checking.
- * @{
- */
-#define ARM_INSTR_IS_SWP(instr) ((instr & 0x0fb00ff0) == 0x01000090)
-/*@}*/
-
-#endif /// _INSTR_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/lowmemkiller_variant.sh b/arch/arm/mvp/mvpkm/lowmemkiller_variant.sh
deleted file mode 100644
index 7721e57..0000000
--- a/arch/arm/mvp/mvpkm/lowmemkiller_variant.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/bash
-#
-# Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
-#
-# Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
-# the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; see the file COPYING. If not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# @brief Script providing the variant of the low memory killer implementation
-# to assist in mvpkm's export of the other_file calculation.
-
-if [ -z "$1" ]
-then
- echo "Usage: $0 <path to lowmemorykiller.c>"
- exit 1
-fi
-
-# We look at the relevant section of the lowmem_shrink function here. This
-# pattern is sufficient to distinguish between the known variants without
-# introducing too many false positives for new variants. I.e. we can spot the
-# lines that matter for the other_file calculation. In some cases the
-# lowmemorykiller uses only the other_file calculation instead of max(free,
-# file) - in the cases we've seen this is OK with the balloon policy, since the
-# free term isn't really significant when we get into low memory states anyway.
-
-tmp_file="lmk_md5sum_$RANDOM"
-
-cat $1 | tr -d '\ \t\n\r' > $tmp_file
-sed -i -e 's/.*\(intother_file.*other_file<\).*/;\1/' \
- -e 's/[;][^;]*other_file[^;]*/#<#&#>#/g' \
- -e 's/#>#[^#]*//g' $tmp_file
-
-# Detect MD5SUM executable
-HOST_OS=`uname -s`
-if [ "$HOST_OS" = "Darwin" ]
-then
- MD5SUM_EXEC=md5
-else
- MD5SUM_EXEC=md5sum
-fi
-
-MD5=`${MD5SUM_EXEC} $tmp_file | cut -f1 -d\ `
-
-rm $tmp_file
-
-case $MD5 in
-4af66fafb5e4cbd7b4092e29e071f152|\
-a0f18472eb53e52b38d6f85d4ec66842|\
-590b89af56f57146edffceba60845ad8|\
-fddbb73a58e82ba1966fd862a561c2bd)
- #/*
- # * This is the same as the non-exported global_reclaimable_pages() when there
- # * is no swap.
- # */
- #other_file = global_page_state(NR_ACTIVE_FILE) +
- # global_page_state(NR_INACTIVE_FILE);
- V=1
-;;
-943372c447dd868845d71781292eae17|\
-14d0cc4189c1f4fd7818c3393cc8c311)
- # other_file = global_page_state(NR_FILE_PAGES);
- V=2
-;;
-59f3bb678a855acfea2365b7a904bc5b|\
-df96cbb1784869ac7d017dd343e4e8f2)
- # other_file = global_page_state(NR_FILE_PAGES) - global_page_state(NR_SHMEM);
- V=3
-;;
-ed03b69361c2881ed1a031c9b9a24d8a|\
-8639aca416d3014d68548d6cb538405b)
- # other_file = global_page_state(NR_FREE_PAGES) + global_page_state(NR_FILE_PAGES);
- # (other_free not used, but max(other_free, other_file) = other_file in this
- # case.
- V=4
-;;
-*)
- V=0
-;;
-esac
-
-echo "$MD5 $V"
diff --git a/arch/arm/mvp/mvpkm/lpae_defs.h b/arch/arm/mvp/mvpkm/lpae_defs.h
deleted file mode 100644
index 7729268..0000000
--- a/arch/arm/mvp/mvpkm/lpae_defs.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Large physical address extension definitions.
- *
- * See ARM PRD03-GENC-008469 11.0.
- */
-#ifndef _LPAE_DEFS_H_
-#define _LPAE_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define ARM_LPAE_PT_ORDER 12
-
-#define ARM_LPAE_PT_SIZE (1 << ARM_LPAE_PT_ORDER)
-#define ARM_LPAE_ENTRY_ORDER 3
-#define ARM_LPAE_PT_ENTRIES_ORDER (ARM_LPAE_PT_ORDER - ARM_LPAE_ENTRY_ORDER)
-#define ARM_LPAE_PT_ENTRIES (1 << ARM_LPAE_PT_ENTRIES_ORDER)
-
-#define ARM_LPAE_L1D_BLOCK_ORDER 30
-#define ARM_LPAE_L2D_BLOCK_ORDER 21
-#define ARM_LPAE_L3D_BLOCK_ORDER 12
-
-#define ARM_LPAE_L1D_BLOCK_BITS (40 - ARM_LPAE_L1D_BLOCK_ORDER)
-#define ARM_LPAE_L2D_BLOCK_BITS (40 - ARM_LPAE_L2D_BLOCK_ORDER)
-#define ARM_LPAE_L3D_BLOCK_BITS (40 - ARM_LPAE_L3D_BLOCK_ORDER)
-
-/*
- * Currently supporting up to 16GB PA spaces.
- */
-#define ARM_LPAE_L1PT_INDX(addr) \
- MVP_EXTRACT_FIELD64(addr, ARM_LPAE_L1D_BLOCK_ORDER, 4)
-#define ARM_LPAE_L2PT_INDX(addr) \
- MVP_EXTRACT_FIELD64(addr, ARM_LPAE_L2D_BLOCK_ORDER, ARM_LPAE_PT_ENTRIES_ORDER)
-#define ARM_LPAE_L3PT_INDX(addr) \
- MVP_EXTRACT_FIELD64(addr, ARM_LPAE_L3D_BLOCK_ORDER, ARM_LPAE_PT_ENTRIES_ORDER)
-
-#define ARM_LPAE_L1D_BLOCK_BASE_ADDR(base) ((base) << ARM_LPAE_L1D_BLOCK_ORDER)
-#define ARM_LPAE_L1D_BLOCK_ADDR_BASE(addr) ((addr) >> ARM_LPAE_L1D_BLOCK_ORDER)
-#define ARM_LPAE_L2D_BLOCK_BASE_ADDR(base) ((base) << ARM_LPAE_L2D_BLOCK_ORDER)
-#define ARM_LPAE_L2D_BLOCK_ADDR_BASE(addr) ((addr) >> ARM_LPAE_L2D_BLOCK_ORDER)
-#define ARM_LPAE_L3D_BLOCK_BASE_ADDR(base) ((base) << ARM_LPAE_L3D_BLOCK_ORDER)
-#define ARM_LPAE_L3D_BLOCK_ADDR_BASE(addr) ((addr) >> ARM_LPAE_L3D_BLOCK_ORDER)
-
-#define ARM_LPAE_TABLE_BASE_ADDR(base) ((base) << ARM_LPAE_PT_ORDER)
-#define ARM_LPAE_TABLE_ADDR_BASE(addr) ((addr) >> ARM_LPAE_PT_ORDER)
-
-#define ARM_LPAE_TYPE_INVALID 0
-#define ARM_LPAE_TYPE_TABLE 3
-#define ARM_LPAE_L1D_TYPE_BLOCK 1
-#define ARM_LPAE_L2D_TYPE_BLOCK 1
-#define ARM_LPAE_L3D_TYPE_BLOCK 3
-
-/**
- * @name Second stage permission model.
- *
- * @{
- */
-#define ARM_LPAE_S2_PERM_NONE 0
-#define ARM_LPAE_S2_PERM_RO 1
-#define ARM_LPAE_S2_PERM_WO 2
-#define ARM_LPAE_S2_PERM_RW 3
-/*@}*/
-
-
-#endif /// ifndef _LPAE_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/lpae_types.h b/arch/arm/mvp/mvpkm/lpae_types.h
deleted file mode 100644
index 292f0d9..0000000
--- a/arch/arm/mvp/mvpkm/lpae_types.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Large physical address extension types.
- *
- * See ARM PRD03-GENC-008469 11.0.
- */
-#ifndef _LPAE_TYPES_H_
-#define _LPAE_TYPES_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "lpae_defs.h"
-
-/**
- * @name ARM LPAE page table descriptors. See p7-8 ARM PRD03-GENC-008469 11.0.
- * @{
- */
-
-#define LOWER_PAGE_ATTRIBUTES_STAGE1 \
- uint64 attrIndx : 3; \
- uint64 ns : 1; \
- uint64 ap : 2; \
- uint64 sh : 2; \
- uint64 af : 1; \
- uint64 ng : 1;
-
-#define LOWER_PAGE_ATTRIBUTES_STAGE2 \
- uint64 memAttr : 4; \
- uint64 hap : 2; \
- uint64 sh : 2; \
- uint64 af : 1; \
- uint64 sbzL : 1;
-
-#define UPPER_PAGE_ATTRIBUTES_STAGE1 \
- uint64 contig : 1; \
- uint64 pxn : 1; \
- uint64 xn : 1; \
- uint64 sw : 4; \
- uint64 ignU : 5;
-
-#define UPPER_PAGE_ATTRIBUTES_STAGE2 \
- uint64 contig : 1; \
- uint64 sbzU : 1; \
- uint64 xn : 1; \
- uint64 sw : 4; \
- uint64 ignU : 5;
-
-
-#define ARM_LPAE_DESC_TYPE(lvl,blen,sbzpad) \
- typedef union { \
- uint64 u; \
- \
- struct { \
- uint64 type : 2;\
- uint64 ign : 62; \
- } x; \
- \
- struct { \
- uint64 type : 2;\
- LOWER_PAGE_ATTRIBUTES_STAGE1 \
- sbzpad \
- uint64 base : blen; \
- uint64 sbz : 12; \
- UPPER_PAGE_ATTRIBUTES_STAGE1 \
- } blockS1; \
- \
- struct { \
- uint64 type : 2;\
- LOWER_PAGE_ATTRIBUTES_STAGE2 \
- sbzpad \
- uint64 base : blen; \
- uint64 sbz : 12; \
- UPPER_PAGE_ATTRIBUTES_STAGE2 \
- } blockS2; \
- \
- struct { \
- uint64 type : 2;\
- uint64 ign0 : 10; \
- uint64 base : 28; \
- uint64 sbz : 12; \
- uint64 ign1 : 7; \
- uint64 pxn : 1; \
- uint64 xn : 1; \
- uint64 ap : 2; \
- uint64 ns : 1; \
- } table; \
- \
- } ARM_LPAE_L##lvl##D;
-
-
-ARM_LPAE_DESC_TYPE(1, ARM_LPAE_L1D_BLOCK_BITS, uint64 sbzP : 18;)
-ARM_LPAE_DESC_TYPE(2, ARM_LPAE_L2D_BLOCK_BITS, uint64 sbzP : 9;)
-ARM_LPAE_DESC_TYPE(3, ARM_LPAE_L3D_BLOCK_BITS, )
-
-/*@}*/
-
-#endif /// ifndef _LPAE_TYPES_H_
diff --git a/arch/arm/mvp/mvpkm/mksck.h b/arch/arm/mvp/mvpkm/mksck.h
deleted file mode 100644
index aac00f7..0000000
--- a/arch/arm/mvp/mvpkm/mksck.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#ifndef _MKSCK_H
-#define _MKSCK_H
-
-/**
- * @file
- *
- * @brief The monitor-kernel socket interface definitions.
- *
- * The monitor kernel socket interface was created for (what the name
- * says) communications between the monitor and host processes. On the
- * monitor side a special API is introduced, see mksck_vmm.h. On the
- * host side the API is the standard Berkeley socket interface. Host
- * process to host process or monitor to monitor communication is not
- * supported.
- *
- * A generic address consists of two 16 bit fields: the vm id and the
- * port id. Both hosts (vmx) and monitors (vmm) get their vm id
- * automatically. The host vm id is assigned at the time the host
- * process opens the mvpkm file descriptor, while the monitor vm id is
- * assigned when the vmx.c:SetupWorldSwitchPage() calls
- * Mvpkm_SetupIds(). As a vmx may create multiple monitors to service
- * an MP guest, a vmx vm id may be associated with multiple monitor vm
- * ids. A monitor id, however, has a single associated vmx host id,
- * the id of its canonical vmx.
- *
- * Sockets on the host get their addresses either by explicit user
- * call (the bind command) or implicitly by (issuing a send command
- * first). At an explicit bind the user may omit one or both fields by
- * providing MKSCK_VMID_UNDEF/MKSCK_PORT_UNDEF respectively. An
- * implicit bind behaves as if both fields were omitted in an explicit
- * bind. The default value of the vmid field is the vmid computed from
- * the thread group id while that of a port is a new number. It is not
- * invalid to bind a host process socket with a vm id different from
- * the vmid computed from the tgid.
- *
- * Sockets of the monitor are automatically assigned a vmid, that of their
- * monitor, at the time of their creation. The port id can be assigned by the
- * user or left to the implementation to assign an unused one (by specifying
- * MKSCK_PORT_UNDEF at @ref Mksck_Open).
- *
- * Host unconnected sockets may receive from any monitor sender, may send to any
- * monitor socket. A socket can be connected to a peer address, that enables the
- * use of the send command.
- *
- * One of many special predefined port (both host and monitor) is
- * MKSCK_PORT_MASTER. It is used for initialization.
- *
- * Monitor sockets have to send their peer address explicitly (by
- * Mksck_SetPeer()) or implicitly by receiving first. After the peer
- * is set, monitor sockets may send or receive only to/from their
- * peer.
- */
-
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "vmid.h"
-
-/*
- * The interface limits the size of transferable packets.
- */
-#define MKSCK_XFER_MAX 1024
-
-#define MKSCK_ADDR_UNDEF (uint32)0xffffffff
-
-#define MKSCK_PORT_UNDEF (uint16)0xffff
-#define MKSCK_PORT_MASTER (MKSCK_PORT_UNDEF-1)
-#define MKSCK_PORT_HOST_FB (MKSCK_PORT_UNDEF-2)
-#define MKSCK_PORT_BALLOON (MKSCK_PORT_UNDEF-3)
-#define MKSCK_PORT_HOST_HID (MKSCK_PORT_UNDEF-4)
-#define MKSCK_PORT_CHECKPOINT (MKSCK_PORT_UNDEF-5)
-#define MKSCK_PORT_COMM_EV (MKSCK_PORT_UNDEF-6)
-#define MKSCK_PORT_HIGH (MKSCK_PORT_UNDEF-7)
-
-#define MKSCK_VMID_UNDEF VMID_UNDEF
-#define MKSCK_VMID_HIGH (MKSCK_VMID_UNDEF-1)
-
-#define MKSCK_DETACH 3
-
-typedef uint16 Mksck_Port;
-typedef VmId Mksck_VmId;
-
-/**
- * @brief Page descriptor for typed messages. Each page describes a region of
- * the machine address space with base mpn and size 2^(12 + order) bytes.
- */
-typedef struct {
- uint32 mpn : 20; ///< Base MPN of region described by page
- uint32 order : 12; ///< Region is 2^(12 + order) bytes.
-} Mksck_PageDesc;
-
-/**
- * @brief Typed message template macro. Allows us to avoid having two message
- * types, one with page descriptor vector (for VMM), one without (for
- * VMX).
- *
- * @param type C type of uninterpreted component of the message (following the
- * page descriptor vector).
- * @param pages number of page descriptors in vector.
- */
-#define MKSCK_DESC_TYPE(type,pages) \
- struct { \
- type umsg; \
- Mksck_PageDesc page[pages]; \
- }
-
-/**
- * @brief The monitor kernel socket interface address format
- */
-typedef union {
- uint32 addr; ///< the address
- struct { /* The address is decomposed to two shorts */
- Mksck_Port port; ///< port unique within a vmid
- Mksck_VmId vmId; ///< unique vmid
- };
-} Mksck_Address;
-
-static inline uint32
-Mksck_AddrInit(Mksck_VmId vmId, Mksck_Port port)
-{
- Mksck_Address aa;
- aa.vmId = vmId;
- aa.port = port;
- return aa.addr;
-}
-#endif
diff --git a/arch/arm/mvp/mvpkm/mksck_kernel.c b/arch/arm/mvp/mvpkm/mksck_kernel.c
deleted file mode 100644
index 6811a68..0000000
--- a/arch/arm/mvp/mvpkm/mksck_kernel.c
+++ /dev/null
@@ -1,2589 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The monitor/kernel socket interface kernel extension.
- */
-
-#define __KERNEL_SYSCALLS__
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/fcntl.h>
-#include <linux/syscalls.h>
-#include <linux/kmod.h>
-#include <linux/socket.h>
-#include <linux/net.h>
-#include <linux/skbuff.h>
-#include <linux/miscdevice.h>
-#include <linux/poll.h>
-#include <linux/rcupdate.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/vmalloc.h>
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#include <net/sock.h>
-
-#include <asm/memory.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "mvp.h"
-#include "actions.h"
-#include "mvpkm_kernel.h"
-#include "mksck_kernel.h"
-#include "mksck_sockaddr.h"
-#include "mutex_kernel.h"
-
-void NORETURN FatalError(char const *file,
- int line,
- FECode feCode,
- int bugno,
- char const *fmt,
- ...)
-{
- /* Lock around printing the error details so that the messages from multiple
- * threads are not interleaved. */
- static DEFINE_MUTEX(fatalErrorMutex);
- mutex_lock(&fatalErrorMutex);
-
- FATALERROR_COMMON(printk, vprintk, file, line, feCode, bugno, fmt);
-
- dump_stack();
-
- /* done printing */
- mutex_unlock(&fatalErrorMutex);
-
- /* do_exit below exits the current thread but does not crash the kernel.
- * Hence the stack dump will actually be readable from other user threads.
- */
- do_exit(1);
-}
-
-
-/*
- * The project uses a new address family: AF_MKSCK. Optimally this address
- * family were accepted with the Linux community and a permanent number
- * were assigned. This, however, is a dream only, not even the x86 team
- * has been able to pull it off.
- *
- * Instead we ASSUME that DECnet is dead and re-use it's address family number.
- * This is what the x86 world is moving too in the latest versions.
- */
-
-static struct proto mksckProto = {
- .name = "AF_MKSCK",
- .owner = THIS_MODULE,
- .obj_size = sizeof (struct sock),
-};
-
-static int MksckCreate(struct net *net,
- struct socket *sock,
- int protocol,
- int kern);
-
-static struct net_proto_family mksckFamilyOps = {
- .family = AF_MKSCK,
- .owner = THIS_MODULE,
- .create = MksckCreate,
-};
-
-static int MksckFault(struct vm_area_struct *vma, struct vm_fault *vmf);
-
-
-/**
- * @brief Linux vma operations for receive windows established via Mksck
- * mmap.
- */
-static struct vm_operations_struct mksckVMOps = {
- .fault = MksckFault
-};
-
-/*
- * List of hosts and guests we know about.
- */
-static spinlock_t mksckPageListLock;
-static MksckPage *mksckPages[MKSCK_MAX_SHARES];
-
-/*
- * The following functions form the AF_MKSCK DGRAM operations.
- */
-static int MksckRelease(struct socket *sock);
-static int MksckBacklogRcv(struct sock *sk, struct sk_buff *skb);
-static void MksckSkDestruct(struct sock *sk);
-static int MksckBind(struct socket *sock,
- struct sockaddr *addr,
- int addrLen);
-static int MksckBindGeneric(struct sock *sk,
- Mksck_Address addr);
-static int MksckDgramRecvMsg(struct kiocb *kiocb,
- struct socket *sock,
- struct msghdr *msg,
- size_t len,
- int flags);
-static int MksckDgramSendMsg(struct kiocb *kiocb,
- struct socket *sock,
- struct msghdr *msg,
- size_t len);
-static int MksckGetName(struct socket *sock,
- struct sockaddr *addr,
- int *addrLen,
- int peer);
-static unsigned int MksckPoll(struct file *filp,
- struct socket *sock,
- poll_table *wait);
-static int MksckDgramConnect(struct socket *sock,
- struct sockaddr *addr,
- int addrLen,
- int flags);
-static int MksckMMap(struct file *file,
- struct socket *sock,
- struct vm_area_struct *vma);
-
-static void MksckPageRelease(MksckPage *mksckPage);
-
-static struct proto_ops mksckDgramOps = {
- .family = AF_MKSCK,
- .owner = THIS_MODULE,
- .release = MksckRelease,
- .bind = MksckBind,
- .connect = MksckDgramConnect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = MksckGetName,
- .poll = MksckPoll,
- .ioctl = sock_no_ioctl,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown, /* MksckShutdown, */
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = MksckDgramSendMsg,
- .recvmsg = MksckDgramRecvMsg,
- .mmap = MksckMMap,
- .sendpage = sock_no_sendpage,
-};
-
-
-/**
- * @brief Initialize the MKSCK protocol
- *
- * @return 0 on success, -errno on failure
- */
-int
-Mksck_Init(void)
-{
- int err;
-
- spin_lock_init(&mksckPageListLock);
-
- /*
- * Create a slab to allocate socket structs from.
- */
- err = proto_register(&mksckProto, 1);
- if (err != 0) {
- printk(KERN_INFO
- "Mksck_Init: Cannot register MKSCK protocol, errno = %d.\n", err);
- return err;
- }
-
- /*
- * Register the socket family
- */
- err = sock_register(&mksckFamilyOps);
- if (err < 0) {
- printk(KERN_INFO
- "Mksck_Init: Could not register address family AF_MKSCK"
- " (errno = %d).\n", err);
- return err;
- }
-
- return 0;
-}
-
-
-/**
- * @brief De-register the MKSCK protocol
- */
-void
-Mksck_Exit(void)
-{
- sock_unregister(mksckFamilyOps.family);
- proto_unregister(&mksckProto);
-}
-
-
-/**
- * @brief Create a new MKSCK socket
- *
- * @param net network namespace (2.6.24 or above)
- * @param sock user socket structure
- * @param protocol protocol to be used
- * @param kern called from kernel mode
- *
- * @return 0 on success, -errno on failure
- */
-static int
-MksckCreate(struct net *net,
- struct socket *sock,
- int protocol,
- int kern)
-{
- struct sock *sk;
- uid_t currentUid = current_euid();
-
- if (!(currentUid == 0 ||
- currentUid == Mvpkm_vmwareUid)) {
- printk(KERN_WARNING
- "MksckCreate: rejected from process %s tgid=%d, pid=%d euid:%d.\n",
- current->comm,
- task_tgid_vnr(current),
- task_pid_vnr(current),
- currentUid);
- return -EPERM;
- }
-
- if (!sock) {
- return -EINVAL;
- }
-
- if (protocol) {
- return -EPROTONOSUPPORT;
- }
-
- switch (sock->type) {
- case SOCK_DGRAM: {
- sock->ops = &mksckDgramOps;
- break;
- }
- default: {
- return -ESOCKTNOSUPPORT;
- }
- }
-
- sock->state = SS_UNCONNECTED;
-
- /*
- * Most recently (in 2.6.24), sk_alloc() was changed to expect the
- * network namespace, and the option to zero the sock was dropped.
- */
- sk = sk_alloc(net, mksckFamilyOps.family, GFP_KERNEL, &mksckProto);
-
- if (!sk) {
- return -ENOMEM;
- }
-
- sock_init_data(sock, sk);
-
- sk->sk_type = SOCK_DGRAM;
- sk->sk_destruct = MksckSkDestruct;
- sk->sk_backlog_rcv = MksckBacklogRcv;
-
- /*
- * On socket lock...
- *
- * A bound socket will have an associated private area, the Mksck
- * structure part of MksckPage. That area is pointed to by
- * sk->sk_protinfo. In addition, a connected socket will have the
- * peer field in its associated area set to point to the associated
- * private area of the peer socket. A mechanism is needed to ensure
- * that these private areas area not freed while they are being
- * accessed within the scope of a function. A simple lock would not
- * suffice as the interface functions (like MksckDgramRecvMsg())
- * may block. Hence a reference count mechanism is employed. When
- * the mentioned references (sk->sk_protinfo and mksck->peer) to
- * the respective private areas are set a refcount is incremented,
- * and decremented when the references are deleted.
- *
- * The refcounts of areas pointed to by sk->sk_protinfo and
- * mksck->peer will be decremented under the lock of the socket.
- * Hence these private areas cannot disappear as long as the socket
- * lock is held.
- *
- * The interface functions will have one of the following
- * structures:
- *
- * simpleFn(sk)
- * {
- * lock_sock(sk);
- * if ((mksck = sk->sk_protinfo)) {
- * <non-blocking use of mksck>
- * }
- * release_sock(sk);
- * }
- *
- * complexFn(sk)
- * {
- * lock_sock(sk);
- * if ((mksck = sk->sk_protinfo)) {
- * IncRefc(mksck);
- * }
- * release_sock(sk);
- *
- * if (mksck) {
- * <use of mksck in a potentially blocking manner>
- * DecRefc(mksck);
- * }
- * }
- */
- sk->sk_protinfo = NULL;
- sock_reset_flag(sk, SOCK_DONE);
-
- return 0;
-}
-
-
-/**
- * @brief Delete a MKSCK socket
- *
- * @param sock user socket structure
- *
- * @return 0 on success, -errno on failure
- */
-static int
-MksckRelease(struct socket *sock)
-{
- struct sock *sk = sock->sk;
-
- if (sk) {
- lock_sock(sk);
- sock_orphan(sk);
- release_sock(sk);
- sock_put(sk);
- }
-
- sock->sk = NULL;
- sock->state = SS_FREE;
-
- return 0;
-}
-
-
-static int
-MksckBacklogRcv(struct sock *sk, struct sk_buff *skb)
-{
- /*
- * We should never get these as we never queue an skb.
- */
- printk("MksckBacklogRcv: should never get here\n");
- return -EIO;
-}
-
-
-/**
- * @brief Callback at socket destruction
- *
- * @param sk pointer to kernel socket structure
- */
-static void
-MksckSkDestruct(struct sock *sk)
-{
- Mksck *mksck;
-
- lock_sock(sk);
- mksck = sk->sk_protinfo;
-
- if (mksck != NULL) {
- sk->sk_protinfo = NULL;
- Mksck_CloseCommon(mksck);
- }
-
- if (sk->sk_user_data != NULL) {
- sock_kfree_s(sk, sk->sk_user_data, sizeof(int));
- sk->sk_user_data = NULL;
- }
-
- release_sock(sk);
-}
-
-
-/**
- * @brief Set the local address of a MKSCK socket
- *
- * @param sk kernel socket structure
- * @param addr the new address of the socket
- *
- * @return 0 on success, -errno on failure
- *
- * If addr.port is undefined a new random port is assigned.
- * If addr.vmId is undefined then the vmId computed from the tgid is used.
- * Hence the vmId of a socket does not determine the host all the time.
- *
- * Assumed that the socket is locked.
- * This function is called by explicit set (MksckBind) and implicit (Send).
- */
-static int
-MksckBindGeneric(struct sock *sk,
- Mksck_Address addr)
-{
- int err;
- Mksck *mksck;
- MksckPage *mksckPage;
-
- if (sk->sk_protinfo != NULL) {
- return -EISCONN;
- }
-
- /*
- * Locate the page for the given host and increment its reference
- * count so it can't get freed off while we are working on it.
- */
- if (addr.vmId == MKSCK_VMID_UNDEF) {
- mksckPage = MksckPage_GetFromTgidIncRefc();
- } else {
- printk(KERN_WARNING "MksckBind: host bind called on vmid 0x%X\n", addr.vmId);
- mksckPage = MksckPage_GetFromVmIdIncRefc(addr.vmId);
- }
-
- if (mksckPage == NULL) {
- printk(KERN_INFO "MksckBind: no mksckPage for vm 0x%X\n", addr.vmId);
- return -ENETUNREACH;
- }
- addr.vmId = mksckPage->vmId;
-
- /*
- * Before we can find an unused socket port on the page we have to
- * lock the page for exclusive access so another thread can't
- * allocate the same port.
- */
- err = Mutex_Lock(&mksckPage->mutex, MutexModeEX);
- if (err < 0) {
- goto outDec;
- }
-
- addr.port = MksckPage_GetFreePort(mksckPage, addr.port);
- if (addr.port == MKSCK_PORT_UNDEF) {
- err = -EINVAL;
- goto outUnlockDec;
- }
-
- /*
- * At this point we have the mksckPage locked for exclusive access
- * and its reference count incremented. Also, addr is completely
- * filled in with vmId and port that we want to bind.
- *
- * Find an available mksck struct on the shared page and initialize
- * it.
- */
- mksck = MksckPage_AllocSocket(mksckPage, addr);
- if (mksck == NULL) {
- err = -EMFILE;
- goto outUnlockDec;
- }
-
- /*
- * Stable, release mutex. Leave mksckPage->refCount incremented so
- * mksckPage can't be freed until socket is closed.
- */
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
-
- /*
- * This is why we start mksck->refCount at 1. When sk_protinfo gets
- * cleared, we decrement mksck->refCount.
- */
- sk->sk_protinfo = mksck;
-
- PRINTK(KERN_DEBUG "MksckBind: socket bound to %08X\n", mksck->addr.addr);
-
- return 0;
-
-outUnlockDec:
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
-outDec:
- MksckPage_DecRefc(mksckPage);
- return err;
-}
-
-
-/**
- * @brief Test if the socket is already bound to a local address and,
- * if not, bind it to an unused address.
- *
- * @param sk kernel socket structure
- * @return 0 on success, -errno on failure
- *
- * Assumed that the socket is locked.
- */
-static inline int
-MksckTryBind(struct sock *sk)
-{
- int err = 0;
-
- if (!sk->sk_protinfo) {
- static const Mksck_Address addr = { .addr = MKSCK_ADDR_UNDEF };
- err = MksckBindGeneric(sk, addr);
- }
- return err;
-}
-
-
-
-/**
- * @brief Set the address of a MKSCK socket (user call)
- *
- * @param sock user socket structure
- * @param addr the new address of the socket
- * @param addrLen length of the address
- *
- * @return 0 on success, -errno on failure
- */
-static int
-MksckBind(struct socket *sock,
- struct sockaddr *addr,
- int addrLen)
-{
- int err;
- struct sock *sk = sock->sk;
- struct sockaddr_mk *addrMk = (struct sockaddr_mk *)addr;
-
- if (addrLen != sizeof *addrMk) {
- return -EINVAL;
- }
- if (addrMk->mk_family != AF_MKSCK) {
- return -EAFNOSUPPORT;
- }
-
- /*
- * Obtain the socket lock and call the generic Bind function.
- */
- lock_sock(sk);
- err = MksckBindGeneric(sk, addrMk->mk_addr);
- release_sock(sk);
-
- return err;
-}
-
-/**
- * @brief Lock the peer socket by locating it, incrementing its refc
- * @param addr the address of the peer socket
- * @param[out] peerMksckR set to the locked peer socket pointer
- * upon successful lookup
- * @return 0 on success, -errno on failure
- */
-static int
-LockPeer(Mksck_Address addr, Mksck **peerMksckR)
-{
- int err = 0;
- MksckPage *peerMksckPage = MksckPage_GetFromVmIdIncRefc(addr.vmId);
- Mksck *peerMksck;
-
- /*
- * Find corresponding destination shared page and increment its
- * reference count so it can't be freed while we are sending to the
- * socket. Make sure that the address is indeed an address of a
- * monitor/guest socket.
- */
- if (peerMksckPage == NULL) {
- printk(KERN_INFO "LockPeer: vmId %x is not in use!\n", addr.vmId);
- return -ENETUNREACH;
- }
- if (!peerMksckPage->isGuest) {
- MksckPage_DecRefc(peerMksckPage);
- printk(KERN_INFO "LockPeer: vmId %x does not belong to a guest!\n",
- addr.vmId);
- return -ENETUNREACH;
- }
-
-
- err = Mutex_Lock(&peerMksckPage->mutex, MutexModeSH);
- if (err < 0) {
- MksckPage_DecRefc(peerMksckPage);
- return err;
- }
-
- /*
- * Find corresponding destination socket on that shared page and
- * increment its reference count so it can't be freed while we are
- * trying to send to it.
- */
- peerMksck = MksckPage_GetFromAddr(peerMksckPage, addr);
-
- if (peerMksck) {
- ATOMIC_ADDV(peerMksck->refCount, 1);
- *peerMksckR = peerMksck;
- } else {
- printk(KERN_INFO "LockPeer: addr %x is not a defined socket!\n",
- addr.addr);
- err = -ENETUNREACH;
- }
-
- Mutex_Unlock(&peerMksckPage->mutex, MutexModeSH);
- MksckPage_DecRefc(peerMksckPage);
- return err;
-}
-
-/**
- * @brief Set the peer address of a MKSCK socket
- *
- * @param sock user socket structure
- * @param addr the new address of the socket
- * @param addrLen length of the address
- * @param flags flags
- *
- * @return 0 on success, -errno on failure
- */
-static int
-MksckDgramConnect(struct socket *sock,
- struct sockaddr *addr,
- int addrLen,
- int flags)
-{
- struct sock *sk = sock->sk;
- Mksck *mksck;
- struct sockaddr_mk *peerAddrMk = (struct sockaddr_mk *)addr;
- int err = 0;
-
- if (addrLen != sizeof *peerAddrMk) {
- printk(KERN_INFO "MksckConnect: wrong address length!\n");
- return -EINVAL;
- }
- if (peerAddrMk->mk_family != AF_MKSCK) {
- printk(KERN_INFO "MksckConnect: wrong address family!\n");
- return -EAFNOSUPPORT;
- }
-
- lock_sock(sk);
-
- if ((err = MksckTryBind(sk))) {
- goto releaseSock;
- }
- mksck = sk->sk_protinfo;
-
- /*
- * First severe any past peer connections
- */
- Mksck_DisconnectPeer(mksck);
- sock->state = SS_UNCONNECTED;
-
- /*
- * Then build new connections ...
- */
- if (peerAddrMk->mk_addr.addr != MKSCK_ADDR_UNDEF) {
- sock->state = SS_CONNECTED;
- mksck->peerAddr = peerAddrMk->mk_addr;
- err = LockPeer(mksck->peerAddr, &mksck->peer);
- PRINTK(KERN_DEBUG "MksckConnect: socket %x is connected to %x!\n",
- mksck->addr.addr, mksck->peerAddr.addr);
- }
-
-releaseSock:
- release_sock(sk);
-
- return err;
-}
-
-
-/**
- * @brief returns the address of a MKSCK socket/peer address
- *
- * @param sock user socket structure
- * @param addr the new address of the socket
- * @param addrLen length of the address
- * @param peer 1 if the peer address is sought
- *
- * @return 0 on success, -errno on failure
- */
-static int
-MksckGetName(struct socket *sock,
- struct sockaddr *addr,
- int *addrLen,
- int peer)
-{
- int err;
- Mksck *mksck;
- struct sock *sk = sock->sk;
-
- // MAX_SOCK_ADDR is size of *addr, Linux doesn't export it!
- // ASSERT_ON_COMPILE(sizeof (struct sockaddr_mk) <= MAX_SOCK_ADDR);
-
- lock_sock(sk);
- mksck = sk->sk_protinfo;
-
- if (mksck == NULL) {
- if (peer) {
- err = -ENOTCONN;
- } else {
- ((struct sockaddr_mk *)addr)->mk_family = AF_MKSCK;
- ((struct sockaddr_mk *)addr)->mk_addr.addr = MKSCK_ADDR_UNDEF;
- *addrLen = sizeof (struct sockaddr_mk);
- err = 0;
- }
- } else if (!peer) {
- ((struct sockaddr_mk *)addr)->mk_family = AF_MKSCK;
- ((struct sockaddr_mk *)addr)->mk_addr = mksck->addr;
- *addrLen = sizeof (struct sockaddr_mk);
- err = 0;
- } else if (mksck->peerAddr.addr == MKSCK_ADDR_UNDEF) {
- err = -ENOTCONN;
- } else {
- ((struct sockaddr_mk *)addr)->mk_family = AF_MKSCK;
- ((struct sockaddr_mk *)addr)->mk_addr = mksck->peerAddr;
- *addrLen = sizeof (struct sockaddr_mk);
- err = 0;
- }
-
- release_sock(sk);
-
- return err;
-}
-
-
-/**
- * @brief VMX polling a receipted packet from VMM.
- *
- * @param filp kernel file pointer to poll for
- * @param sock user socket structure
- * @param wait kernel polling table where to poll if not null
- *
- * @return poll mask state given from socket state.
- */
-static unsigned int MksckPoll(struct file *filp,
- struct socket *sock,
- poll_table *wait)
-{
- struct sock *sk = sock->sk;
- unsigned int mask = 0;
- Mksck *mksck = NULL;
- uint32 read;
- int err;
-
- lock_sock(sk);
- if ((err = MksckTryBind(sk))) {
- release_sock(sk);
- return err;
- }
- mksck = sk->sk_protinfo;
-
- /*
- * To avoid mksck disappearing right after the release_sock the
- * refcount needs to be incremented. For more details read the
- * block comment on locking in MksckCreate.
- */
- ATOMIC_ADDV(mksck->refCount, 1);
- release_sock(sk);
-
- /*
- * Wait to make sure this is the only thread trying to access socket.
- */
- if ((err = Mutex_Lock(&mksck->mutex, MutexModeEX)) < 0) {
- /* we might get in this situation if we are signaled
- (select() may handle this, so leave) */
- PRINTK(KERN_INFO "MksckPoll: try to abort\n");
- return mask;
- }
-
- /*
- * See if packet in ring.
- */
- read = mksck->read;
- if (read != mksck->write) {
- mask |= POLLIN | POLLRDNORM; /* readable, socket is unlocked */
- /* Note that if we are implementing support for POLLOUT, we SHOULD
- change this Mutex_Unlock by Mutex_UnlPoll, because there is no
- obvious knowledge about the sleepy reason that is intended by user */
- Mutex_Unlock(&mksck->mutex, MutexModeEX);
- } else {
- Mutex_UnlPoll(&mksck->mutex, MutexModeEX, MKSCK_CVAR_FILL, filp, wait);
- }
-
- /*
- * Note that locking rules differ a little inside MksckPoll, since we are
- * not only given a pointer to the struct socket but also a pointer to a
- * struct file. This means that during the whole operation of this function
- * and during any pending wait (registered with poll_wait()), the file itself
- * is reference counted up, and we should rely on that 'upper' reference
- * counting to prevent from tearing the Mksck down. That holds true since one
- * never re-bind sockets !
- */
- Mksck_DecRefc(mksck);
- return mask;
-}
-
-/**
- * @brief Manage a set of Mksck_PageDesc from a message or a stored array.
- *
- * @param pd set of Mksck_PageDesc
- * @param pages Mksck_PageDesc pages count for this management operation
- * @param incr ternary used to indicate if we want to reference (+1), or
- * dereference (-1), or count (0) 4k pages
- *
- * @return length of bytes processed.
- */
-static size_t
-MksckPageDescManage(Mksck_PageDesc *pd,
- uint32 pages,
- int incr)
-{
- size_t payloadLen = 0;
- uint32 i;
-
- for (i = 0; i < pages && pd[i].mpn != INVALID_MPN; ++i) {
- uint32 j;
-
- for (j = 0; j < 1 << pd[i].order; ++j) {
- struct page *page;
- MPN currMPN = pd[i].mpn + j;
-
- /*
- * The monitor tried to send an invalid MPN, bad.
- */
- if (!pfn_valid(currMPN)) {
- printk("MksckPageDescManage: Invalid MPN %x\n", currMPN);
- } else {
- page = pfn_to_page(currMPN);
-
- if (incr == +1) {
- get_page(page);
- }
- if (incr == -1) {
- put_page(page);
- }
- }
-
- payloadLen += PAGE_SIZE;
- }
- }
-
- return payloadLen;
-}
-
-/**
- * @brief Management values to be used as third parameter of MksckPageDescManage
- */
-#define MANAGE_INCREMENT +1
-#define MANAGE_DECREMENT -1
-#define MANAGE_COUNT 0
-
-
-/**
- * @brief Map a set of Mksck_PageDesc from a message or a stored array.
- *
- * @param pd set of Mksck_PageDesc
- * @param pages pages count for this mapping
- * @param iov vectored user virtual addresses of the recv commands
- * @param iovCount size for iov parameter
- * @param vma virtual memory area used for the mapping, note that
- * this is mandatorily required MksckPageDescMap is used
- * on an indirect PageDesc context (i.e whenever iov is
- * not computed by the kernel but by ourselves).
- *
- * Since find_vma() and vm_insert_page() are used, this function must
- * be called with current's mmap_sem locked, or inside an MMap operation.
- *
- * @return length of bytes mapped.
- */
-static size_t
-MksckPageDescMap(Mksck_PageDesc *pd,
- uint32 pages,
- struct iovec *iov,
- int iovCount,
- struct vm_area_struct *vma)
-{
- size_t payloadLen = 0;
- uint32 i;
-
- for (i = 0; i < pages && pd[i].mpn != INVALID_MPN; ++i) {
- uint32 j;
-
- for (j = 0; j < 1 << pd[i].order; ++j) {
- HUVA huva = 0;
- struct page *page;
- MPN currMPN = pd[i].mpn + j;
-
- while (iovCount > 0 && iov->iov_len == 0) {
- iovCount--;
- iov++;
- }
-
- if (iovCount == 0) {
- printk("MksckPageDescMap: Invalid iov length\n");
- goto map_done;
- }
-
- huva = (HUVA)iov->iov_base;
-
- /*
- * iovecs for receiving the typed component of the message should
- * have page aligned base and size sufficient for page descriptor's
- * mappings.
- */
- if (huva & (PAGE_SIZE - 1) || iov->iov_len < PAGE_SIZE) {
- printk("MksckPageDescMap: Invalid huva %x or iov_len %d\n",
- huva,
- iov->iov_len);
- goto map_done;
- }
-
- /*
- * Might be in a new vma...
- */
- if (vma == NULL || huva < vma->vm_start || huva >= vma->vm_end) {
- vma = find_vma(current->mm, huva);
-
- /*
- * Couldn't find a matching vma for huva.
- */
- if (vma == NULL ||
- huva < vma->vm_start ||
- vma->vm_ops != &mksckVMOps) {
- printk("MksckPageDescMap: Invalid vma\n");
- goto map_done;
- }
- }
-
- /*
- * The monitor tried to send an invalid MPN, bad.
- */
- if (!pfn_valid(currMPN)) {
- printk("MksckPageDescMap: Invalid MPN %x\n", currMPN);
- } else {
- int rc;
-
- page = pfn_to_page(currMPN);
-
- /*
- * Map into the receive window.
- */
- rc = vm_insert_page(vma, huva, page);
- if (rc) {
- printk("MksckPageDescMap: Failed to insert %x at %x, error %d\n",
- currMPN,
- huva,
- rc);
- goto map_done;
- }
-
- ASSERT(iov->iov_len >= PAGE_SIZE);
- iov->iov_base += PAGE_SIZE;
- iov->iov_len -= PAGE_SIZE;
- }
-
- payloadLen += PAGE_SIZE;
- }
- }
-
-map_done:
- return payloadLen;
-}
-
-
-/**
- * @brief Check if the provided MsgHdr has still room for a receive operation.
- *
- * @param msg user buffer
- * @return 1 if MsgHdr has IO space room in order to receive a mapping, 0 otherwise.
- */
-static int
-MsgHdrHasAvailableRoom(struct msghdr *msg)
-{
- struct iovec *vec = msg->msg_iov;
- uint32 count = msg->msg_iovlen;
-
- while (count > 0 && vec->iov_len == 0) {
- count--;
- vec++;
- }
-
- return (count != 0);
-}
-
-
-/**
- * Whenever a typed message is received from the monitor, we may choose to store
- * all the page descriptor content in a linked state of descriptors, through the
- * following information context
- */
-typedef struct MksckPageDescInfo {
- struct MksckPageDescInfo *next;
- uint32 flags;
- uint32 pages;
- uint32 mapCounts;
- Mksck_PageDesc descs[0];
-} MksckPageDescInfo;
-
-static void MksckPageDescSkDestruct(struct sock *sk);
-static int MksckPageDescMMap(struct file *file,
- struct socket *sock,
- struct vm_area_struct *vma);
-static int MksckPageDescIoctl(struct socket *sock,
- unsigned int cmd,
- unsigned long arg);
-
-/**
- * @brief Delete a page descriptor container socket
- *
- * @param sock user socket structure
- * @return 0 on success, -errno on failure
- */
-static int
-MksckPageDescRelease(struct socket *sock)
-{
- /* This is generic socket release */
- struct sock *sk = sock->sk;
-
- if (sk) {
- lock_sock(sk);
- sock_orphan(sk);
- release_sock(sk);
- sock_put(sk);
- }
-
- sock->sk = NULL;
- sock->state = SS_FREE;
-
- return 0;
-}
-
-
-/**
- * Whenever a typed message is received from the monitor, we may choose to store
- * all the page descriptor content for a future mapping. One shall put a context
- * usable by host userland, that means trough a file descriptor, and as a secure
- * implementation we choose to define a strict set of operations that are used
- * only for that purpose. This set of operation is reduced to leaving the
- * default "PageDesc(s) accumulating" mode (inside ioctl), mapping the context,
- * and generic socket destruction.
- */
-static struct proto_ops mksckPageDescOps = {
- .family = AF_MKSCK,
- .owner = THIS_MODULE,
- .release = MksckPageDescRelease,
- .bind = sock_no_bind,
- .connect = sock_no_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = sock_no_getname,
- .poll = sock_no_poll,
- .ioctl = MksckPageDescIoctl,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = sock_no_sendmsg,
- .recvmsg = sock_no_recvmsg,
- .mmap = MksckPageDescMMap,
- .sendpage = sock_no_sendpage,
-};
-
-
-/**
- * @brief Create or accumulate to a PageDesc context, backed as a descriptor.
- *
- * @param sock user socket structure
- * @param msg user buffer to receive the file descriptor as ancillary data
- * @param pd source descriptor part of a message
- * @param pages pages count for this mapping
- *
- * @return error if negative, 0 otherwise
- *
- */
-static int
-MksckPageDescToFd(struct socket *sock,
- struct msghdr *msg,
- Mksck_PageDesc *pd,
- uint32 pages)
-{
- int retval;
- int newfd;
- struct socket *newsock;
- struct sock *newsk;
- struct sock *sk = sock->sk;
- MksckPageDescInfo **pmpdi, *mpdi;
- lock_sock(sk);
-
- /*
- * Relation between any mk socket and the PageDesc context is as follow:
- *
- * From the mk socket to the PageDesc context:
- * - sk->sk_user_data is a WEAK LINK, containing only a file descriptor
- * numerical value such that accumulating is keyed on it.
- *
- * From the PageDesc context to the mk socket:
- * - sk->sk_protinfo contains a MksckPageDescInfo struct.
- * - sk->sk_user_data is a pointer REF-COUNTED sock_hold() LINK, also it is
- * rarely dereferenced but usually used to check that the
- * right socket pair is used. Full dereferencing is used
- * only to break the described links.
- */
- if (sk->sk_user_data) {
- MksckPageDescInfo *mpdi2;
-
- /* continue any previous on-going mapping, i.e accumulate */
- newfd = *((int *)sk->sk_user_data);
- newsock = sockfd_lookup(newfd, &retval); // promote the weak link
- if (!newsock) {
- retval = -EINVAL;
- goto endProcessingReleaseSock;
- }
-
- newsk = newsock->sk;
- lock_sock(newsk);
- sockfd_put(newsock);
-
- if (((struct sock *)newsk->sk_user_data) != sk) {
- /* One way of going into this situation would be for userland to dup
- the file descriptor just received, close the original number, and
- open a new mk socket in the very same spot. The userland code have
- a lot of way of interacting with the kernel without this driver
- code to be notified. */
- retval = -EINVAL;
- release_sock(newsk);
- goto endProcessingReleaseSock;
- }
-
- mpdi = sock_kmalloc(newsk, sizeof(MksckPageDescInfo) +
- pages*sizeof(Mksck_PageDesc), GFP_KERNEL);
- if (IS_ERR(mpdi)) {
- retval = PTR_ERR(mpdi);
- release_sock(newsk);
- goto endProcessingReleaseSock;
- }
-
- /* There is no mandatory needs for us to notify userland from
- the progress in "appending" to the file descriptor, but it
- would feel strange if the userland would have no mean to
- tell if the received message was just not thrown away. So, in
- order to be consistent one fill the ancillary message while
- "creating" and "appending to" file descriptors. */
- retval = put_cmsg(msg, SOL_DECNET, 0, sizeof(int), &newfd);
- if (retval < 0) {
- goto endProcessingKFreeReleaseSock;
- }
-
- release_sock(sk);
-
- mpdi2 = (MksckPageDescInfo *)newsk->sk_protinfo;
- while (mpdi2->next) {
- mpdi2 = mpdi2->next;
- }
- pmpdi = &(mpdi2->next);
-
- } else {
- /* Create a new socket, new context and a new file descriptor. */
- retval = sock_create(sk->sk_family, sock->type, 0, &newsock);
- if (retval < 0) {
- goto endProcessingReleaseSock;
- }
-
- newsk = newsock->sk;
- lock_sock(newsk);
- newsk->sk_destruct = &MksckPageDescSkDestruct;
- newsk->sk_user_data = sk;
- sock_hold(sk); // keeps a reference to parent mk socket
- newsock->ops = &mksckPageDescOps;
-
- mpdi = sock_kmalloc(newsk, sizeof(MksckPageDescInfo) +
- pages*sizeof(Mksck_PageDesc), GFP_KERNEL);
- if (IS_ERR(mpdi)) {
- retval = PTR_ERR(mpdi);
- goto endProcessingFreeNewSock;
- }
-
- sk->sk_user_data = sock_kmalloc(sk, sizeof(int), GFP_KERNEL);
- if (IS_ERR(sk->sk_user_data)) {
- retval = PTR_ERR(sk->sk_user_data);
- sk->sk_user_data = NULL;
- goto endProcessingKFreeAndNewSock;
- }
-
- /* mapping to a file descriptor may fail if a thread is closing
- in parallel of sock_map_fd/sock_alloc_fd, or kernel memory is full */
- newfd = sock_map_fd(newsock, O_CLOEXEC);
- if (newfd < 0) {
- retval = newfd;
- sock_kfree_s(sk, sk->sk_user_data, sizeof(int));
- sk->sk_user_data = NULL;
- goto endProcessingKFreeAndNewSock;
- }
-
- /* notify userland from a new file descriptor, alike AF_UNIX ancillary */
- retval = put_cmsg(msg, SOL_DECNET, 0, sizeof(int), &newfd);
- if (retval < 0) {
- sock_kfree_s(sk, sk->sk_user_data, sizeof(int));
- sk->sk_user_data = NULL;
- sock_kfree_s(newsk, mpdi, sizeof(MksckPageDescInfo) +
- mpdi->pages*sizeof(Mksck_PageDesc));
- release_sock(newsk);
- sockfd_put(newsock);
- sock_release(newsock);
- put_unused_fd(newfd);
- goto endProcessingReleaseSock;
- }
-
- *(int*)sk->sk_user_data = newfd;
- release_sock(sk);
- pmpdi = (MksckPageDescInfo **)(&(newsk->sk_protinfo));
- }
-
- mpdi->next = NULL;
- mpdi->flags = 0;
- mpdi->mapCounts = 0;
- mpdi->pages = pages;
- memcpy(mpdi->descs, pd, pages*sizeof(Mksck_PageDesc));
-
- *pmpdi = mpdi; // link
- release_sock(newsk);
-
- /* increment all reference counters for the pages */
- MksckPageDescManage(pd, pages, MANAGE_INCREMENT);
- return 0;
-
-endProcessingKFreeAndNewSock:
- sock_kfree_s(newsk, mpdi, sizeof(MksckPageDescInfo) +
- mpdi->pages*sizeof(Mksck_PageDesc));
-endProcessingFreeNewSock:
- release_sock(newsk);
- sock_release(newsock);
- release_sock(sk);
- return retval;
-
-endProcessingKFreeReleaseSock:
- sock_kfree_s(newsk, mpdi, sizeof(MksckPageDescInfo) +
- mpdi->pages*sizeof(Mksck_PageDesc));
- release_sock(newsk);
-endProcessingReleaseSock:
- release_sock(sk);
- return retval;
-}
-
-/**
- * @brief Callback at socket destruction
- *
- * @param sk pointer to kernel socket structure
- */
-static void
-MksckPageDescSkDestruct(struct sock *sk)
-{
- struct sock *mkSk = NULL;
- MksckPageDescInfo *mpdi;
- lock_sock(sk);
- mpdi = sk->sk_protinfo;
- while (mpdi) {
- MksckPageDescInfo *next = mpdi->next;
- MksckPageDescManage(mpdi->descs, mpdi->pages,
- MANAGE_DECREMENT);
- sock_kfree_s(sk, mpdi, sizeof(MksckPageDescInfo) +
- mpdi->pages*sizeof(Mksck_PageDesc));
- mpdi = next;
- }
- if (sk->sk_user_data) {
- mkSk = (struct sock *)sk->sk_user_data;
- sk->sk_user_data = NULL;
- }
- sk->sk_protinfo = NULL;
- release_sock(sk);
- /* clean the monki socket that we are holding */
- if (mkSk) {
- lock_sock(mkSk);
- sock_kfree_s(mkSk, mkSk->sk_user_data, sizeof(int));
- mkSk->sk_user_data = NULL;
- release_sock(mkSk);
- sock_put(mkSk); // revert of sock_hold()
- }
-}
-
-/**
- * @brief The mmap operation of the PageDesc context file descriptor.
- *
- * The mmap command is used to mmap any detached (i.e. no more accumulating)
- * PageDesc context, full of the content from its parent communication mk
- * socket. Mapping may be done a specified number of times, so that the
- * PageDesc context could become useless (as a security restriction).
- *
- * Also note that mapping from an offset different from zero is considered
- * as a userland invalid operation.
- *
- * @param file user file structure
- * @param sock user socket structure
- * @param vma virtual memory area structure
- *
- * @return error code, 0 on success
- */
-static int
-MksckPageDescMMap(struct file *file,
- struct socket *sock,
- struct vm_area_struct *vma)
-{
- struct sock *sk = sock->sk;
- MksckPageDescInfo *mpdi;
- struct iovec iov;
- unsigned long vm_flags;
- int freed = 0;
-
- iov.iov_base = (void*)vma->vm_start;
- iov.iov_len = vma->vm_end - vma->vm_start;
-
- lock_sock(sk);
- mpdi = sk->sk_protinfo;
-
- // vma->vm_pgoff is checked, since offsetting the map is not supported
- if (!mpdi || sk->sk_user_data || vma->vm_pgoff) {
- release_sock(sk);
- printk(KERN_INFO "MMAP failed for virt %lx size %lx\n",
- vma->vm_start, vma->vm_end - vma->vm_start);
- return -EINVAL;
- }
-
- vm_flags = mpdi->flags;
- if ((vma->vm_flags & ~vm_flags) & (VM_READ|VM_WRITE)) {
- release_sock(sk);
- return -EACCES;
- }
-
- while (mpdi) {
- MksckPageDescInfo *next = mpdi->next;
- MksckPageDescMap(mpdi->descs, mpdi->pages, &iov, 1, vma);
- if (mpdi->mapCounts && !--mpdi->mapCounts) {
- MksckPageDescManage(mpdi->descs, mpdi->pages,
- MANAGE_DECREMENT);
- sock_kfree_s(sk, mpdi, sizeof(MksckPageDescInfo) +
- mpdi->pages*sizeof(Mksck_PageDesc));
- freed = 1;
- }
- mpdi = next;
- }
-
- if (freed) {
- sk->sk_protinfo = NULL;
- }
- vma->vm_ops = &mksckVMOps;
- release_sock(sk);
- return 0;
-}
-
-/**
- * @brief The ioctl operation of the PageDesc context file descriptor.
- *
- * The ioctl MKSCK_DETACH command is used to detach the PageDesc context
- * from its parent communication mk socket. Once done, the context
- * is able to remap the transferred PageDesc(s) of typed messages accumulated
- * into the context.
- *
- * @param sock user socket structure
- * @param cmd select which cmd function needs to be performed
- * @param arg argument for command
- *
- * @return error code, 0 on success
- */
-static int
-MksckPageDescIoctl(struct socket *sock,
- unsigned int cmd,
- unsigned long arg)
-{
- struct sock *monkiSk = NULL;
- struct sock *sk = sock->sk;
- MksckPageDescInfo *mpdi;
- int retval = 0;
-
- switch (cmd) {
- /**
- * ioctl MKSCK_DETACH (in and out):
- * Detach, compute size and define allowed protection access rights
- *
- * [in]: unsigned long flags, similar to prot argument of mmap()
- * unsigned long number of available further mappings
- * with 0 meaning unlimited number of mappings
- * [out]: unsigned long size of the available mappable area
- */
- case MKSCK_DETACH: {
- unsigned long ul[2];
- lock_sock(sk);
- mpdi = sk->sk_protinfo;
- // read unsigned long argument that contains the mmap alike flags
- if (copy_from_user(ul, (void *)arg, sizeof ul)) {
- retval = -EFAULT;
- // check that the file descriptor has a parent and some context there
- } else if (!mpdi || !sk->sk_user_data) {
- retval = -EINVAL;
- } else {
- /* compute mapping protection bits from argument and size of the
- * mapping, that is also given back to userland as unsigned long.
- */
- uint32 flags = calc_vm_prot_bits(ul[0]);
- ul[0] = 0;
- while (mpdi) {
- MksckPageDescInfo *next = mpdi->next;
- ul[0] += MksckPageDescManage(mpdi->descs, mpdi->pages,
- MANAGE_COUNT);
- mpdi->mapCounts = ul[1];
- mpdi = next;
- }
- if (copy_to_user((void *)arg, ul, sizeof(ul[0]))) {
- retval = -EFAULT;
- } else {
- mpdi = sk->sk_protinfo;
- mpdi->flags = flags;
- monkiSk = (struct sock *)sk->sk_user_data;
- sk->sk_user_data = NULL;
- }
- }
- release_sock(sk);
- // clean the monki socket that we are holding
- if ((sk = monkiSk)) {
- lock_sock(sk);
- sock_kfree_s(sk, sk->sk_user_data, sizeof(int));
- sk->sk_user_data = NULL;
- release_sock(sk);
- sock_put(sk);
- }
- break;
- }
- default: {
- retval = -EINVAL;
- break;
- }
- }
- return retval;
-}
-
-
-/**
- * @brief VMX receiving a packet from VMM.
- *
- * @param kiocb kernel io control block (unused)
- * @param sock user socket structure
- * @param msg user buffer to receive the packet
- * @param len size of the user buffer
- * @param flags flags
- *
- * @return -errno on failure, else length of untyped portion + total number
- * of bytes mapped for typed portion.
- */
-static int
-MksckDgramRecvMsg(struct kiocb *kiocb,
- struct socket *sock,
- struct msghdr *msg,
- size_t len,
- int flags)
-{
- int err = 0;
- struct sock *sk = sock->sk;
- Mksck *mksck;
- Mksck_Datagram *dg;
- struct sockaddr_mk *fromAddr;
- uint32 read;
- struct iovec *iov;
- size_t payloadLen, untypedLen;
- uint32 iovCount;
-
- if (flags & MSG_OOB || flags & MSG_ERRQUEUE) {
- return -EOPNOTSUPP;
- }
-
- if ((msg->msg_name != NULL) && (msg->msg_namelen < sizeof *fromAddr)) {
- return -EINVAL;
- }
-
- lock_sock(sk);
- if ((err = MksckTryBind(sk))) {
- release_sock(sk);
- return err;
- }
- mksck = sk->sk_protinfo;
-
- /*
- * To avoid mksck disappearing right after the release_sock the
- * refcount needs to be incremented. For more details read the
- * block comment on locking in MksckCreate.
- */
- ATOMIC_ADDV(mksck->refCount, 1);
- release_sock(sk);
-
- /*
- * Get pointer to next packet in ring to be dequeued.
- */
- while (1) {
-
- /*
- * Wait to make sure this is the only thread trying to access socket.
- */
- if ((err = Mutex_Lock(&mksck->mutex, MutexModeEX)) < 0) {
- goto decRefc;
- }
-
- /*
- * See if packet in ring.
- */
- read = mksck->read;
- if (read != mksck->write) {
- break;
- }
-
- /*
- * Nothing there, if user wants us not to block then just return EAGAIN.
- */
- if (flags & MSG_DONTWAIT) {
- Mutex_Unlock(&mksck->mutex, MutexModeEX);
- err = -EAGAIN;
- goto decRefc;
- }
-
- /*
- * Nothing there, unlock socket and wait for data.
- */
- mksck->foundEmpty ++;
- err = Mutex_UnlSleep(&mksck->mutex, MutexModeEX, MKSCK_CVAR_FILL);
- if (err < 0) {
- PRINTK(KERN_INFO "MksckDgramRecvMsg: aborted\n");
- goto decRefc;
- }
- }
-
- /*
- * Point to packet in ring.
- */
- dg = (void *)&mksck->buff[read];
-
- /*
- * Provide the address of the sender.
- */
- if (msg->msg_name != NULL) {
- fromAddr = (void *)msg->msg_name;
- fromAddr->mk_addr = dg->fromAddr;
- fromAddr->mk_family = AF_MKSCK;
- msg->msg_namelen = sizeof *fromAddr;
- } else {
- msg->msg_namelen = 0;
- }
-
- /*
- * Copy data from ring buffer to caller's buffer and remove packet from
- * ring buffer.
- */
- iov = msg->msg_iov;
- iovCount = msg->msg_iovlen;
- payloadLen = untypedLen =
- dg->len - dg->pages * sizeof(Mksck_PageDesc) - dg->pad;
-
- /*
- * Handle the untyped portion of the message.
- */
- if (untypedLen <= len) {
- err = memcpy_toiovec(iov,
- dg->data,
- untypedLen);
- if (err < 0) {
- printk("MksckDgramRecvMsg: Failed to memcpy_to_iovec untyped message component "
- "(buf len %d datagram len %d (untyped %d))\n",
- len,
- dg->len,
- untypedLen);
- }
- } else {
- err = -EINVAL;
- }
-
- /*
- * Map in the typed descriptor.
- */
- if (err >= 0 && dg->pages > 0) {
- Mksck_PageDesc *pd = (Mksck_PageDesc *)(dg->data + untypedLen + dg->pad);
-
- /*
- * There are 3 ways of receiving typed messages from the monitor.
- * - The typed message is mapped directly into a VMA. To indicate this the
- * userland sets msg_controllen == 0.
- * - The typed message is mapped directly into a VMA and a file descriptor
- * created for further mappings on the host (in same userland address
- * space or an alternate userland address space). In this case
- * msg_controllen should be set to sizeof(fd).
- * - The typed message is not mapped directly into a VMA, but a file
- * descriptor is created for later mapping on the host. In this case
- * msg_controllen should be set to sizeof(fd) and the supplied iovec
- * shall not specify a receive window.
- *
- * The conjuncts below decide on which of these 3 cases we've encountered.
- */
-
- if ((msg->msg_controllen <= 0) ||
- ((err = MksckPageDescToFd(sock, msg, pd, dg->pages)) != 0) ||
- (MsgHdrHasAvailableRoom(msg) != 0)) {
-
- down_write(&current->mm->mmap_sem); // lock for a change of mapping
- payloadLen += MksckPageDescMap(pd, dg->pages, iov, iovCount, NULL);
- up_write(&current->mm->mmap_sem);
- }
- }
-
- /*
- * Now that packet is removed, it is safe to unlock socket so another thread
- * can do a recv(). We also want to wake someone waiting for room to insert
- * a new packet.
- */
- if ((err >= 0) && Mksck_IncReadIndex(mksck, read, dg)) {
- Mutex_UnlWake(&mksck->mutex, MutexModeEX, MKSCK_CVAR_ROOM, true);
- } else {
- Mutex_Unlock(&mksck->mutex, MutexModeEX);
- }
-
- /*
- * If memcpy error, return error status.
- * Otherwise, return number of bytes copied.
- */
- if (err >= 0) {
- err = payloadLen;
- }
-
-decRefc:
- Mksck_DecRefc(mksck);
- return err;
-}
-
-
-/**
- * @brief VMX sending a packet to VMM.
- *
- * @param kiocb kernel io control block
- * @param sock user socket structure
- * @param msg packet to be transmitted
- * @param len length of the packet
- *
- * @return length of the sent msg on success, -errno on failure
- */
-static int
-MksckDgramSendMsg(struct kiocb *kiocb,
- struct socket *sock,
- struct msghdr *msg,
- size_t len)
-{
- int err = 0;
- struct sock *sk = sock->sk;
- Mksck *peerMksck;
- Mksck_Datagram *dg;
- uint32 needed;
- uint32 write;
- Mksck_Address fromAddr;
-
- if (msg->msg_flags & MSG_OOB) {
- return -EOPNOTSUPP;
- }
-
- if (len > MKSCK_XFER_MAX) {
- return -EMSGSIZE;
- }
-
- /*
- * In the next locked section peerMksck pointer needs to be set and
- * its refcount needs to be incremented.
- */
- lock_sock(sk);
- do {
- Mksck *mksck;
- Mksck_Address peerAddr =
- { .addr = (msg->msg_name ?
- ((struct sockaddr_mk *)msg->msg_name)->mk_addr.addr :
- MKSCK_ADDR_UNDEF) };
-
- if ((err = MksckTryBind(sk))) {
- break;
- }
- mksck = sk->sk_protinfo;
- fromAddr = mksck->addr;
-
- /*
- * If the socket is connected, use that address (no sendto for
- * connected sockets). Otherwise, use the provided address if any.
- */
- if ((peerMksck = mksck->peer)) {
- if (peerAddr.addr != MKSCK_ADDR_UNDEF &&
- peerAddr.addr != mksck->peerAddr.addr) {
- err = -EISCONN;
- break;
- }
- /*
- * To avoid mksckPeer disappearing right after the
- * release_sock the refcount needs to be incremented. For
- * more details read the block comment on locking in
- * MksckCreate.
- */
- ATOMIC_ADDV(peerMksck->refCount, 1);
- } else if (peerAddr.addr == MKSCK_ADDR_UNDEF) {
- err = -ENOTCONN;
- } else {
- /*
- * LockPeer also increments the refc on the peer.
- */
- err = LockPeer(peerAddr, &peerMksck);
- }
- } while(0);
- release_sock(sk);
-
- if (err) {
- return err;
- }
-
- /*
- * Get pointer to sufficient empty space in ring buffer.
- */
- needed = MKSCK_DGSIZE(len);
- while (1) {
- /*
- * Wait to make sure this is the only thread trying to write to ring.
- */
- if ((err = Mutex_Lock(&peerMksck->mutex, MutexModeEX)) < 0) {
- goto decRefc;
- }
-
- /*
- * Check if socket can receive data.
- */
- if (peerMksck->shutDown & MKSCK_SHUT_RD) {
- err = -ENOTCONN;
- goto unlockDecRefc;
- }
-
- /*
- * See if there is room for the packet.
- */
- write = Mksck_FindSendRoom(peerMksck, needed);
- if (write != MKSCK_FINDSENDROOM_FULL) {
- break;
- }
-
- /*
- * No room, unlock socket and maybe wait for room.
- */
- if (msg->msg_flags & MSG_DONTWAIT) {
- err = -EAGAIN;
- goto unlockDecRefc;
- }
-
- peerMksck->foundFull ++;
- err = Mutex_UnlSleep(&peerMksck->mutex,
- MutexModeEX,
- MKSCK_CVAR_ROOM);
- if (err < 0) {
- PRINTK(KERN_INFO "MksckDgramSendMsg: aborted\n");
- goto decRefc;
- }
- }
-
- /*
- * Point to room in ring and fill in message.
- */
- dg = (void *)&peerMksck->buff[write];
-
- dg->fromAddr = fromAddr;
- dg->len = len;
-
- if ((err = memcpy_fromiovec(dg->data, msg->msg_iov, len)) != 0) {
- goto unlockDecRefc;
- }
-
- /*
- * Increment past message.
- */
- Mksck_IncWriteIndex(peerMksck, write, needed);
-
- /*
- * Unlock socket and wake someone trying to receive, ie, we filled
- * in a message.
- */
- Mutex_UnlWake(&peerMksck->mutex, MutexModeEX, MKSCK_CVAR_FILL, false);
-
- /*
- * Maybe guest is in a general 'wait for interrupt' wait or
- * grinding away executing guest instructions.
- *
- * If it has a receive callback armed for the socket and is
- * waiting a message, just wake it up. Else send an IPI to the CPU
- * running the guest so it will interrupt whatever it is doing and
- * read the message.
- *
- * Holding the mksckPage->mutex prevents mksckPage->vmHKVA from
- * clearing on us.
- */
- if (peerMksck->rcvCBEntryMVA != 0) {
- MksckPage *peerMksckPage = Mksck_ToSharedPage(peerMksck);
-
- if ((err = Mutex_Lock(&peerMksckPage->mutex, MutexModeSH)) == 0) {
- uint32 sockIdx = peerMksck->index;
- MvpkmVM *vm = (MvpkmVM *) peerMksckPage->vmHKVA;
-
- /*
- * The destruction of vm and wsp is blocked by the
- * mksckPage->mutex.
- */
- if (vm) {
- WorldSwitchPage *wsp = vm->wsp;
-
- ASSERT(sockIdx < 8 * sizeof peerMksckPage->wakeVMMRecv);
- ATOMIC_ORV(peerMksckPage->wakeVMMRecv, 1U << sockIdx);
-
- if (wsp) {
- Mvpkm_WakeGuest(vm, ACTION_MKSCK);
- }
- }
- Mutex_Unlock(&peerMksckPage->mutex, MutexModeSH);
- }
- }
-
- /*
- * If all are happy tell the caller the number of transferred bytes.
- */
- if (!err) {
- err = len;
- }
-
- /*
- * Now that we are done with target socket, allow it to be freed.
- */
-decRefc:
- Mksck_DecRefc(peerMksck);
- return err;
-
-unlockDecRefc:
- Mutex_Unlock(&peerMksck->mutex, MutexModeEX);
- goto decRefc;
-}
-
-
-/**
- * @brief Page fault handler for receive windows. Since the host process
- * should not be faulting in this region and only be accessing
- * memory that has been established via a typed message transfer,
- * we always signal the fault back to the process.
- */
-static int
-MksckFault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- return VM_FAULT_SIGBUS;
-}
-
-/**
- * @brief Establish a region in the host process suitable for use as a
- * receive window.
- *
- * @param file file reference (ignored).
- * @param sock user socket structure.
- * @param vma Linux virtual memory area defining the region.
- *
- * @return 0 on success, otherwise error code.
- */
-static int
-MksckMMap(struct file *file, struct socket *sock, struct vm_area_struct *vma)
-{
- /*
- * All the hard work is done in MksckDgramRecvMsg. Here we simply mark the
- * vma as belonging to Mksck.
- */
- vma->vm_ops = &mksckVMOps;
-
- return 0;
-}
-
-/**
- * @brief This gets called after returning from the monitor.
- * Since the monitor doesn't directly wake VMX threads when it sends
- * something to VMX (for efficiency), this routine checks for the
- * omitted wakes and does them.
- * @param mksckPage some shared page that the monitor writes packets to, ie
- * an host shared page
- */
-void
-Mksck_WakeBlockedSockets(MksckPage *mksckPage)
-{
- Mksck *mksck;
- uint32 i, wakeHostRecv;
-
- wakeHostRecv = mksckPage->wakeHostRecv;
- if (wakeHostRecv != 0) {
- mksckPage->wakeHostRecv = 0;
- for (i = 0; wakeHostRecv != 0; i ++) {
- if (wakeHostRecv & 1) {
- mksck = &mksckPage->sockets[i];
- Mutex_CondSig(&mksck->mutex, MKSCK_CVAR_FILL, true);
- }
- wakeHostRecv >>= 1;
- }
- }
-}
-
-/**
- * @brief allocate and initialize a shared page.
- * @return pointer to shared page.<br>
- * NULL on error
- */
-MksckPage *
-MksckPageAlloc(void)
-{
- uint32 jj;
- /*
- * Ask for pages in the virtual kernel space. There is no
- * requirement to be physically contiguous.
- */
- MksckPage *mksckPage = vmalloc(MKSCKPAGE_SIZE);
-
- if (mksckPage) {
-
- /*
- * Initialize its contents. Start refCount at 1 and decrement it
- * when the worldswitch or VM page gets freed.
- */
- memset(mksckPage, 0, MKSCKPAGE_SIZE);
- ATOMIC_SETV(mksckPage->refCount, 1);
- mksckPage->portStore = MKSCK_PORT_HIGH;
-
- Mutex_Init(&mksckPage->mutex);
- for (jj = 0; jj<MKSCK_SOCKETS_PER_PAGE; jj++) {
- Mutex_Init(&mksckPage->sockets[jj].mutex);
- }
- }
-
- return mksckPage;
-}
-
-/**
- * @brief Release the allocated pages.
- * @param mksckPage the address of the mksckPage to be released
- */
-static void
-MksckPageRelease(MksckPage *mksckPage)
-{
- int ii;
-
- for (ii = 0; ii<MKSCK_SOCKETS_PER_PAGE; ii++) {
- Mutex_Destroy(&mksckPage->sockets[ii].mutex);
- }
- Mutex_Destroy(&mksckPage->mutex);
-
- vfree(mksckPage);
-}
-
-/**
- * @brief Using the tgid locate the vmid of this process.
- * Assumed that mksckPageListLock is held
- * @return the vmId if page is already allocated,
- * the first vacant vmid if not yet allocated.<br>
- * MKSCK_PORT_UNDEF if no slot is vacant
- */
-static inline Mksck_VmId
-GetHostVmId(void)
-{
- uint32 jj;
- Mksck_VmId vmId, vmIdFirstVacant = MKSCK_VMID_UNDEF;
- MksckPage *mksckPage;
- uint32 tgid = task_tgid_vnr(current);
- /*
- * Assign an unique vmId to the shared page. Start the search from
- * the vmId that is the result of hashing tgid to 15 bits. As a
- * used page with a given vmId can occupy only a given slot in the
- * mksckPages array, it is enough to search through the
- * MKSCK_MAX_SHARES slots for a vacancy.
- */
- for (jj = 0, vmId = MKSCK_TGID2VMID(tgid);
- jj < MKSCK_MAX_SHARES;
- jj++, vmId++) {
- if (vmId > MKSCK_VMID_HIGH) {
- vmId = 0;
- }
- mksckPage = mksckPages[MKSCK_VMID2IDX(vmId)];
-
- if (mksckPage) {
- if (mksckPage->tgid == tgid &&
- !mksckPage->isGuest) {
- return mksckPage->vmId;
- }
-
- } else if (vmIdFirstVacant == MKSCK_VMID_UNDEF) {
- vmIdFirstVacant = vmId;
- }
- }
- return vmIdFirstVacant;
-}
-
-
-/**
- * @brief Locate the first empty slot
- * Assumed that mksckPageListLock is held
- * @return the first vacant vmid.<br>
- * MKSCK_PORT_UNDEF if no slot is vacant
- */
-static inline Mksck_VmId
-GetNewGuestVmId(void)
-{
- Mksck_VmId vmId;
-
- for (vmId = 0; vmId < MKSCK_MAX_SHARES; vmId++) {
- if (!mksckPages[MKSCK_VMID2IDX(vmId)]) {
- return vmId;
- }
- }
- return MKSCK_VMID_UNDEF;
-}
-
-
-/**
- * @brief Find shared page for a given idx. The page referred to be the
- * idx should exist and be locked by the caller.
- * @param idx index of the page in the array
- * @return pointer to shared page
- */
-MksckPage *
-MksckPage_GetFromIdx(uint32 idx)
-{
- MksckPage *mksckPage = mksckPages[idx];
- ASSERT(mksckPage);
- ASSERT(idx<MKSCK_MAX_SHARES);
- ASSERT(ATOMIC_GETO(mksckPage->refCount));
- return mksckPage;
-}
-
-/**
- * @brief find shared page for a given vmId
- * The vmid should exist and be locked by the caller.
- * @param vmId vmId to look for, either an host vmId or a guest vmId
- * @return pointer to shared page
- */
-MksckPage *
-MksckPage_GetFromVmId(Mksck_VmId vmId)
-{
- MksckPage *mksckPage = mksckPages[MKSCK_VMID2IDX(vmId)];
- ASSERT(mksckPage);
- ASSERT(mksckPage->vmId == vmId);
- ASSERT(ATOMIC_GETO(mksckPage->refCount));
- return mksckPage;
-}
-
-
-/**
- * @brief find shared page for a given vmId
- * @param vmId vmId to look for, either an host vmId or a guest vmId
- * @return NULL: no such shared page exists<br>
- * else: pointer to shared page.
- * Call Mksck_DecRefc() when done with pointer
- */
-MksckPage *
-MksckPage_GetFromVmIdIncRefc(Mksck_VmId vmId)
-{
- MksckPage *mksckPage;
-
- spin_lock(&mksckPageListLock);
- mksckPage = mksckPages[MKSCK_VMID2IDX(vmId)];
-
- if (!mksckPage || (mksckPage->vmId != vmId)) {
- printk(KERN_INFO "MksckPage_GetFromVmIdIncRefc: vmId %04X not found\n",
- vmId);
- mksckPage = NULL;
- } else {
- ATOMIC_ADDV(mksckPage->refCount, 1);
- }
- spin_unlock(&mksckPageListLock);
- return mksckPage;
-}
-
-
-/**
- * @brief find or allocate shared page using tgid
- * @return NULL: no such shared page exists<br>
- * else: pointer to shared page.
- * Call Mksck_DecRefc() when done with pointer
- */
-MksckPage *
-MksckPage_GetFromTgidIncRefc(void)
-{
- MksckPage *mksckPage;
- Mksck_VmId vmId;
-
- while (1) {
- spin_lock(&mksckPageListLock);
- vmId = GetHostVmId();
-
- if (vmId == MKSCK_VMID_UNDEF) {
- /*
- * No vmId has been allocated yet and there is no free slot.
- */
- spin_unlock(&mksckPageListLock);
- return NULL;
- }
-
- mksckPage = mksckPages[MKSCK_VMID2IDX(vmId)];
- if (mksckPage != NULL) {
- /*
- * There is a vmid already allocated, increment the refc on it.
- */
- ATOMIC_ADDV(mksckPage->refCount, 1);
- spin_unlock(&mksckPageListLock);
- return mksckPage;
- }
-
- /*
- * Have to release spinlock to allocate a new page.
- */
- spin_unlock(&mksckPageListLock);
- mksckPage = MksckPageAlloc();
- if (mksckPage == NULL) {
- return NULL;
- }
-
- /*
- * Re-lock and make sure no one else allocated while unlocked.
- * If someone else did allocate, free ours off and use theirs.
- */
- spin_lock(&mksckPageListLock);
- vmId = GetHostVmId();
- if ((vmId != MKSCK_VMID_UNDEF) &&
- (mksckPages[MKSCK_VMID2IDX(vmId)] == NULL)) {
- break;
- }
- spin_unlock(&mksckPageListLock);
- MksckPageRelease(mksckPage);
- }
-
- /*
- * This is a successful new allocation. insert it into the table
- * and initialize the fields.
- */
- mksckPages[MKSCK_VMID2IDX(vmId)] = mksckPage;
- mksckPage->vmId = vmId;
- mksckPage->isGuest = false;
- mksckPage->vmHKVA = 0;
- mksckPage->tgid = task_tgid_vnr(current);
- printk(KERN_DEBUG "New host mksck page is allocated: idx %x, vmId %x, tgid %d\n",
- MKSCK_VMID2IDX(vmId), vmId, mksckPage->tgid);
-
- spin_unlock(&mksckPageListLock);
- return mksckPage;
-}
-
-/**
- * @brief Initialize the VMX provided wsp. Allocate communication page.
- * @param vm which virtual machine we're running
- * @return 0 if all OK, error value otherwise
- */
-int
-Mksck_WspInitialize(MvpkmVM *vm)
-{
- WorldSwitchPage *wsp = vm->wsp;
- int err;
- Mksck_VmId vmId;
- MksckPage *mksckPage;
-
- if (wsp->guestId) {
- err = -EBUSY;
- } else if (!(mksckPage = MksckPageAlloc())) {
- err = -ENOMEM;
- } else {
- spin_lock(&mksckPageListLock);
-
- if ((vmId = GetNewGuestVmId()) == MKSCK_VMID_UNDEF) {
-
- err = -EMFILE;
- MksckPageRelease(mksckPage);
-
- printk(KERN_INFO "Mksck_WspInitialize: Cannot allocate vmId\n");
-
- } else {
- /*
- * Now that the mksckPage is all initialized, let others see it.
- */
- mksckPages[MKSCK_VMID2IDX(vmId)] = mksckPage;
- mksckPage->vmId = vmId;
- mksckPage->isGuest = true;
- mksckPage->vmHKVA = (HKVA)vm;
- /* mksckPage->tgid is undefined when isGuest is true */
-
- wsp->guestId = vmId;
-
- printk(KERN_DEBUG "New guest mksck page is allocated: idx %x, vmId %x\n",
- MKSCK_VMID2IDX(vmId), vmId);
-
- err = 0;
- }
-
- /*
- * All stable, ie, mksckPages[] written, ok to unlock now.
- */
- spin_unlock(&mksckPageListLock);
- }
-
- return err;
-}
-
-/**
- * @brief Release the wsp. Clean up after the monitor. Free the
- * associated communication page.
- * @param wsp which worldswitch page (VCPU)
- */
-void
-Mksck_WspRelease(WorldSwitchPage *wsp)
-{
- int ii;
- int err;
- MksckPage *mksckPage = MksckPage_GetFromVmId(wsp->guestId);
-
- /*
- * The worldswitch page for a particular VCPU is about to be freed
- * off, so we know the monitor will never execute again. But the
- * monitor most likely left some sockets open. Those may have
- * outbound connections to host sockets that we must close.
- *
- * Loop through all possibly open sockets.
- */
- uint32 isOpened = wsp->isOpened;
- Mksck *mksck = mksckPage->sockets;
- while (isOpened) {
- if (isOpened & 1) {
- ASSERT(ATOMIC_GETO(mksck->refCount) != 0);
- /*
- * The socket may be connected to a peer (host) socket, so we
- * have to decrement that target socket's reference
- * count. Unfortunately, Mksck_DisconnectPeer(mksck) cannot
- * be called as mksck->peer is an mva not an hkva. Translate
- * the address first.
- */
- if (mksck->peer) {
- MksckPage *mksckPagePeer = MksckPage_GetFromVmId(mksck->peerAddr.vmId);
- ASSERT(mksckPagePeer);
- mksck->peer = MksckPage_GetFromAddr(mksckPagePeer, mksck->peerAddr);
- ASSERT(mksck->peer);
- /* mksck->peer is now a hkva */
- }
-
- Mksck_CloseCommon(mksck);
- }
- isOpened >>= 1;
- mksck++;
- }
-
- /*
- * A host socket may be in the process of sending to the guest. It
- * will attempt to wake up the guest using mksckPage->vmHKVA and
- * mksckPage->vmHKVA->wsp. To assure that the vm and wsp structures
- * are not disappearing from under the sending thread we lock the
- * page here.
- */
- err = Mutex_Lock(&mksckPage->mutex, MutexModeEX);
- ASSERT(!err);
- mksckPage->vmHKVA = 0;
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
- /*
- * Decrement refcount set by MksckPageAlloc() call in
- * Mksck_WspInitialize().
- */
- MksckPage_DecRefc(mksckPage);
-
- /*
- * Decrement refcount set by VMM:Mksck_Init() referring to the local
- * variable guestMksckPage.
- */
- if (wsp->guestPageMapped) {
- wsp->guestPageMapped = false;
- MksckPage_DecRefc(mksckPage);
- }
-
- /*
- * Another task is to decrement the reference count on the mksck
- * pages the monitor accessed. Those pages are listed in the
- * wsp->isPageMapped list. They were locked by the monitor
- * calling WSCALL_GET_PAGE_FROM_VMID
- */
- for (ii = 0; ii < MKSCK_MAX_SHARES; ii++) {
- if (wsp->isPageMapped[ii]) {
- MksckPage *mksckPageOther = MksckPage_GetFromIdx(ii);
-
- wsp->isPageMapped[ii] = false;
- MksckPage_DecRefc(mksckPageOther);
- }
- }
-}
-
-/**
- * @brief disconnect from peer by decrementing
- * peer socket's reference count and clearing the pointer.
- * @param mksck local socket to check for connection
- */
-void
-Mksck_DisconnectPeer(Mksck *mksck)
-{
- Mksck *peerMksck = mksck->peer;
- if (peerMksck != NULL) {
- mksck->peer = NULL;
- mksck->peerAddr.addr = MKSCK_ADDR_UNDEF;
- Mksck_DecRefc(peerMksck);
- }
-}
-
-
-/**
- * @brief decrement shared page reference count, free page if it goes zero.
- * also do a dmb first to make sure all activity on the struct is
- * finished before decrementing the ref count.
- * @param mksckPage shared page
- */
-void
-MksckPage_DecRefc(MksckPage *mksckPage)
-{
- uint32 oldRefc;
-
- DMB();
- do {
- while ((oldRefc = ATOMIC_GETO(mksckPage->refCount)) == 1) {
-
- /*
- * Find corresponding entry in list of known shared pages and
- * clear it so we can't open any new sockets on this shared
- * page, thus preventing its refCount from being incremented.
- */
- spin_lock(&mksckPageListLock);
- if (ATOMIC_SETIF(mksckPage->refCount, 0, 1)) {
- uint32 ii = MKSCK_VMID2IDX(mksckPage->vmId);
- ASSERT(ii < MKSCK_MAX_SHARES);
- ASSERT(mksckPages[ii] == mksckPage);
- mksckPages[ii] = NULL;
- spin_unlock(&mksckPageListLock);
- printk(KERN_DEBUG "%s mksck page is released: idx %x, vmId %x, tgid %d\n",
- mksckPage->isGuest?"Guest":"Host",
- ii, mksckPage->vmId, mksckPage->tgid);
- MksckPageRelease(mksckPage);
- return;
- }
- spin_unlock(&mksckPageListLock);
- }
- ASSERT(oldRefc != 0);
- } while (!ATOMIC_SETIF(mksckPage->refCount, oldRefc - 1, oldRefc));
-}
-
-/**
- * @brief Lookup if the provided mpn belongs to one of the Mksck pages. Map if found.
- * @return 0 if all OK, error value otherwise
- */
-int
-MksckPage_LookupAndInsertPage(struct vm_area_struct *vma,
- unsigned long address,
- MPN mpn)
-{
- int ii, jj;
- MksckPage **mksckPagePtr = mksckPages;
-
- spin_lock(&mksckPageListLock);
- for (jj = MKSCK_MAX_SHARES; jj--; mksckPagePtr++) {
- if (*mksckPagePtr) {
- for (ii = 0; ii < MKSCKPAGE_TOTAL; ii++) {
- if (vmalloc_to_pfn((void*)(((HKVA)*mksckPagePtr) + ii*PAGE_SIZE)) == mpn &&
- vm_insert_page(vma, address, pfn_to_page(mpn)) == 0) {
- spin_unlock(&mksckPageListLock);
- return 0;
- }
- }
- }
- }
- spin_unlock(&mksckPageListLock);
- return -1;
-}
-
-
-/**
- * @brief Print information on the allocated shared pages
- *
- * This function reports (among many other things) on the use of locks
- * on the mksck page (page lock and individual socket locks). To avoid
- * the Hiesenberg effect it avoids using locks unless there is a
- * danger of dereferencing freed memory. In particular, holding
- * mksckPageListLock ensures that the mksck page is not freed while it
- * is read. But under very rare conditions this function may report
- * inconsistent or garbage data.
- */
-static int
-MksckPageInfoShow(struct seq_file *m, void *private)
-{
- int ii, jj;
- uint32 isPageMapped = 0;
- int err;
- MvpkmVM *vm;
-
- /*
- * Lock is needed to atomize the test and dereference of
- * mksckPages[ii]
- */
- spin_lock(&mksckPageListLock);
- for (ii = 0; ii < MKSCK_MAX_SHARES; ii++) {
- MksckPage *mksckPage = mksckPages[ii];
- if (mksckPage != NULL && mksckPage->isGuest) {
- /*
- * After the refcount is incremented mksckPage will not be
- * freed and it can continued to be dereferenced after the
- * unlock of mksckPageListLock.
- */
- ATOMIC_ADDV(mksckPage->refCount, 1);
- spin_unlock(&mksckPageListLock);
-
- /*
- * To dereference mksckPage->vmHKVA, we need to have the page
- * lock.
- */
- err = Mutex_Lock(&mksckPage->mutex, MutexModeEX);
- vm = (MvpkmVM *) mksckPage->vmHKVA;
-
- if (err == 0 && vm && vm->wsp) {
- for (jj = 0; jj < MKSCK_MAX_SHARES; jj++) {
- if (vm->wsp->isPageMapped[jj]) isPageMapped |= 1<<jj;
- }
- }
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
- /*
- * Decrement the page refcount and relock the
- * mksckPageListLock for the next for loop.
- */
- MksckPage_DecRefc(mksckPage);
- spin_lock(&mksckPageListLock);
- break;
- }
- }
-
- /* mksckPageListLock is still locked, mksckPages[ii] can be dereferenced */
- for (ii = 0; ii < MKSCK_MAX_SHARES; ii++) {
- MksckPage *mksckPage = mksckPages[ii];
- if (mksckPage != NULL) {
- uint32 lState = ATOMIC_GETO(mksckPage->mutex.state);
- uint32 isOpened = 0; /* guest has an implicit ref */
-
- seq_printf(m, "MksckPage[%02d]: { vmId = %4x(%c), refC = %2d%s",
- ii, mksckPage->vmId,
- mksckPage->isGuest?'G':'H',
- ATOMIC_GETO(mksckPage->refCount),
- (isPageMapped&(1<<ii) ? "*" : ""));
-
- if (lState) {
- seq_printf(m, ", lock=%x locked by line %d, unlocked by %d",
- lState, mksckPage->mutex.line, mksckPage->mutex.lineUnl);
- }
-
-
- if (!mksckPage->isGuest) {
- struct task_struct *target;
- seq_printf(m, ", tgid = %d", mksckPage->tgid);
-
- rcu_read_lock();
-
- target = pid_task(find_vpid(mksckPage->tgid), PIDTYPE_PID);
- seq_printf(m, "(%s)", target ? target->comm : "no such process");
-
- rcu_read_unlock();
- } else {
- ATOMIC_ADDV(mksckPage->refCount, 1);
- spin_unlock(&mksckPageListLock);
-
- err = Mutex_Lock(&mksckPage->mutex, MutexModeEX);
- vm = (MvpkmVM *) mksckPage->vmHKVA;
-
- if (err == 0 && vm && vm->wsp) {
- isOpened = vm->wsp->isOpened;
- }
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
- MksckPage_DecRefc(mksckPage);
- spin_lock(&mksckPageListLock);
- /*
- * As the mksckPageListLock was unlocked, nothing
- * prevented the MksckPage_DecRefc from actually freeing
- * the page. Lets verify that the page is still there.
- */
- if (mksckPage != mksckPages[ii]) {
- seq_printf(m, " released }\n");
- continue;
- }
- }
- seq_printf(m, ", sockets[] = {");
-
- for (jj = 0; jj < mksckPage->numAllocSocks; jj++, isOpened >>= 1) {
- Mksck *mksck = mksckPage->sockets + jj;
-
- if (ATOMIC_GETO(mksck->refCount)) {
- uint32 blocked;
- lState = ATOMIC_GETO(mksck->mutex.state);
- seq_printf(m, "\n { addr = %8x, refC = %2d%s%s%s",
- mksck->addr.addr,
- ATOMIC_GETO(mksck->refCount),
- (isOpened & 1 ? "*" : ""),
- (mksck->shutDown & MKSCK_SHUT_RD ? " SHUTD_RD":""),
- (mksck->shutDown & MKSCK_SHUT_WR ? " SHUTD_WR":""));
-
- if (mksck->peer) {
- seq_printf(m, ", peerAddr = %8x",
- mksck->peerAddr.addr);
- }
-
- if (lState) {
- seq_printf(m, ", lock=%x locked by line %d, unlocked by %d",
- lState, mksck->mutex.line, mksck->mutex.lineUnl);
- }
-
- if ((blocked = ATOMIC_GETO(mksck->mutex.blocked))) {
- seq_printf(m, ", blocked=%d", blocked);
- }
-
- seq_printf(m, " }");
- }
- }
- seq_printf(m, " } }\n");
- }
- }
- spin_unlock(&mksckPageListLock);
-
- return 0;
-}
-
-
-static int
-MksckPageInfoOpen(struct inode *inode, struct file *file)
-{
- return single_open(file, MksckPageInfoShow, inode->i_private);
-}
-
-static const struct file_operations mksckPageInfoFops = {
- .open = MksckPageInfoOpen,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static struct dentry *mksckPageDentry = NULL;
-
-void
-MksckPageInfo_Init(void)
-{
- mksckPageDentry = debugfs_create_file("mksckPage",
- S_IROTH,
- NULL,
- NULL,
- &mksckPageInfoFops);
-}
-
-void
-MksckPageInfo_Exit(void)
-{
- if (mksckPageDentry) {
- debugfs_remove(mksckPageDentry);
- }
-}
diff --git a/arch/arm/mvp/mvpkm/mksck_kernel.h b/arch/arm/mvp/mvpkm/mksck_kernel.h
deleted file mode 100644
index 233b780..0000000
--- a/arch/arm/mvp/mvpkm/mksck_kernel.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The monitor-kernel socket interface kernel-only definitions.
- */
-
-#ifndef _MKSCK_KERNEL_H
-#define _MKSCK_KERNEL_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mksck_shared.h"
-
-/*
- * prototypes
- */
-int Mksck_Init(void);
-void Mksck_Exit(void);
-void Mksck_WakeBlockedSockets(MksckPage *mksckPage);
-MksckPage *MksckPage_GetFromTgidIncRefc(void);
-MksckPage *MksckPage_GetFromVmIdIncRefc(Mksck_VmId vmId);
-MksckPage *MksckPage_GetFromIdx(uint32 idx);
-void MksckPageInfo_Init(void);
-void MksckPageInfo_Exit(void);
-int Mksck_WspInitialize(MvpkmVM *vm);
-void Mksck_WspRelease(WorldSwitchPage *wsp);
-int MksckPage_LookupAndInsertPage(struct vm_area_struct *vma,
- unsigned long address,
- MPN mpn);
-
-/*
- * Mksck open request must come from this uid.
- */
-extern uid_t Mvpkm_vmwareUid;
-
-#define MKSCK_DEVEL 0
-
-#if MKSCK_DEVEL
-#define PRINTK printk
-#else
-#define PRINTK if (0) printk
-#endif
-
-#define HOST_CPUID_UNDEF (~0)
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mksck_shared.c b/arch/arm/mvp/mvpkm/mksck_shared.c
deleted file mode 100644
index 68c38fc6..0000000
--- a/arch/arm/mvp/mvpkm/mksck_shared.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#include "mvp.h"
-#include "mksck_shared.h"
-
-/**
- * @file
- *
- * @brief The mksck shared area functions used by the monitor and the
- * kernel extension.
- *
- */
-
-/**
- * @brief try to locate a socket using an address.
- * @param mksckPage which shared page to look on.
- * ASSUMED: locked for shared access
- * @param addr address to check
- * @return pointer to mksck page with addr.
- * NULL if not found
- */
-Mksck *
-MksckPage_GetFromAddr(MksckPage *mksckPage, Mksck_Address addr)
-{
- Mksck *mksck = mksckPage->sockets;
- uint32 ii;
-
- ASSERT(addr.vmId == mksckPage->vmId);
-
- for (ii = mksckPage->numAllocSocks; ii--; mksck++) {
- if ((ATOMIC_GETO(mksck->refCount) != 0) &&
- (mksck->addr.addr == addr.addr)) {
- return mksck;
- }
- }
- return NULL;
-}
-
-/**
- * @brief Close a monitor socket.
- *
- * @param mksck pointer to the socket control block
- */
-void
-Mksck_CloseCommon(Mksck *mksck)
-{
- /*
- * If a peer was connected, release the peer.
- */
- Mksck_DisconnectPeer(mksck);
-
- /*
- * Signal senders that this socket won't be read anymore.
- */
- while (Mutex_Lock(&mksck->mutex, MutexModeEX) < 0);
- mksck->shutDown = MKSCK_SHUT_WR | MKSCK_SHUT_RD;
- Mutex_UnlWake(&mksck->mutex, MutexModeEX, MKSCK_CVAR_ROOM, true);
-
- /*
- * Decrement reference count because it was set to 1 when opened. It could
- * still be non-zero after this if some other thread is currently sending to
- * this socket.
- */
- Mksck_DecRefc(mksck);
-}
-
-
-/**
- * @brief decrement socket reference count, free if it goes zero. Also do a
- * dmb first to make sure all activity on the struct is finished before
- * decrementing the ref count.
- * @param mksck socket
- */
-void
-Mksck_DecRefc(Mksck *mksck)
-{
- uint32 oldRefc;
-
- DMB();
- do {
- while ((oldRefc = ATOMIC_GETO(mksck->refCount)) == 1) {
-
- MksckPage *mksckPage = Mksck_ToSharedPage(mksck);
-
- /*
- * Socket refcount is going zero on a socket that locks mksckPage in.
- * Lock shared page exclusive to make sure no one is trying to look
- * for this socket, thus preventing socket's refcount from being
- * incremented non-zero once we decrement it to zero.
- */
-
- /*
- * Lock failed probably because of an interrupt. Keep trying
- * to lock until we succeed.
- */
- while (Mutex_Lock(&mksckPage->mutex, MutexModeEX) < 0);
-
- /*
- * No one is doing any lookups, so set refcount zero.
- */
- if (ATOMIC_SETIF(mksck->refCount, 0, 1)) {
-#if 0
- /**
- * @knownjira{MVP-1349}
- * The standard Log is not yet implemented in the kernel space.
- */
- KNOWN_BUG(MVP-1349);
- PRINTK(KERN_INFO "Mksck_DecRefc: %08X shutDown %u, foundEmpty %u,"
- " foundFull %u, blocked %u\n",
- mksck->addr.addr, mksck->shutDown,
- mksck->foundEmpty, mksck->foundFull,
- ATOMIC_GETO(mksck->mutex.blocked));
-#endif
-
- /*
- * Sockets can't have connected peers by the time their
- * refc hits 0. The owner should have cleaned that up by
- * now.
- */
- ASSERT(mksck->peer == 0);
-
- /*
- * Successfully set to zero, release mutex and decrement
- * shared page ref count as it was incremented when the
- * socket was opened. This may free the shared page.
- */
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
- MksckPage_DecRefc(mksckPage);
- return;
- }
-
- /*
- * Someone incremented refcount just before we locked the mutex, so
- * try it all again.
- */
- Mutex_Unlock(&mksckPage->mutex, MutexModeEX);
- }
-
- /*
- * Not going zero or doesn't lock mksckPage, simple decrement.
- */
- ASSERT(oldRefc != 0);
- } while (!ATOMIC_SETIF(mksck->refCount, oldRefc - 1, oldRefc));
-}
-
-
-/**
- * @brief Find an unused port.
- * @param mksckPage which shared page to look in.
- * Locked for exclusive access
- * @param port if not MKSCK_PORT_UNDEF test only this port
- * @return port allocated or MKSCK_PORT_UNDEF if none was found
- */
-Mksck_Port
-MksckPage_GetFreePort(MksckPage *mksckPage, Mksck_Port port)
-{
- Mksck_Address addr = { .addr = Mksck_AddrInit(mksckPage->vmId, port) };
- uint32 ii;
-
- if (port == MKSCK_PORT_UNDEF) {
- for (ii = 0; ii<MKSCK_SOCKETS_PER_PAGE; ii++) {
-
- /*
- * Find an unused local socket number.
- */
- addr.port = mksckPage->portStore--;
- if (!addr.port) {
-
- /*
- * Wrapped around, reset portStore
- */
- mksckPage->portStore = MKSCK_PORT_HIGH;
- }
-
- if (!MksckPage_GetFromAddr(mksckPage, addr)) {
- return addr.port;
- }
- }
-
- } else if (!MksckPage_GetFromAddr(mksckPage, addr)) {
- return addr.port;
- }
-
- return MKSCK_PORT_UNDEF;
-}
-
-/**
- * @brief Find an unused slot in the sockets[] array and allocate it.
- * @param mksckPage which shared page to look in.
- * Locked for exclusive access
- * @param addr what local address to assign to the socket
- * @return NULL: no slots available <br>
- * else: pointer to allocated socket
- */
-Mksck *
-MksckPage_AllocSocket(MksckPage *mksckPage, Mksck_Address addr)
-{
- Mksck *mksck;
- uint32 i;
-
- for (i = 0; (offsetof(MksckPage, sockets[i+1]) <= MKSCKPAGE_SIZE) &&
- (i < 8 * sizeof mksckPage->wakeHostRecv) &&
- (i < 8 * sizeof mksckPage->wakeVMMRecv); i ++) {
- mksck = &mksckPage->sockets[i];
- if (ATOMIC_GETO(mksck->refCount) == 0) {
- ATOMIC_SETV(mksck->refCount, 1);
- mksck->addr = addr;
- mksck->peerAddr.addr = MKSCK_ADDR_UNDEF;
- mksck->peer = NULL;
- mksck->index = i;
- mksck->write = 0;
- mksck->read = 0;
- mksck->shutDown = 0;
- mksck->foundEmpty = 0;
- mksck->foundFull = 0;
- ATOMIC_SETV(mksck->mutex.blocked, 0);
- mksck->rcvCBEntryMVA = 0;
- mksck->rcvCBParamMVA = 0;
-
- if (mksckPage->numAllocSocks < ++ i) {
- mksckPage->numAllocSocks = i;
- }
-
- return mksck;
- }
- }
- return NULL;
-}
-
-
-/**
- * @brief increment read index over the packet just read
- * @param mksck socket packet was read from.
- * Locked for exclusive access
- * @param read current value of mksck->read
- * @param dg datagram at current mksck->read
- * @return with mksck->read updated to next packet <br>
- * false: buffer not empty <br>
- * true: buffer now empty
- */
-_Bool
-Mksck_IncReadIndex(Mksck *mksck, uint32 read, Mksck_Datagram *dg)
-{
- ASSERT(read == mksck->read);
- ASSERT((void *)dg == (void *)&mksck->buff[read]);
-
- read += MKSCK_DGSIZE(dg->len);
- if ((read > mksck->write) && (read >= mksck->wrap)) {
- ASSERT(read == mksck->wrap);
- read = 0;
- }
- mksck->read = read;
-
- return read == mksck->write;
-}
-
-
-/**
- * @brief find index in buffer that has enough room for a packet
- * @param mksck socket message is being sent to.
- * Locked for exclusive access
- * @param needed room needed, including dg header and rounded up
- * @return MKSCK_FINDSENDROOM_FULL: not enough room available <br>
- * else: index in mksck->buff for packet
- */
-uint32
-Mksck_FindSendRoom(Mksck *mksck, uint32 needed)
-{
- uint32 read, write;
-
- /*
- * We must leave at least one byte unused so receiver can distinguish full
- * from empty.
- */
- read = mksck->read;
- write = mksck->write;
- if (write == read) {
- if (needed < MKSCK_BUFSIZE) {
- mksck->read = 0;
- mksck->write = 0;
- return 0;
- }
- } else if (write < read) {
- if (write + needed < read) {
- return write;
- }
- } else {
- if (write + needed < MKSCK_BUFSIZE) {
- return write;
- }
- if ((write + needed == MKSCK_BUFSIZE) && (read > 0)) {
- return write;
- }
- if (needed < read) {
- mksck->wrap = write;
- mksck->write = 0;
- return 0;
- }
- }
-
- return MKSCK_FINDSENDROOM_FULL;
-}
-
-
-/**
- * @brief increment read index over the packet just written
- * @param mksck socket packet was written to.
- * Locked for exclusive access
- * @param write as returned by @ref Mksck_FindSendRoom
- * @param needed as passed to @ref Mksck_FindSendRoom
- * @return with mksck->write updated to next packet
- */
-void
-Mksck_IncWriteIndex(Mksck *mksck, uint32 write, uint32 needed)
-{
- ASSERT(write == mksck->write);
- write += needed;
- if (write >= MKSCK_BUFSIZE) {
- ASSERT(write == MKSCK_BUFSIZE);
- mksck->wrap = MKSCK_BUFSIZE;
- write = 0;
- }
- ASSERT(write != mksck->read);
- mksck->write = write;
-}
diff --git a/arch/arm/mvp/mvpkm/mksck_shared.h b/arch/arm/mvp/mvpkm/mksck_shared.h
deleted file mode 100644
index 2677ec1..0000000
--- a/arch/arm/mvp/mvpkm/mksck_shared.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The monitor-kernel socket interface shared area definitions.
- */
-
-#ifndef _MKSCK_SHARED_H
-#define _MKSCK_SHARED_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/*
- * Allocated MksckPages are stored in an array of size
- * MKSCK_MAX_SHARES. The vmid and the slot index of a shared page is
- * not unrelated: vmid = idx%MKSCK_MAX_SHARES.
- */
-#define MKSCK_MAX_SHARES_LOG2 4 // 16: one per VM + one per VCPU
-#define MKSCK_MAX_SHARES (1U << MKSCK_MAX_SHARES_LOG2)
-#define MKSCK_VMID2IDX(idx) ((idx)%MKSCK_MAX_SHARES)
-#define MKSCK_TGID2VMID(tgid) (((((tgid)<<1)^((tgid)>>15))&0xfffe)|1)
-/*
- * The size of a shared page determines how many sockets can be open
- * concurrently.
- */
-#define MKSCKPAGE_TOTAL 8 // number of shared pages
-#define MKSCKPAGE_SIZE (PAGE_SIZE * MKSCKPAGE_TOTAL)
-#define MKSCK_SOCKETS_PER_PAGE ((MKSCKPAGE_SIZE-offsetof(MksckPage, sockets[0])) / \
- sizeof(Mksck))
-
-/*
- * Individual datagrams are aligned on a MKSCK_ALIGNMENT byte boundary
- * in the data receive area of a socket.
- */
-#define MKSCK_ALIGNMENT 8 // data packet alignment
-#define MKSCK_ALIGN(x) MVP_ALIGN(x, MKSCK_ALIGNMENT)
-#define MKSCK_DGSIZE(len) offsetof(Mksck_Datagram, data[MKSCK_ALIGN(len)])
-#define MKSCK_BUFSIZE MKSCK_DGSIZE(MKSCK_XFER_MAX + 1)
-
-/*
- * Conditional variables for sleeping on.
- */
-#define MKSCK_CVAR_ROOM 0 // senders waiting for room for message
-#define MKSCK_CVAR_FILL 1 // receivers waiting for a message to fetch
-
-#define MKSCK_FINDSENDROOM_FULL 0xFFFFFFFFU
-
-/*
- * Shutdown bits
- */
-#define MKSCK_SHUT_WR (1 << 0) // socket can't send data anymore
-#define MKSCK_SHUT_RD (1 << 1) // socket can't receive data anymore
-
-typedef struct Mksck Mksck;
-typedef struct Mksck_Datagram Mksck_Datagram;
-typedef struct MksckPage MksckPage;
-
-#include "atomic.h"
-#include "mksck.h"
-#include "mmu_defs.h"
-#include "mutex.h"
-#include "arm_inline.h"
-
-/**
- * @brief Monitor-kernel socket datagram structure
- */
-struct Mksck_Datagram {
- Mksck_Address fromAddr; ///< source address
- uint32 len : 16; ///< length of the data
- uint32 pad : 3; ///< padding between untyped message and mpn
- ///< array.
- uint32 pages : 13; ///< number of pages in mpn array
- uint8 data[1] ///< start of the data
- __attribute__((aligned(MKSCK_ALIGNMENT)));
-};
-
-/**
- * @brief one particular socket's shared page data.
- */
-struct Mksck {
- AtmUInt32 refCount; ///< when zero, struct is free
- ///< ... increment only with mksckPage->mutex
- ///< ... decrement at any time
- Mksck_Address addr; ///< this socket's address if open
- ///< ... MKSCK_ADDR_UNDEF if closed
- ///< ... open only with mksckPage->mutex
- Mksck_Address peerAddr; ///< peer's address if connected
- ///< ... MKSCK_ADDR_UNDEF if not
- struct Mksck *peer; ///< connected peer's ptr or NULL if not
- ///< ... ptr is MVA for monitor sockets and
- ///< ... HKVA for sockets of host processes
- ///< ... holds ref count on target socket
- uint32 index; ///< index of this socket in page
-
- ///< empty ring indicated by read == write
- ///< ring never completely fills, always at
- ///< least room for one more byte so we can tell
- ///< empty from full
-
- uint32 write; ///< index within buff to insert next data
- ///< ... always < MKSCK_BUFSIZE
- uint32 read; ///< index within buff to remove next data
- ///< ... always < MKSCK_BUFSIZE
- uint32 wrap; ///< current wrapping point
- ///< ... valid only whenever write < read
- uint32 shutDown; ///< MKSCK_SHUT_RD, MKSCK_SHUT_WR bitfield
- uint32 foundEmpty; ///< number of times a receive has blocked
- uint32 foundFull; ///< number of times a send has blocked
- Mutex mutex; ///< locks the ring buffer
- MVA rcvCBEntryMVA; ///< monitor's receive callback entrypoint
- MVA rcvCBParamMVA; ///< monitor's receive callback parameter
- uint8 buff[MKSCK_BUFSIZE] ///< data going TO this socket
- __attribute__((aligned(MKSCK_ALIGNMENT)));
-};
-
-
-/**
- * @brief the shared page of an address domain (vmId)
- */
-struct MksckPage {
- _Bool isGuest; ///< the page belongs to a monitor/guest
- uint32 tgid; ///< thread group id if isGuest=true
- ///< undefined otherwise
- volatile HKVA vmHKVA; ///< host side local data structure for vm
- AtmUInt32 refCount; ///< page cannot be freed unless this is zero
- ///< ... increment only with mksckPageListLock
- ///< ... decrement at any time
- ///< ... initialized to 1 for wsp->mksckPage* pointers
- uint32 wakeHostRecv; ///< bitmask of sockets[] to be woken for receive
- ///< ... access from VCPU thread only
- AtmUInt32 wakeVMMRecv; ///< likewise for monitor receive callbacks
- Mutex mutex; ///< locks list of open sockets
- Mksck_VmId vmId; ///< hostId or guestId these sockets are for
- Mksck_Port portStore; ///< used to assign ephemeral port numbers
- uint32 numAllocSocks; ///< number of elements in sockets[] array
- Mksck sockets[1]; ///< array of sockets (to fill MKSCKPAGE_SIZE)
-};
-
-MksckPage *MksckPage_GetFromVmId(Mksck_VmId vmId);
-Mksck_Port MksckPage_GetFreePort(MksckPage *mksckPage, Mksck_Port port);
-Mksck *MksckPage_GetFromAddr(MksckPage *mksckPage, Mksck_Address addr);
-Mksck *MksckPage_AllocSocket(MksckPage *mksckPage, Mksck_Address addr);
-void MksckPage_DecRefc(MksckPage *mksckPage);
-
-void Mksck_DecRefc(Mksck *mksck);
-void Mksck_CloseCommon(Mksck *mksck);
-_Bool Mksck_IncReadIndex(Mksck *mksck, uint32 read, Mksck_Datagram *dg);
-uint32 Mksck_FindSendRoom(Mksck *mksck, uint32 needed);
-void Mksck_IncWriteIndex(Mksck *mksck, uint32 write, uint32 needed);
-void Mksck_DisconnectPeer(Mksck *mksck);
-
-
-/**
- * @brief determine which shared page a given socket is on
- * Note that this process does not rely on any directory.
- * @param mksck pointer to socket
- * @return pointer to shared page
- */
-static inline MksckPage *
-Mksck_ToSharedPage(Mksck *mksck)
-{
- return (MksckPage*)((char*)(mksck - mksck->index)
- - offsetof(MksckPage, sockets));
-}
-#endif
diff --git a/arch/arm/mvp/mvpkm/mksck_sockaddr.h b/arch/arm/mvp/mvpkm/mksck_sockaddr.h
deleted file mode 100644
index e99d1f5..0000000
--- a/arch/arm/mvp/mvpkm/mksck_sockaddr.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Host user space definitions for mksck sockets.
- */
-
-#ifndef _MKSCK_SOCKADDR_H_
-#define _MKSCK_SOCKADDR_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mksck.h"
-
-/* no one ever uses DECnet anymore? */
-#define AF_MKSCK AF_DECnet
-#define PF_MKSCK PF_DECnet
-
-/* Address structure used by the host user socket interface. */
-struct sockaddr_mk {
- sa_family_t mk_family;
- Mksck_Address mk_addr;
-};
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mmu_defs.h b/arch/arm/mvp/mvpkm/mmu_defs.h
deleted file mode 100644
index 340b91b..0000000
--- a/arch/arm/mvp/mvpkm/mmu_defs.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MMU-related definitions.
- */
-
-#ifndef _MMU_DEFS_H_
-#define _MMU_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @name ARM address space identifier.
- * @{
- */
-#define ARM_ASID_BITS 8
-#define ARM_ASID_NUM (1 << ARM_ASID_BITS)
-#define ARM_ASID_MASK (ARM_ASID_NUM - 1)
-/*@}*/
-
-/**
- * @name ARM level 1 and 2 page table sizes.
- * @{
- */
-#define ARM_L1PT_ORDER 14
-#define ARM_L2PT_FINE_ORDER 12
-#define ARM_L2PT_COARSE_ORDER 10
-
-#define ARM_L1D_SECTION_ORDER 20
-#define ARM_L1D_SUPERSECTION_ORDER 24
-
-#define ARM_L2D_SMALL_ORDER 12
-#define ARM_L2D_LARGE_ORDER 16
-
-#define ARM_L1PT_SIZE (1 << ARM_L1PT_ORDER)
-#define ARM_L2PT_FINE_SIZE (1 << ARM_L2PT_FINE_ORDER)
-#define ARM_L2PT_COARSE_SIZE (1 << ARM_L2PT_COARSE_ORDER)
-
-#define ARM_L1D_SECTION_SIZE (1 << ARM_L1D_SECTION_ORDER)
-#define ARM_L1D_SUPERSECTION_SIZE (1 << ARM_L1D_SUPERSECTION_ORDER)
-
-#define ARM_L2D_SMALL_SIZE (1 << ARM_L2D_SMALL_ORDER)
-#define ARM_L2D_LARGE_SIZE (1 << ARM_L2D_LARGE_ORDER)
-
-#define ARM_L2PT_COARSE_PER_PAGE (PAGE_SIZE / ARM_L2PT_COARSE_SIZE)
-
-#define ARM_L1PT_ENTRIES (ARM_L1PT_SIZE / sizeof(ARM_L1D))
-#define ARM_L2PT_FINE_ENTRIES (ARM_L2PT_FINE_SIZE / sizeof(ARM_L2D))
-#define ARM_L2PT_COARSE_ENTRIES (ARM_L2PT_COARSE_SIZE / sizeof(ARM_L2D))
-/*@}*/
-
-/**
- * @brief Level 1 descriptor type field values.
- * @{
- */
-#define ARM_L1D_TYPE_INVALID 0
-#define ARM_L1D_TYPE_COARSE 1
-#define ARM_L1D_TYPE_SECTION 2
-#define ARM_L1D_TYPE_SUPERSECTION 2
-/*@}*/
-
-/**
- * @name Decomposition of virtual addresses for page table indexing.
- * @{
- */
-#define ARM_L1PT_INDX(addr) MVP_EXTRACT_FIELD((addr), 20, 12)
-#define ARM_L2PT_COARSE_INDX(addr) MVP_EXTRACT_FIELD((addr), 12, 8)
-/*@}*/
-
-/**
- * @name Mapping from the VA/PA/MA of a LxD entry to its table index.
- * @{
- */
-#define ARM_L1D_PTR_INDX(l1dp) MVP_BITS((uint32)(l1dp), 2, ARM_L1PT_ORDER - 1)
-#define ARM_L2D_PTR_INDX(l2dp) MVP_BITS((uint32)(l2dp), 2, ARM_L2PT_COARSE_ORDER - 1)
-/*@}*/
-
-/**
- * @name L1D base index <-> MA.
- * @{
- */
-#define ARM_L1D_BASE_ADDR(base) ((base) << ARM_L1PT_ORDER)
-#define ARM_L1D_ADDR_BASE(addr) ((addr) >> ARM_L1PT_ORDER)
-/*@}*/
-
-/**
- * @brief Which 1 MB section of a 16 MB supersection does the given addr lie in?
- */
-#define ARM_SUPER_SECTION_INDEX(addr) MVP_EXTRACT_FIELD((addr), 20, 4)
-
-/**
- * @name L1D entry base <-> either MA or MA of a second-level table.
- * @{
- */
-#define ARM_L1D_SUPERSECTION_BASE_ADDR(base) ((base) << ARM_L1D_SUPERSECTION_ORDER)
-#define ARM_L1D_SUPERSECTION_ADDR_BASE(addr) ((addr) >> ARM_L1D_SUPERSECTION_ORDER)
-#define ARM_L1D_SECTION_BASE_ADDR(base) ((base) << ARM_L1D_SECTION_ORDER)
-#define ARM_L1D_SECTION_ADDR_BASE(addr) ((addr) >> ARM_L1D_SECTION_ORDER)
-#define ARM_L1D_COARSE_BASE_ADDR(base) ((base) << ARM_L2PT_COARSE_ORDER)
-#define ARM_L1D_COARSE_ADDR_BASE(addr) ((addr) >> ARM_L2PT_COARSE_ORDER)
-#define ARM_L1D_FINE_BASE_ADDR(base) ((base) << ARM_L2PT_FINE_ORDER)
-#define ARM_L1D_FINE_ADDR_BASE(addr) ((addr) >> ARM_L2PT_FINE_ORDER)
-/*@}*/
-
-/*
- * The number of L1 page directory pages the service the entire
- * virtual space
- */
-#define ARM_L1PT_PAGES (1<<(ARM_L1PT_ORDER - PAGE_ORDER))
-
-
-/**
- * @name Level 2 descriptor type field values.
- * @{
- */
-#define ARM_L2D_TYPE_INVALID 0
-#define ARM_L2D_TYPE_LARGE 0
-#define ARM_L2D_TYPE_SMALL 1
-#define ARM_L2D_XTYPE_LARGE 1
-#define ARM_L2D_XTYPE_SMALL 2
-#define ARM_L2D_XTYPE_SMALL_NX 3
-/*@}*/
-
-/**
- * @name Small/Large L2D (in coarse table) base <-> MA conversion.
- * @{
- */
-#define ARM_L2D_LARGE_BASE_ADDR(base) ((base) << ARM_L2D_LARGE_ORDER)
-#define ARM_L2D_LARGE_ADDR_BASE(addr) ((addr) >> ARM_L2D_LARGE_ORDER)
-#define ARM_L2D_SMALL_BASE_ADDR(base) ((base) << ARM_L2D_SMALL_ORDER)
-#define ARM_L2D_SMALL_ADDR_BASE(addr) ((addr) >> ARM_L2D_SMALL_ORDER)
-
-#define ARM_L2D_SMALL_PAGE_NUMBER(addr) ARM_L2D_SMALL_ADDR_BASE(addr)
-#define ARM_L2D_SMALL_PAGE_OFFSET(addr) ((addr) & (PAGE_SIZE - 1))
-/* @}*/
-
-/**
- * @brief ARM page table descriptor access permissions for the AP field.
- * @{
- */
-#define ARM_PERM_NONE 0
-#define ARM_PERM_PRIV_RW 1
-#define ARM_PERM_USER_RO 2
-#define ARM_PERM_USER_RW 3
-/*@}*/
-
-/**
- * @name Simplified access permission model introduced in ARMv7.
- *
- * AP[0] is an access flag, AP[2:1] are one of the following.
- *
- * @{
- */
-#define ARM_SIMPLE_PERM_KERN_RW 0
-#define ARM_SIMPLE_PERM_USER_RW 1
-#define ARM_SIMPLE_PERM_KERN_RO 2
-#define ARM_SIMPLE_PERM_USER_RO 3
-
-#define ARM_SIMPLE_PERM_AP_KERN 1
-#define ARM_SIMPLE_PERM_AP_USER 3
-
-#define ARM_SIMPLE_PERM_APX_RW 0
-#define ARM_SIMPLE_PERM_APX_RO 1
-
-#define ARM_SIMPLE_PERM_AP(x) ((MVP_BIT(x, 0) << 1) | 1)
-#define ARM_SIMPLE_PERM_APX(x) MVP_BIT(x, 1)
-/*@}*/
-
-/**
- * @name ARM domains.
- * @{
- */
-#define ARM_DOMAINS 16
-
-#define ARM_DOMAIN_NOACCESS 0
-#define ARM_DOMAIN_CLIENT 1
-#define ARM_DOMAIN_RESERVED 2
-#define ARM_DOMAIN_MANAGER 3
-/*@}*/
-
-#define ARM_DOMAIN_INDEX(dacr,dom) MVP_EXTRACT_FIELD((dacr), 2*(dom), 2)
-#define ARM_DOMAIN_ACCESS(dom,access) ((access) << (2*(dom)))
-
-/*
- * Cache-related definitions.
- */
-#define ARM_CACHE_LEVELS_MAX 8
-#define ARM_CACHE_LINE_SIZE_MAX 2048
-
-#endif /// _MMU_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/mmu_types.h b/arch/arm/mvp/mvpkm/mmu_types.h
deleted file mode 100644
index da8a6fa..0000000
--- a/arch/arm/mvp/mvpkm/mmu_types.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MMU-related types.
- */
-
-#ifndef _MMU_TYPES_H_
-#define _MMU_TYPES_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mmu_defs.h"
-
-/**
- * @brief ARM level 1 page table descriptor. See B3-8 ARM DDI 0406B.
- */
-typedef union {
- uint32 u;
-
- struct {
- uint32 type : 2;
- uint32 xx : 30;
- } x;
-
- struct {
- uint32 type : 2;
- uint32 sbz1 : 1;
- uint32 ns : 1;
- uint32 sbz2 : 1;
- uint32 domain : 4;
- uint32 imp : 1;
- uint32 base : 22;
- } coarse;
-
- struct {
- uint32 type : 2;
- uint32 cb : 2;
- uint32 xn : 1;
- uint32 domain : 4;
- uint32 imp : 1;
- uint32 ap : 2;
- uint32 tex : 3;
- uint32 apx : 1;
- uint32 s : 1;
- uint32 ng : 1;
- uint32 sbz : 1;
- uint32 ns : 1;
- uint32 base : 12;
- } section;
-
- struct {
- uint32 type : 2;
- uint32 cb : 2;
- uint32 xn : 1;
- uint32 xbase2 : 4;
- uint32 imp : 1;
- uint32 ap : 2;
- uint32 tex : 3;
- uint32 apx : 1;
- uint32 s : 1;
- uint32 ng : 1;
- uint32 sbo : 1;
- uint32 ns : 1;
- uint32 xbase1 : 4;
- uint32 base : 8;
- } supersection;
-} ARM_L1D;
-
-/**
- * @brief ARM level 2 page table descriptor. See B3-10 ARM DDI 0406B.
- */
-typedef union {
- uint32 u;
-
- struct {
- uint32 type : 2;
- uint32 cb : 2;
- uint32 xx : 28;
- } x;
-
- struct {
- uint32 type : 2;
- uint32 cb : 2;
- uint32 ap : 2;
- uint32 sbz : 3;
- uint32 apx : 1;
- uint32 s : 1;
- uint32 ng : 1;
- uint32 tex : 3;
- uint32 xn : 1;
- uint32 base : 16;
- } large;
-
- struct {
- uint32 xn : 1;
- uint32 type : 1;
- uint32 cb : 2;
- uint32 ap : 2;
- uint32 tex : 3;
- uint32 apx : 1;
- uint32 s : 1;
- uint32 ng : 1;
- uint32 base : 20;
- } small;
-} ARM_L2D;
-
-/**
- * @brief Get the simplified access permissions from a small L2 descriptor.
- *
- * @param l2D value of L2 descriptor.
- *
- * @return Simplified access permissions.
- */
-static inline uint8
-ARM_L2DSimpleAP(ARM_L2D l2D)
-{
- ASSERT(l2D.small.type == ARM_L2D_TYPE_SMALL);
- return (l2D.small.apx << 1) | (l2D.small.ap >> 1);
-}
-
-/**
- * @brief Permissions for a page - intermediate format.
- */
-typedef struct {
- uint8 ap : 2;
- uint8 apx : 1;
- uint8 xn : 1;
-} ARM_AccessPerms;
-
-/**
- * @brief ARM domain (0-15).
- */
-typedef uint8 ARM_Domain;
-
-/**
- * @brief ARM Domain Access Control Register, see B4.9.4 ARM DDI 0100I.
- */
-typedef uint32 ARM_DACR;
-
-/**
- * @brief ARM address space identifier.
- * 8-bits with an "invalid ASID" value
- * representation.
- */
-typedef uint32 ARM_ASID;
-
-#define ARM_INVALID_ASID ((uint32)(-1))
-
-/**
- * @brief Page shareability property.
- *
- * LPAE encoding, see p8 ARM PRD03-GENC-008469 11.0.
- */
-typedef enum {
- ARM_SHARE_ATTR_NONE,
- ARM_SHARE_ATTR_RESERVED,
- ARM_SHARE_ATTR_OUTER,
- ARM_SHARE_ATTR_INNER,
-} PACKED ARM_ShareAttr;
-
-/**
- * @brief Page cacheability property (TEX Remap disabled).
- *
- * ARM C/B bits, see B4.4.1 ARM DDI 0100I.
- */
-typedef enum {
- ARM_CB_UNBUFFERED = 0,
- ARM_CB_UNCACHED = 1,
- ARM_CB_WRITETHROUGH = 2,
- ARM_CB_WRITEBACK = 3
-} PACKED ARM_CB;
-
-/**
- * @brief Normal page cacheability property (TEX Remap enabled).
- *
- * NMRR encoding, see B3-146 ARM DDI 0406B.
- */
-typedef enum {
- ARM_CACHE_ATTR_NORMAL_NONE,
- ARM_CACHE_ATTR_NORMAL_WB_WALLOC,
- ARM_CACHE_ATTR_NORMAL_WT,
- ARM_CACHE_ATTR_NORMAL_WB
-} PACKED ARM_CacheAttrNormal;
-
-/**
- * @brief Normal page memory attributes.
- *
- * Captures the general case of distinct inner/outer cacheability/shareability.
- * See A3-30 ARM DDI 0406B for a discussion of shareability domains and
- * cacheability attributes.
- */
-typedef struct {
- ARM_ShareAttr share;
- ARM_CacheAttrNormal innerCache;
- ARM_CacheAttrNormal outerCache;
-} ARM_MemAttrNormal;
-
-#endif /// _MMU_TYPES_H_
diff --git a/arch/arm/mvp/mvpkm/montimer_kernel.c b/arch/arm/mvp/mvpkm/montimer_kernel.c
deleted file mode 100644
index e2f8ef8..0000000
--- a/arch/arm/mvp/mvpkm/montimer_kernel.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP host kernel implementation of monitor timers
- *
- * The monitor sends requests that are simply a 64-bit absolute time that it
- * wants a reply. If it changes its mind, it simply sends a different 64-bit
- * absolute time. It is tolerant of us replying too soon, so if we miss the
- * update to a later time, it doesn't matter, the monitor will re-send the
- * request for the later time. The only time we should miss an update to a
- * sooner time is when we are about to send the reply to the old time anyway,
- * in which case the monitor sees a reply as quickly as we can generate them,
- * so no harm there either.
- */
-
-#include <linux/module.h>
-#include <linux/hrtimer.h>
-
-#include "mvp.h"
-#include "mvp_timer.h"
-#include "actions.h"
-#include "mvpkm_kernel.h"
-
-/**
- * @brief Linux timer callback
- * @param timer The linux timer raised
- * @return Status to not restart the timer
- */
-static enum hrtimer_restart
-MonitorTimerCB(struct hrtimer *timer)
-{
- MvpkmVM *vm = container_of(timer, MvpkmVM, monTimer.timer);
- Mvpkm_WakeGuest(vm, ACTION_TIMER);
- return HRTIMER_NORESTART;
-}
-
-/**
- * @brief Initialize vm associated timer
- * @param vm which virtual machine we're running
- */
-void
-MonitorTimer_Setup(MvpkmVM *vm)
-{
- MonTimer *monTimer = &vm->monTimer;
- monTimer->vm = vm;
-
- hrtimer_init(&monTimer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- monTimer->timer.function = MonitorTimerCB;
-}
-
-/**
- * @brief New timer request from monitor
- * @param monTimer Monitor timer
- * @param when64 Timer target value
- */
-void
-MonitorTimer_Request(MonTimer *monTimer, uint64 when64)
-{
- if (when64) {
- ktime_t kt;
-
- /*
- * Simple conversion, assuming RATE64 is 1e+9
- */
- kt = ns_to_ktime(when64);
- ASSERT_ON_COMPILE(MVP_TIMER_RATE64 == 1000000000);
-
- /*
- * Start the timer. If it was already active, it will remove
- * the previous expiration time. Linux handles correctly timer
- * with deadline in the past, and forces a safety minimal delta
- * for closer timer deadlines.
- */
- hrtimer_start(&monTimer->timer, kt, HRTIMER_MODE_ABS);
- } else {
- /*
- * Cancel a pending request. If there is none, this will do nothing.
- * If it's too late, monitor tolerance will forgive us.
- */
- hrtimer_cancel(&monTimer->timer);
- }
-}
diff --git a/arch/arm/mvp/mvpkm/montimer_kernel.h b/arch/arm/mvp/mvpkm/montimer_kernel.h
deleted file mode 100644
index 6817a83..0000000
--- a/arch/arm/mvp/mvpkm/montimer_kernel.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The monitor-kernel socket interface kernel-only definitions.
- */
-
-#ifndef _MONITOR_TIMER_KERNEL_H
-#define _MONITOR_TIMER_KERNEL_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include <linux/hrtimer.h>
-
-/**
- * @brief Monitor Timer structure
- */
-typedef struct {
- struct MvpkmVM *vm; ///< Associated vm
- struct hrtimer timer; ///< Linux timer
-} MonTimer;
-
-void MonitorTimer_Setup(struct MvpkmVM *vm);
-void MonitorTimer_Request(MonTimer *monTimer, uint64 when64);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/monva_common.h b/arch/arm/mvp/mvpkm/monva_common.h
deleted file mode 100644
index de3dd1a..0000000
--- a/arch/arm/mvp/mvpkm/monva_common.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Constant definitions that describing the monitor memory layout
- * (common to both LPV and VE monitors).
- *
- */
-
-#ifndef _MONVA_COMMON_H_
-#define _MONVA_COMMON_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mmu_defs.h"
-#include "mmu_types.h"
-
-/*
- * The monitor occupies a hole in the guest virtual address space.
- * The following macros define that hole.
- */
-
-#define MONITOR_VA_START ((MVA)0xE8000000)
-#define MONITOR_VA_LEN 0x03000000
-
-/*
- * Worldswitch page gets mapped right after the stack guard.
- */
-#define MONITOR_VA_WORLDSWITCH \
- ((MVA)(MONITOR_VA_START + 3 * PAGE_SIZE))
-
-#define MONITOR_VA_WORLDSWITCH_CODE \
- (MONITOR_VA_WORLDSWITCH + PAGE_SIZE)
-
-#define MONITOR_VA_UART \
- (MONITOR_VA_WORLDSWITCH_CODE + PAGE_SIZE)
-
-/**
- * @brief Type of physmem region mapping that we want the VMX to know about.
- * Helps to identify Guest page allocations.
- */
-typedef enum {
- MEMREGION_MAINMEM = 1,
- MEMREGION_MODULE = 2,
- MEMREGION_WSP = 3,
- MEMREGION_MONITOR_MISC = 4,
- MEMREGION_DEFAULT = 0
-} PACKED PhysMem_RegionType;
-
-typedef struct MonVA { /* Note that this struct is VE only */
- MA l2BaseMA; ///< MA of monitor L2 page table page
- MVA excVec; ///< Monitor exception vector virtual address
-} MonVA;
-
-/**
- * @brief Monitor VA mapping type, device or memory.
- *
- * These values are used to index HMAIR0 in the VE monitor - do not change
- * without making the required update to HMAIR0.
- */
-typedef enum {
- MVA_MEMORY = 0,
- MVA_DEVICE = 1
-} MVAType;
-
-/**
- * @name Monitor types, used in VMX, Mvpkm and monitors.
- *
- * This is not a C enumeration, as we may want to use the values in CPP macros.
- *
- * @{
- */
-#define MONITOR_TYPE_LPV 0
-#define MONITOR_TYPE_VE 1
-#define MONITOR_TYPE_UNKNOWN 0xf
-
-typedef uint32 MonitorType;
-/*@}*/
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mutex.h b/arch/arm/mvp/mvpkm/mutex.h
deleted file mode 100644
index 30de97d..0000000
--- a/arch/arm/mvp/mvpkm/mutex.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Common mutex definitions.
- */
-
-#ifndef _MUTEX_H
-#define _MUTEX_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define MUTEX_CVAR_MAX 2 ///< maximum number of condition variables supported
- ///< on a given mutex
-
-typedef enum MutexMode MutexMode;
-typedef struct HKWaitQ HKWaitQ;
-typedef struct Mutex Mutex;
-
-/**
- * @brief modes for locking
- */
-enum MutexMode {
- MutexModeSH = 1, ///< minimum value that can be saved in low
- ///< 16 bits of 'state', ie, it won't allow
- ///< any other EXs in there without overflowing.
- ///< it also will block if there are already
- ///< 0xFFFF other shared accesses, but it should
- ///< be of little consequence.
-
- MutexModeEX = 0xFFFF ///< maximum value that can be saved in low
- ///< 16 bits of 'state', ie, it won't allow
- ///< any other EXs or SHs in there without
- ///< overflowing, thus causing a block.
-};
-
-#include "atomic.h"
-
-typedef union Mutex_State {
- uint32 state; ///< for atomic setting/reading
- struct {
- uint16 mode; ///< the sum of mode values of MutexMode
- uint16 blck; ///< The number of threads blocked
- };
-} Mutex_State;
-
-/**
- * @brief shareable mutex struct.
- */
-struct Mutex {
- HKVA mtxHKVA; ///< mutex's host kernel virtual address
- AtmUInt32 state; ///< low 16 bits: # of granted shared accessors
- ///< or FFFF if granted exclusive
- ///< high 16 bits: # of blocked threads
- AtmUInt32 waiters; ///< number of threads on all condWaitQs
- ///< ... increment only with mutex locked EX
- ///< ... decrement any time
- AtmUInt32 blocked; ///< number times blocked (stats only)
- HKVA lockWaitQ; ///< threads blocked for mutex to be unlocked
- HKVA cvarWaitQs[MUTEX_CVAR_MAX]; ///< condition variables
- /*
- * Padding to keep binary compatibility @see{MVP-1876}
- * These padding bytes can be used for debugging.
- */
- int line;
- int lineUnl;
- uint32 pad3;
- uint32 pad4;
- uint32 pad5;
- uint32 pad6;
-};
-
-#define Mutex_Lock(a, b) Mutex_LockLine(a, b, __FILE__, __LINE__)
-#define Mutex_Unlock(a, b) Mutex_UnlockLine(a, b, __LINE__)
-#define Mutex_UnlSleep(a, b, c) Mutex_UnlSleepLine(a, b, c, __FILE__, __LINE__)
-#define Mutex_UnlSleepTest(a, b, c, d, e) Mutex_UnlSleepTestLine(a, b, c, d, e, __FILE__, __LINE__)
-int Mutex_LockLine(Mutex *mutex, MutexMode mode, const char *file, int line);
-void Mutex_UnlockLine(Mutex *mutex, MutexMode mode, int line);
-int Mutex_UnlSleepLine(Mutex *mutex, MutexMode mode, uint32 cvi, const char *file, int line);
-int Mutex_UnlSleepTestLine(Mutex *mutex, MutexMode mode, uint32 cvi, AtmUInt32 *test, uint32 mask, const char *file, int line);
-void Mutex_UnlWake(Mutex *mutex, MutexMode mode, uint32 cvi, _Bool all);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mutex_kernel.c b/arch/arm/mvp/mvpkm/mutex_kernel.c
deleted file mode 100644
index 7b76bfcf..0000000
--- a/arch/arm/mvp/mvpkm/mutex_kernel.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The host kernel mutex functions. These mutexes can be located in
- * shared address space with the monitor.
- */
-
-#include <linux/kernel.h>
-
-#include <asm/string.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/hardirq.h>
-
-#include "mvp.h"
-
-#include "arm_inline.h"
-#include "coproc_defs.h"
-#include "mutex_kernel.h"
-
-#define POLL_IN_PROGRESS_FLAG (1<<(30-MUTEX_CVAR_MAX))
-
-#define INITWAITQ(waitQ) do { \
- init_waitqueue_head((wait_queue_head_t *)(waitQ)); \
-} while (0)
-
-#define WAKEUPALL(waitQ) do { \
- wake_up_all((wait_queue_head_t *)(waitQ)); \
-} while (0)
-
-#define WAKEUPONE(waitQ) do { \
- wake_up((wait_queue_head_t *)(waitQ)); \
-} while (0)
-
-/**
- * @brief initialize mutex
- * @param[in,out] mutex mutex to initialize
- */
-void
-Mutex_Init(Mutex *mutex)
-{
- wait_queue_head_t *wq;
- int i;
-
- wq = kcalloc(MUTEX_CVAR_MAX + 1, sizeof(wait_queue_head_t), 0);
- FATAL_IF(wq == NULL);
-
- memset(mutex, 0, sizeof *mutex);
- mutex->mtxHKVA = (HKVA)mutex;
- mutex->lockWaitQ = (HKVA)&wq[0];
- INITWAITQ(mutex->lockWaitQ);
- for (i = 0; i < MUTEX_CVAR_MAX; i ++) {
- mutex->cvarWaitQs[i] = (HKVA)&wq[i + 1];
- INITWAITQ(mutex->cvarWaitQs[i]);
- }
-}
-
-/**
- * @brief Check if it is ok to sleep
- * @param file the file of the caller code
- * @param line the line number of the caller code
- */
-static void
-MutexCheckSleep(const char *file, int line)
-{
-#ifdef MVP_DEVEL
- static unsigned long prev_jiffy; /* ratelimiting: 1/s */
-
-#ifdef CONFIG_PREEMPT
- if (preemptible() && !irqs_disabled()) {
- return;
- }
-#else
- if (!irqs_disabled()) {
- return;
- }
-#endif
- if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) {
- return;
- }
- prev_jiffy = jiffies;
- printk(KERN_ERR
- "BUG: sleeping function called from invalid context at %s:%d\n",
- file, line);
- printk(KERN_ERR
- "irqs_disabled(): %d, preemtible(): %d, pid: %d, name: %s\n",
- irqs_disabled(),
- preemptible(),
- current->pid, current->comm);
- dump_stack();
-#endif
-}
-
-/**
- * @brief destroy mutex
- * @param[in,out] mutex mutex to destroy
- */
-void
-Mutex_Destroy(Mutex *mutex)
-{
- kfree((void*)mutex->lockWaitQ);
-}
-
-/**
- * @brief Lock the mutex. Also does a data barrier after locking so the
- * locking is complete before any shared data is accessed.
- * @param[in,out] mutex which mutex to lock
- * @param mode mutex lock mode
- * @param file the file of the caller code
- * @param line the line number of the code that called this function
- * @return rc = 0: mutex now locked by caller<br>
- * < 0: interrupted
- */
-int
-Mutex_LockLine(Mutex *mutex, MutexMode mode, const char *file, int line)
-{
- Mutex_State newState, oldState;
-
- MutexCheckSleep(file, line);
-
- /*
- * If uncontended, just set new lock state and return success status.
- * If contended, mark state saying there is a waiting thread to wake.
- */
- do {
-lock_start:
- /*
- * Get current state and calculate what new state would be.
- * New state adds 1 for shared and 0xFFFF for exclusive.
- * If the 16 bit field overflows, there is contention.
- */
- oldState.state = ATOMIC_GETO(mutex->state);
- newState.mode = oldState.mode + mode;
- newState.blck = oldState.blck;
-
- /*
- * So we are saying there is no contention if new state
- * indicates no overflow.
- *
- * On fairness: The test here allows a new-comer thread to grab
- * the lock even if there is a blocked thread. For example 2
- * threads repeatedly obtaining shared access can starve a third
- * wishing to obtain an exclusive lock. Currently this is only a
- * hypothetical situation as mksck use exclusive lock only and
- * the code never has more than 2 threads using the same mutex.
- */
- if ((uint32)newState.mode >= (uint32)mode) {
- if (!ATOMIC_SETIF(mutex->state, newState.state, oldState.state)) {
- goto lock_start;
- }
- DMB();
- mutex->line = line;
- mutex->lineUnl = -1;
- return 0;
- }
-
- /*
- * There is contention, so increment the number of blocking threads.
- */
- newState.mode = oldState.mode;
- newState.blck = oldState.blck + 1;
- } while (!ATOMIC_SETIF(mutex->state, newState.state, oldState.state));
-
- /*
- * Statistics...
- */
- ATOMIC_ADDV(mutex->blocked, 1);
-
- /*
- * Mutex is contended, state has been updated to say there is a blocking
- * thread.
- *
- * So now we block till someone wakes us up.
- */
- do {
- DEFINE_WAIT(waiter);
-
- /*
- * This will make sure we catch any wakes done after we check the lock
- * state again.
- */
- prepare_to_wait((wait_queue_head_t *)mutex->lockWaitQ,
- &waiter,
- TASK_INTERRUPTIBLE);
-
- /*
- * Now that we will catch wakes, check the lock state again. If now
- * uncontended, mark it locked, abandon the wait and return success.
- */
-
-set_new_state:
- /*
- * Same as the original check for contention above, except that we
- * must decrement the number of waiting threads by one
- * if we are successful in locking the mutex.
- */
- oldState.state = ATOMIC_GETO(mutex->state);
- newState.mode = oldState.mode + mode;
- newState.blck = oldState.blck - 1;
- ASSERT(oldState.blck);
-
- if ((uint32)newState.mode >= (uint32)mode) {
- if (!ATOMIC_SETIF(mutex->state, newState.state, oldState.state)) {
- goto set_new_state;
- }
- /*
- * Mutex is no longer contended and we were able to lock it.
- */
- finish_wait((wait_queue_head_t *)mutex->lockWaitQ, &waiter);
- DMB();
- mutex->line = line;
- mutex->lineUnl = -1;
- return 0;
- }
-
- /*
- * Wait for a wake that happens any time after prepare_to_wait()
- * returned.
- */
- WARN(!schedule_timeout(10*HZ), "Mutex_Lock: soft lockup - stuck for 10s!\n");
- finish_wait((wait_queue_head_t *)mutex->lockWaitQ, &waiter);
- } while (!signal_pending(current));
-
- /*
- * We aren't waiting anymore, so decrement the number of waiting threads.
- */
- do {
- oldState.state = ATOMIC_GETO(mutex->state);
- newState.mode = oldState.mode;
- newState.blck = oldState.blck - 1;
-
- ASSERT(oldState.blck);
-
- } while (!ATOMIC_SETIF(mutex->state, newState.state, oldState.state));
-
- return -ERESTARTSYS;
-}
-
-
-/**
- * @brief Unlock the mutex. Also does a data barrier before unlocking so any
- * modifications made before the lock gets released will be completed
- * before the lock is released.
- * @param mutex as passed to Mutex_Lock()
- * @param mode as passed to Mutex_Lock()
- * @param line the line number of the code that called this function
- */
-void
-Mutex_UnlockLine(Mutex *mutex, MutexMode mode, int line)
-{
- Mutex_State newState, oldState;
-
- DMB();
- do {
- oldState.state = ATOMIC_GETO(mutex->state);
- newState.mode = oldState.mode - mode;
- newState.blck = oldState.blck;
- mutex->lineUnl = line;
-
- ASSERT(oldState.mode >= mode);
- } while (!ATOMIC_SETIF(mutex->state, newState.state, oldState.state));
-
- /*
- * If another thread was blocked, then wake it up.
- */
- if (oldState.blck) {
- if (mode == MutexModeSH) {
- WAKEUPONE(mutex->lockWaitQ);
- } else {
- WAKEUPALL(mutex->lockWaitQ);
- }
- }
-}
-
-
-/**
- * @brief Unlock the mutex and sleep. Also does a data barrier before
- * unlocking so any modifications made before the lock gets released
- * will be completed before the lock is released.
- * @param mutex as passed to Mutex_Lock()
- * @param mode as passed to Mutex_Lock()
- * @param cvi which condition variable to sleep on
- * @param file the file of the caller code
- * @param line the line number of the caller code
- * @return rc = 0: successfully waited<br>
- * < 0: error waiting
- */
-int
-Mutex_UnlSleepLine(Mutex *mutex, MutexMode mode, uint32 cvi, const char *file, int line)
-{
- return Mutex_UnlSleepTestLine(mutex, mode, cvi, NULL, 0, file, line);
-}
-
-/**
- * @brief Unlock the mutex and sleep. Also does a data barrier before
- * unlocking so any modifications made before the lock gets released
- * will be completed before the lock is released.
- * @param mutex as passed to Mutex_Lock()
- * @param mode as passed to Mutex_Lock()
- * @param cvi which condition variable to sleep on
- * @param test sleep only if null or pointed atomic value mismatches mask
- * @param mask bitfield to check test against before sleeping
- * @param file the file of the caller code
- * @param line the line number of the caller code
- * @return rc = 0: successfully waited<br>
- * < 0: error waiting
- */
-int
-Mutex_UnlSleepTestLine(Mutex *mutex, MutexMode mode, uint32 cvi, AtmUInt32 *test, uint32 mask, const char *file, int line)
-{
- DEFINE_WAIT(waiter);
-
- MutexCheckSleep(file, line);
-
- ASSERT(cvi < MUTEX_CVAR_MAX);
-
- /*
- * Tell anyone who might try to wake us that they need to actually call
- * WAKEUP***().
- */
- ATOMIC_ADDV(mutex->waiters, 1);
-
- /*
- * Be sure to catch any wake that comes along just after we unlock the mutex
- * but before we call schedule().
- */
- prepare_to_wait_exclusive((wait_queue_head_t *)mutex->cvarWaitQs[cvi],
- &waiter,
- TASK_INTERRUPTIBLE);
-
- /*
- * Release the mutex, someone can wake us up now.
- * They will see mutex->waiters non-zero so will actually do the wake.
- */
- Mutex_Unlock(mutex, mode);
-
- /*
- * Wait to be woken or interrupted.
- */
- if (test == NULL || (ATOMIC_GETO(*test) & mask) == 0) {
- schedule();
- }
- finish_wait((wait_queue_head_t *)mutex->cvarWaitQs[cvi], &waiter);
-
- /*
- * Done waiting, don't need a wake any more.
- */
- ATOMIC_SUBV(mutex->waiters, 1);
-
- /*
- * If interrupted, return error status.
- */
- if (signal_pending(current)) {
- return -ERESTARTSYS;
- }
-
- /*
- * Wait completed, return success status.
- */
- return 0;
-}
-
-
-/**
- * @brief Unlock the mutex and prepare to sleep on a kernel polling table
- * given as anonymous parameters for poll_wait
- * @param mutex as passed to Mutex_Lock()
- * @param mode as passed to Mutex_Lock()
- * @param cvi which condition variable to sleep on
- * @param filp which file to poll_wait upon
- * @param wait which poll_table to poll_wait upon
- */
-void
-Mutex_UnlPoll(Mutex *mutex, MutexMode mode, uint32 cvi, void *filp, void *wait)
-{
- ASSERT(cvi < MUTEX_CVAR_MAX);
-
- /* poll_wait is done with mutex locked to prevent any wake that comes and
- * defer them just after we unlock the mutex but before kernel polling
- * tables are used
- * Note that the kernel is probably avoiding an exclusive wait in that case
- * and also increments the usage for the file given in filp
- */
- poll_wait(filp, (wait_queue_head_t *)mutex->cvarWaitQs[cvi], wait);
-
- /*
- * Tell anyone who might try to wake us that they need to actually call
- * WAKEUP***(). This is done in putting ourselves in a "noisy" mode since
- * there is no guaranty that we would really sleep, or if we would be
- * wakening the sleeping thread with that socket or condition. This is
- * done using a POLL_IN_PROGRESS_FLAG, but unfortunately it has to be
- * a per-cvi flag, in case we would poll independently on different cvi
- */
- DMB();
- ATOMIC_ORO(mutex->waiters, (POLL_IN_PROGRESS_FLAG << cvi));
-
- /*
- * Release the mutex, someone can wake us up now.
- * They will see mutex->waiters non-zero so will actually do the wake.
- */
- Mutex_Unlock(mutex, mode);
-}
-
-
-/**
- * @brief Unlock the semaphore and wake sleeping threads. Also does a data
- * barrier before unlocking so any modifications made before the lock
- * gets released will be completed before the lock is released.
- * @param mutex as passed to Mutex_Lock()
- * @param mode as passed to Mutex_Lock()
- * @param cvi which condition variable to signal
- * @param all false: wake a single thread<br>
- * true: wake all threads
- */
-void
-Mutex_UnlWake(Mutex *mutex, MutexMode mode, uint32 cvi, _Bool all)
-{
- Mutex_Unlock(mutex, mode);
- Mutex_CondSig(mutex, cvi, all);
-}
-
-
-/**
- * @brief Signal condition variable, ie, wake up anyone waiting.
- * @param mutex mutex that holds the condition variable
- * @param cvi which condition variable to signal
- * @param all false: wake a single thread<br>
- * true: wake all threads
- */
-void
-Mutex_CondSig(Mutex *mutex, uint32 cvi, _Bool all)
-{
- uint32 waiters;
-
- ASSERT(cvi < MUTEX_CVAR_MAX);
-
- waiters = ATOMIC_GETO(mutex->waiters);
- if (waiters != 0) {
- /* Cleanup the effects of Mutex_UnlPoll() but only when it is SMP safe,
- * considering that atomic and wakeup operations should also do memory
- * barriers accordingly. This is mandatory otherwise rare SMP races are
- * even possible, since Mutex_CondSig is called with the associated mutex
- * unlocked, and that does not prevent from select() to run parallel !
- */
- if ((waiters >= POLL_IN_PROGRESS_FLAG) &&
- !waitqueue_active((wait_queue_head_t *)mutex->cvarWaitQs[cvi])) {
- ATOMIC_ANDO(mutex->waiters, ~(POLL_IN_PROGRESS_FLAG << cvi));
- }
- DMB();
-
- if (all) {
- WAKEUPALL(mutex->cvarWaitQs[cvi]);
- } else {
- WAKEUPONE(mutex->cvarWaitQs[cvi]);
- }
- }
-}
diff --git a/arch/arm/mvp/mvpkm/mutex_kernel.h b/arch/arm/mvp/mvpkm/mutex_kernel.h
deleted file mode 100644
index 4bdf0e1..0000000
--- a/arch/arm/mvp/mvpkm/mutex_kernel.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The host kernel mutex definitions.
- */
-
-#ifndef _MUTEX_KERNEL_H
-#define _MUTEX_KERNEL_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mutex.h"
-
-void Mutex_Init(Mutex *mutex);
-void Mutex_Destroy(Mutex *mutex);
-void Mutex_CondSig(Mutex *mutex, uint32 cvi, _Bool all);
-void Mutex_UnlPoll(Mutex *mutex, MutexMode mode, uint32 cvi, void *filp, void *wait);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvp.h b/arch/arm/mvp/mvpkm/mvp.h
deleted file mode 100644
index e21b8a0..0000000
--- a/arch/arm/mvp/mvpkm/mvp.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief top-level include for all basic includes.
- * This file should not define anything of its own.
- */
-
-#ifndef _MVP_H
-#define _MVP_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "mvp_compiler.h"
-#include "utils.h"
-#include "mvp_assert.h"
-#include "mvp_types.h"
-#include "platdefx.h"
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvp_assert.h b/arch/arm/mvp/mvpkm/mvp_assert.h
deleted file mode 100644
index 9ee6fc0..0000000
--- a/arch/arm/mvp/mvpkm/mvp_assert.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief ASSERT() and related macros.
- */
-
-#ifndef _MVP_ASSERT_H
-#define _MVP_ASSERT_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define ASSERT(_x) ASSERT_BUG((_x),0)
-
-#ifndef NDEBUG
-#define ASSERT_BUG(_x,_tkt) do { \
- if (UNLIKELY(!(_x))) { \
- FatalError(__FILE__, __LINE__, FECodeAssert, _tkt, NULL); \
- } \
-} while (0)
-
-#define ASSERTF(_x, ...) do { \
- if (UNLIKELY(!(_x))) { \
- FatalError(__FILE__, \
- __LINE__, \
- FECodeAssert, \
- 0, \
- __VA_ARGS__); \
- } \
-} while (0)
-#else
-
-#define ASSERT_BUG(_x,_tkt) (void)sizeof((int)(_x))
-#define ASSERTF(_x, ...) ASSERT_BUG(_x, 0)
-
-#endif
-
-/*
- * Compile-time assertions.
- *
- * ASSERT_ON_COMPILE does not use the common
- * switch (0) { case 0: case (e): ; } trick because some compilers (e.g. MSVC)
- * generate code for it.
- *
- * The implementation uses both enum and typedef because the typedef alone is
- * insufficient; gcc allows arrays to be declared with non-constant expressions
- * (even in typedefs, where it makes no sense).
- */
-#ifdef __COVERITY__
-#define ASSERT_ON_COMPILE(e) ASSERT(e)
-#else
-#define ASSERT_ON_COMPILE(e) \
- do { \
- enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
- typedef char AssertOnCompileFailed[AssertOnCompileMisused]; \
- } while (0)
-#endif
-
-/*
- * To put an ASSERT_ON_COMPILE() outside a function, wrap it
- * in MY_ASSERTS(). The first parameter must be unique in
- * each .c file where it appears. For example,
- *
- * MY_ASSERTS(FS3_INT,
- * ASSERT_ON_COMPILE(sizeof(FS3_DiskLock) == 128);
- * ASSERT_ON_COMPILE(sizeof(FS3_DiskLockReserved) == DISK_BLOCK_SIZE);
- * ASSERT_ON_COMPILE(sizeof(FS3_DiskBlock) == DISK_BLOCK_SIZE);
- * ASSERT_ON_COMPILE(sizeof(Hardware_DMIUUID) == 16);
- * )
- *
- * Caution: ASSERT() within MY_ASSERTS() is silently ignored.
- * The same goes for anything else not evaluated at compile time.
- */
-
-#define MY_ASSERTS(name, assertions) \
- static inline void name(void) { \
- assertions \
- }
-
-#define KNOWN_BUG(_tkt)
-
-#define NOT_IMPLEMENTED() NOT_IMPLEMENTED_JIRA(0)
-#define NOT_IMPLEMENTED_JIRA(_tkt,...) FatalError(__FILE__, __LINE__, FECodeNI, _tkt, NULL)
-
-#define NOT_IMPLEMENTED_IF(_x) NOT_IMPLEMENTED_IF_JIRA((_x),0)
-#define NOT_IMPLEMENTED_IF_JIRA(_x,_tkt,...) do { if (UNLIKELY(_x)) NOT_IMPLEMENTED_JIRA(_tkt); } while (0)
-/*
- * All sites tagged with this are @knownjira{MVP-1855}.
- */
-#define NOT_IMPLEMENTEDF(...) FatalError(__FILE__, __LINE__, FECodeNI, 0, __VA_ARGS__)
-
-#define NOT_REACHED() FatalError(__FILE__, __LINE__, FECodeNR, 0, NULL)
-
-#include "fatalerror.h"
-#include "nottested.h"
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvp_balloon.h b/arch/arm/mvp/mvpkm/mvp_balloon.h
deleted file mode 100644
index 9df5669..0000000
--- a/arch/arm/mvp/mvpkm/mvp_balloon.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Common guest/host balloon state machine.
- */
-#ifndef _MVP_BALLOON_H
-#define _MVP_BALLOON_H
-
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_MODULE
-#include "include_check.h"
-
-/**
- * @brief Balloon watchdog timeout (in seconds).
- *
- * If we don't hear back from the guest balloon driver in this amount of time,
- * we terminate the guest.
- *
- * This can sound arbitrary long but we need to deal with checkpointing. The
- * watchdog goal is only to not let not-responding VM running for ages.
- */
-#define BALLOON_WATCHDOG_TIMEOUT_SECS 90
-
-/**
- * @brief MVP_BALLOON_GET_DELTA return.
- */
-typedef union {
- struct {
- int32 delta : 21; ///< Number/direction balloon adjustment in pages.
- };
- uint32 u;
-} Balloon_GetDeltaRet;
-
-/**
- * @name Guest settings for lowmemorykiller oom_adj and minfree thresholds, as reflected in
- * the guest's /sys/module/lowmemorykiller/parameters/{minfree,adj}.
- *
- * @{
- */
-
-/**
- * @brief Android oom_adj levels for the various thresholds.
- */
-typedef enum {
- BALLOON_ANDROID_GUEST_OOM_ADJ_FOREGROUND_APP = 0,
- BALLOON_ANDROID_GUEST_OOM_ADJ_VISIBLE_APP = 1,
- BALLOON_ANDROID_GUEST_OOM_ADJ_SECONDARY_SERVER = 2,
- BALLOON_ANDROID_GUEST_OOM_ADJ_BACKUP_APP = 2,
- BALLOON_ANDROID_GUEST_OOM_ADJ_HOME_APP = 4,
- BALLOON_ANDROID_GUEST_OOM_ADJ_HIDDEN_APP_MIN = 7,
- BALLOON_ANDROID_GUEST_OOM_ADJ_CONTENT_PROVIDER = 14,
- BALLOON_ANDROID_GUEST_OOM_ADJ_EMPTY_APP = 15
-} Balloon_AndroidGuestOOMAdj;
-
-/**
- * @brief Android low memory killer thresholds (in pages).
- */
-typedef enum {
- BALLOON_ANDROID_GUEST_MIN_FREE_FOREGROUND_APP_PAGES = 1536,
- BALLOON_ANDROID_GUEST_MIN_FREE_VISIBLE_APP_PAGES = 2048,
- BALLOON_ANDROID_GUEST_MIN_FREE_SECONDARY_SERVER_PAGES = 4096,
- BALLOON_ANDROID_GUEST_MIN_FREE_BACKUP_APP_PAGES = 4096,
- BALLOON_ANDROID_GUEST_MIN_FREE_HOME_APP_PAGES = 4096,
- BALLOON_ANDROID_GUEST_MIN_FREE_HIDDEN_APP_PAGES = 5120,
- BALLOON_ANDROID_GUEST_MIN_FREE_CONTENT_PROVIDER_PAGES = 5632,
- BALLOON_ANDROID_GUEST_MIN_FREE_EMPTY_APP_MEM_PAGES = 6144
-} Balloon_AndroidGuestMinFreePages;
-
-/* @} */
-/**
- * @brief Calculate distance to the point at which Android will terminate
- * processes.
- *
- * In the balloon policy we strive to maintain the low memory killer minfree
- * value (e.g. max(freePages, filePages)) above the threshold for terminating
- * empty apps (as per the Android low memory killer's logic). Here we measure
- * the number of pages we have buffering us from this point.
- *
- * We chose the empty app threshold instead instead of the home app threshold,
- * the threshold we ultimately want to avoid crossing for two reasons:
- * - We want to avoid any error introduced by the use of max(free, file) when
- * between the two thresholds from interfering with the errorBackground term
- * in the balloon policy. If we instead measure the distance to the home app
- * threshold, we can get into the situation that even when both sides have
- * balanced background pages and the same low memory distance, different
- * free/file ratios in the two worlds introduces a further bias.
- * - It's helpful in avoiding extreme situations where the balloon won't be able
- * to adapt quickly to leave a buffer. With empty app minfree as the target,
- * when background pages drops to zero, and both worlds are below the empty
- * app minfree target, the balloon will stop adjusting, leaving each world to
- * fend for itself. At this point, the worlds have a maximum of 8192 pages
- * (using the above logic) until they start killing services and foreground
- * apps, which seems like a reasonable buffer to have in place. Another way of
- * putting it is that at this point, we are unsure that rebalancing the
- * balloon won't harm the side it balances against by eating into its buffer.
- *
- * We assume that normally filePages only decreases as a result of freePages
- * being close to zero, when vmscan reclaiming kicks in. Based on this,
- * there are two cases when computing the distance.
- *
- * - filePages >= emptyAppPages:
- * freePages + filePages - emptyAppPages
- * - filePages < emptyAppPages:
- * MAX(0, freePages - emptyAppPages)
- *
- * @param freePages number of free pages.
- * @param filePages number of pages in the page cache.
- * @param emptyAppPages number of free/file pages at which the
- * lowmemorykiller will start killing empty apps.
- *
- * @return Low memory distance measure (in pages).
- */
-static inline uint32
-Balloon_LowMemDistance(uint32 freePages, uint32 filePages, uint32 emptyAppPages)
-{
- return filePages >= emptyAppPages ?
- freePages + (filePages - emptyAppPages) :
- (freePages > emptyAppPages ? freePages - emptyAppPages : 0);
-}
-
-#ifdef __KERNEL__
-/**
- * @brief Obtain approximation of # anonymous pages belonging to Android
- * background processes.
- *
- * Used to inform balloon policy. Note that this is a coarse approximation only,
- * since we use RSS. More precise accounting is possible but potentially costly
- * as it's not available directly in the task struct.
- *
- * @param hiddenAppOOMAdj minimum oom_adj for hidden apps.
- *
- * @return sum of empty, content provider and hidden app anon resident pages.
- */
-static uint32
-Balloon_AndroidBackgroundPages(uint32 minHiddenAppOOMAdj)
-{
- uint32 backgroundPages = 0, nonBackgroundPages = 0;
- struct task_struct *t;
-
- /*
- * Traverse the tasklist to replicate the behavior of the Android low memory
- * killer.
- */
- rcu_read_lock();
-
- for_each_process(t) {
- int oom_adj = 0;
-
- task_lock(t);
-
- if (t->signal == NULL) {
- task_unlock(t);
- continue;
- } else {
- oom_adj = t->signal->oom_adj;
- }
-
- if (t->mm != NULL) {
-#ifdef BALLOON_DEBUG_PRINT_ANDROID_PAGES
- printk("Balloon_AndroidBackgroundPages: %d %d %s\n",
- oom_adj,
- (int)get_mm_counter(t->mm, MM_ANONPAGES),
- t->comm);
-#endif
-
- if (oom_adj >= (int)minHiddenAppOOMAdj) {
- /*
- * Unlike the Android low memory killer, we only consider anonymous
- * memory here, since we already account for file pages in the
- * balloon policy using global_page_state(NR_FILE_PAGES).
- */
- backgroundPages += get_mm_counter(t->mm, MM_ANONPAGES);
- } else {
- nonBackgroundPages += get_mm_counter(t->mm, MM_ANONPAGES);
- }
- }
-
- task_unlock(t);
- }
-
- rcu_read_unlock();
-
-#ifdef BALLOON_DEBUG_PRINT_ANDROID_PAGES
- printk("Balloon_AndroidBackgroundPages: non-background pages: %d "
- "background pages: %d\n",
- nonBackgroundPages,
- backgroundPages);
-#endif
-
- return backgroundPages;
-}
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvp_compiler.h b/arch/arm/mvp/mvpkm/mvp_compiler.h
deleted file mode 100644
index 58825a0..0000000
--- a/arch/arm/mvp/mvpkm/mvp_compiler.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Compiler-related definitions and directives.
- */
-
-#ifndef _MVP_COMPILER_H_
-#define _MVP_COMPILER_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#ifdef __GNUC__
-#include "mvp_compiler_gcc.h"
-#else /* __GNUC__ */
-#include "mvp_compiler_other.h"
-#endif /* __GNUC__ */
-
-/**
- * @brief Find last set bit.
- *
- * @param n unsigned 32-bit integer.
- *
- * @return 0 if n == 0 otherwise 32 - the number of leading zeroes in n.
- */
-#define FLS(n) (32 - CLZ(n))
-
-#endif /// ifndef _MVP_COMPILER_H_
diff --git a/arch/arm/mvp/mvpkm/mvp_compiler_gcc.h b/arch/arm/mvp/mvpkm/mvp_compiler_gcc.h
deleted file mode 100644
index ab35ebd..0000000
--- a/arch/arm/mvp/mvpkm/mvp_compiler_gcc.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief common definitions for GCC
- */
-
-#ifndef _MVP_COMPILER_GCC_H
-#define _MVP_COMPILER_GCC_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @brief Count leading zeroes.
- *
- * @param n unsigned 32-bit integer.
- *
- * @return 32 if n == 0 otherwise 31 - the bit position of the most significant 1
- * in n.
- */
-#ifdef __COVERITY__
-static inline int
-CLZ(unsigned int n)
-{
- unsigned int r = 0;
-
- while (n) {
- r++;
- n >>= 1;
- }
-
- return 32 - r;
-}
-#else
-#define CLZ(n) __builtin_clz(n)
-#endif
-
-#define PACKED __attribute__ ((packed))
-#define ALLOC __attribute__ ((malloc, warn_unused_result))
-#define UNUSED __attribute__ ((unused))
-#define PURE __attribute__ ((pure))
-#define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
-#define FORMAT(x,y,z) __attribute__ ((format(x,y,z)))
-#define LIKELY(x) __builtin_expect(!!(x), 1)
-#define UNLIKELY(x) __builtin_expect((x), 0)
-
-/*
- * For debug builds, we want to omit __attribute__((noreturn)) so that gcc will
- * keep stack linkages and then we will have useful core dumps. For non-debug
- * builds, we don't care about the stack frames and want the little bit of
- * optimization that noreturn gives us.
- */
-#if defined(__COVERITY__) || !defined(MVP_DEBUG)
-#define NORETURN __attribute__((noreturn))
-#else
-#define NORETURN
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvp_math.h b/arch/arm/mvp/mvpkm/mvp_math.h
deleted file mode 100644
index 7017bc8..0000000
--- a/arch/arm/mvp/mvpkm/mvp_math.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Math library.
- */
-
-#ifndef _MVP_MATH_H_
-#define _MVP_MATH_H_
-
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_HOSTUSER
-#include "include_check.h"
-
-#include "mvp_compiler_gcc.h"
-
-/**
- * @brief Compute floor log2 of a given 32-bit unsigned integer.
- *
- * @param n 32-bit unsigned integer, n > 0.
- *
- * @return floor(log2(n)).
- */
-#define LOG2(n) \
-( \
- __builtin_constant_p(n) ? ( \
- (n) & (1UL << 31) ? 31 : \
- (n) & (1UL << 30) ? 30 : \
- (n) & (1UL << 29) ? 29 : \
- (n) & (1UL << 28) ? 28 : \
- (n) & (1UL << 27) ? 27 : \
- (n) & (1UL << 26) ? 26 : \
- (n) & (1UL << 25) ? 25 : \
- (n) & (1UL << 24) ? 24 : \
- (n) & (1UL << 23) ? 23 : \
- (n) & (1UL << 22) ? 22 : \
- (n) & (1UL << 21) ? 21 : \
- (n) & (1UL << 20) ? 20 : \
- (n) & (1UL << 19) ? 19 : \
- (n) & (1UL << 18) ? 18 : \
- (n) & (1UL << 17) ? 17 : \
- (n) & (1UL << 16) ? 16 : \
- (n) & (1UL << 15) ? 15 : \
- (n) & (1UL << 14) ? 14 : \
- (n) & (1UL << 13) ? 13 : \
- (n) & (1UL << 12) ? 12 : \
- (n) & (1UL << 11) ? 11 : \
- (n) & (1UL << 10) ? 10 : \
- (n) & (1UL << 9) ? 9 : \
- (n) & (1UL << 8) ? 8 : \
- (n) & (1UL << 7) ? 7 : \
- (n) & (1UL << 6) ? 6 : \
- (n) & (1UL << 5) ? 5 : \
- (n) & (1UL << 4) ? 4 : \
- (n) & (1UL << 3) ? 3 : \
- (n) & (1UL << 2) ? 2 : \
- (n) & (1UL << 1) ? 1 : \
- (n) & (1UL << 0) ? 0 : \
- 0xffffffff \
- ) : (uint32)(CLZ(1) - CLZ(n)) \
-)
-
-/**
- * @brief Multiplicative hash function for 32-bit key and p-bit range. See p229
- * Introduction to Algorithms, Cormen, Leiserson and Rivest, 1996.
- *
- * @param key 32-bit key.
- * @param p range order, <= 32.
- *
- * @return hash value in range [0..2^p)
- */
-static inline uint32
-Math_MultiplicativeHash(uint32 key, uint32 p)
-{
- return (key * 2654435769UL) >> (32 - p);
-}
-
-/**
- * @brief Compute ceiling log2 of a given 32-bit unsigned integer.
- *
- * @param n 32-bit unsigned integer, n > 0.
- *
- * @return ceiling(log2(n)).
- */
-static inline uint32 CLOG2(uint32 n)
-{
- return LOG2(n) + ((n & -n) != n);
-}
-
-
-/**
- * @brief djb2 String hashing function by Dan Bernstein, see
- * http://www.cse.yorku.ca/~oz/hash.html
- * @param str String to hash
- * @return 32-bit hash value
- */
-static inline
-uint32 Math_Djb2Hash(uint8 *str)
-{
- uint32 hash = 5381;
- int32 c;
-
- while ((c = *str++)) {
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
- }
-
- return hash;
-}
-
-#endif // ifndef _MVP_MATH_H_
diff --git a/arch/arm/mvp/mvpkm/mvp_timer.h b/arch/arm/mvp/mvpkm/mvp_timer.h
deleted file mode 100644
index 0bd073a..0000000
--- a/arch/arm/mvp/mvpkm/mvp_timer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief timer definitions
- */
-
-#ifndef _MVP_TIMER_H
-#define _MVP_TIMER_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @brief timer tick rate as returned by MVPTimer_Now64 as a uint64 and used by
- * MVPTimer.when64.
- *
- * For example 1,000,000 means the counter is in microseconds.
- *
- * Current implementation requires MVP_TIMER_RATE64 <= 1,000,000,000 and that
- * it evenly divide 1,000,000,000. Currently 1,000,000,000 to avoid a multiply
- * or divide in MVPTimer_Now64.
- */
-#define MVP_TIMER_RATE64 1000000000
-
-/*
- * Extract current UNIX-style time_t date/time from the 64-bit time as returned
- * by MVPTimer_Now64().
- */
-#define MVP_TIMER_RATE64_TIME_T(time64) ((time_t)((time64) / MVP_TIMER_RATE64))
-
-typedef struct MVPTimer MVPTimer;
-
-/**
- * @brief timer entry struct
- */
-struct MVPTimer {
- MVPTimer *next; ///< next in timers list
- uint64 when64; ///< absolute expiration
- void (*entry)(uint64 now64, MVPTimer *timer); ///< callback entrypoint
- void *param; ///< callback parameter
-};
-
-void MVPTimer_InitVMX(void);
-uint64 MVPTimer_Now64(void);
-void MVPTimer_Start(MVPTimer *timer);
-_Bool MVPTimer_Cancel(MVPTimer *timer);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvp_types.h b/arch/arm/mvp/mvpkm/mvp_types.h
deleted file mode 100644
index 035efd7..0000000
--- a/arch/arm/mvp/mvpkm/mvp_types.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief basic type definitions.
- * These may need to be conditionalized for different compilers/platforms.
- */
-
-#ifndef _MVPTYPES_H
-#define _MVPTYPES_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint32;
-typedef unsigned long long uint64;
-
-typedef signed char int8;
-typedef short int16;
-typedef int int32;
-typedef long long int64;
-
-typedef uint32 CVA; // whatever we are compiling the code as
-typedef uint32 GVA; // guest virtual addresses
-typedef uint32 MVA; // monitor virtual addresses
-typedef uint32 HKVA; // host kernel virtual addresses
-typedef uint32 HUVA; // host user virtual addresses
-typedef uint64 PA; // (guest) physical addresses (40-bit)
-typedef uint32 MA; // (host) machine addresses
-
-typedef uint32 PPN; // PA/PAGE_SIZE
-typedef uint32 MPN; // MA/PAGE_SIZE
-
-typedef uint64 cycle_t;
-
-/**
- * @brief Page segment.
- *
- * Specifies a segment within a single page.
- */
-typedef struct {
- uint16 off;
- uint16 len;
-} PageSeg;
-
-/*
- * GCC's argument checking for printf-like functions
- *
- * fmtPos is the position of the format string argument, beginning at 1
- * varPos is the position of the variable argument, beginning at 1
- */
-
-#if defined(__GNUC__)
-# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos)))
-#else
-# define PRINTF_DECL(fmtPos, varPos)
-#endif
-
-#if defined(__GNUC__)
-# define SCANF_DECL(fmtPos, varPos) __attribute__((__format__(__scanf__, fmtPos, varPos)))
-#else
-# define SCANF_DECL(fmtPos, varPos)
-#endif
-
-#endif /* _MVPTYPES_H */
diff --git a/arch/arm/mvp/mvpkm/mvp_version.h b/arch/arm/mvp/mvpkm/mvp_version.h
deleted file mode 100644
index 31274dd..0000000
--- a/arch/arm/mvp/mvpkm/mvp_version.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief What version is this?
- *
- */
-
-#ifndef _MVP_VERSION_H_
-#define _MVP_VERSION_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#define INCLUDE_ALLOW_HOSTUSER
-#include "include_check.h"
-#include "utils.h"
-
-/*
- * MVP Internal Version Numbering
- *
- *
- * There are 4 different usage areas of version information.
- *
- * Version Name. This is a marketing string that is used to sell the
- * product. The update of this string has legal consequences, it
- * should be done infrequently. Currently we use "V1.0" like
- * terms. Developer builds have E.X.P as Version Name.
- *
- * Android Version Code. This is an integer associated with
- * com.vmware.mvp.apk on Google Play (a.k.a Android Market). If our
- * product is multi-apk (that is, we release individual apks for the
- * different Android versions) then the Android Version Code must
- * satisfy certain constrains. Typically the Android API level is
- * the high order 2 digits.
- *
- * Engineering Version Code. During an update process of one of the
- * 3 components on the handset (MVP, VVP, OEK) compatibility needs
- * to be verified. The Engineering Version Code is a single number
- * associated with each of the 4 components and it serves as a basis
- * of this compatibility test. It reflects time, bigger number is
- * associated with newer code.
- *
- * Git Revision. The git hash is a unique identifier of the
- * source. If picked up from a log, engineers can go to the code
- * depos and check out the exact code used for the build. For MVP,
- * VVP, and OEK this is the main/mvp.git, for HMM it is
- * main/mdm.git. Note that git hash is not ordered, it cannot be
- * used to directly determine precedence.
- *
- */
-
-#define MVP_VERSION_CODE 16800005
-#define MVP_VERSION_CODE_FORMATSTR "%s_%d"
-#define MVP_VERSION_CODE_FORMATARGSV(V_) MVP_STRINGIFY(1.1.3), (V_)
-#define MVP_VERSION_CODE_FORMATARGS \
- MVP_VERSION_CODE_FORMATARGSV(MVP_VERSION_CODE)
-
-#define MVP_VERSION_FORMATSTR \
- MVP_VERSION_CODE_FORMATSTR \
- " compiled at %s based on revision %s by user %s."
-
-#define MVP_VERSION_FORMATARGS \
- MVP_VERSION_CODE_FORMATARGS, \
- __DATE__, \
- MVP_STRINGIFY(5c995a85564cd060562bdbcd1422709e7a326301), \
- MVP_STRINGIFY()
-
-#define MvpVersion_Map(map_, version_) \
- ({ \
- uint32 ii_; \
- uint32 versionApi_ = 0; \
- for (ii_ = 0; ii_ < NELEM(map_); ii_++) { \
- if (map_[ii_] <= version_) { \
- versionApi_ = map_[ii_]; \
- } \
- } \
- versionApi_; \
- })
-
-/*
- * MVP.apk must communicate to VVP and OEK on many of its APIs. To
- * ensure compatibility, it is mandated that any VVP and OEK version
- * younger than the minimums defined below can be serviced on all of
- * the various APIs.
- *
- * During the deprecation process, first a marketing decision is made
- * that the limit below can be raised. After the new minimums are
- * determined, they must be entered here. Then the various APIs can
- * remove code that has been obsoleted before the new minimum versions.
- */
-#define VVP_VERSION_CODE_MIN 0x0100020e
-#define OEK_VERSION_CODE_MIN 0x01000001
-
-#endif /* _MVP_VERSION_H_ */
diff --git a/arch/arm/mvp/mvpkm/mvpkm_comm_ev.c b/arch/arm/mvp/mvpkm/mvpkm_comm_ev.c
deleted file mode 100644
index cb0ce26..0000000
--- a/arch/arm/mvp/mvpkm/mvpkm_comm_ev.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief mvpkm kernel hooks for Comm event signaling
- */
-
-#include <linux/module.h>
-#include "comm_transp_impl.h"
-
-int (*CommTranspEvProcess)(CommTranspID* id, CommTranspIOEvent event);
-
-
-/**
- * @brief Register a processing callback for the host when a signal
- * is received from the guest. Supports only a single comm "service"
- * on the host.
- * @param commProcessFunc function pointer to process a signal
- */
-
-void
-Mvpkm_CommEvRegisterProcessCB(int (*commProcessFunc)(CommTranspID*,
- CommTranspIOEvent))
-{
- CommTranspEvProcess = commProcessFunc;
-}
-
-/**
- * @brief Unregister the processing callback for the host when a signal
- * is received from the guest.
- */
-
-void
-Mvpkm_CommEvUnregisterProcessCB(void)
-{
- CommTranspEvProcess = NULL;
-}
-
-
-EXPORT_SYMBOL(Mvpkm_CommEvRegisterProcessCB);
-EXPORT_SYMBOL(Mvpkm_CommEvUnregisterProcessCB);
diff --git a/arch/arm/mvp/mvpkm/mvpkm_comm_ev.h b/arch/arm/mvp/mvpkm/mvpkm_comm_ev.h
deleted file mode 100644
index 2e3c960..0000000
--- a/arch/arm/mvp/mvpkm/mvpkm_comm_ev.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief mvpkm kernel hooks for comm event signaling
- */
-
-#ifndef _MVPKM_COMM_EV_H
-#define _MVPKM_COMM_EV_H
-
-extern int (*CommTranspEvProcess)(CommTranspID* id, CommTranspIOEvent event);
-
-/**
- * @brief Forward any guest signal requests to the commkm module
- * @param id transport channel id
- * @param event comm event type
- */
-
-static inline void
-Mvpkm_CommEvSignal(CommTranspID *id, CommTranspIOEvent event)
-{
- if (CommTranspEvProcess) {
- CommTranspEvProcess(id, event);
- }
-}
-
-void
-Mvpkm_CommEvRegisterProcessCB(int (*commProcessFunc)(CommTranspID*,
- CommTranspIOEvent));
-void Mvpkm_CommEvUnregisterProcessCB(void);
-
-
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvpkm_kernel.h b/arch/arm/mvp/mvpkm/mvpkm_kernel.h
deleted file mode 100644
index 19ba6ce..0000000
--- a/arch/arm/mvp/mvpkm/mvpkm_kernel.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#ifndef _MVPKM_KERNEL_H
-#define _MVPKM_KERNEL_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include <linux/rwsem.h>
-#include <linux/kobject.h>
-#include <linux/rbtree.h>
-
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-
-#include "atomic.h"
-#include "montimer_kernel.h"
-#include "worldswitch.h"
-
-/**
- * @file
- *
- * @brief The kernel level driver.
- */
-
-struct MvpkmVM {
- struct kobject kobj; ///< used to hook into sysfs
- struct kset *devicesKSet; ///< kset to list virtual device entries
- struct kset *miscKSet; ///< kset to list miscellaneous entries
- _Bool haveKObj; ///< used to properly release instance
- struct rb_root lockedRoot; ///< locked page RB tree root
- struct rw_semaphore lockedSem; ///< linked list rw semaphore
- AtmUInt32 usedPages; ///< number of MEMREGION_MAINMEM pages
- _Bool isMonitorInited; ///< Has SetupMonitor been called already?
- WorldSwitchPage *wsp; ///< worldswitch page
- wait_queue_head_t wfiWaitQ; ///< guest VCPU is waiting-for-interrupt
- struct rw_semaphore wspSem; /*< prevents entries the WFI
- wait Q from disappearing
- underneath us in
- MvpkmShrink. */
- MonTimer monTimer; /*< monitor timers, there
- should be one of these
- per VCPU */
- MPN stubPageMPN; /*< stub page to be used for
- unmappable pages */
- struct vm_struct *wspHkvaArea; ///< VM area struct for wspHkvaArea
- HKVA wspHKVADummyPage;///< Dummy page used for backing wspHkvaArea
-#ifdef CONFIG_HAS_WAKELOCK
- struct wake_lock wakeLock; ///< guest running wake lock
-#endif
- struct rw_semaphore monThreadTaskSem;/*< prevents monThreadTask from
- disappearing underneath us */
- struct task_struct *monThreadTask;
- struct timer_list balloonWDTimer; /// Balloon watchdog timer
- _Bool balloonWDEnabled; /// Balloon watchdog enabled?
-};
-
-typedef struct MvpkmVM MvpkmVM;
-
-void Mvpkm_WakeGuest(MvpkmVM *vm, int why);
-struct kset *Mvpkm_FindVMNamedKSet(int vmID, const char *name);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvpkm_main.c b/arch/arm/mvp/mvpkm/mvpkm_main.c
deleted file mode 100644
index d32a4c1..0000000
--- a/arch/arm/mvp/mvpkm/mvpkm_main.c
+++ /dev/null
@@ -1,2691 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief The kernel level driver.
- */
-
-#define __KERNEL_SYSCALLS__
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/fcntl.h>
-#include <linux/syscalls.h>
-#include <linux/kmod.h>
-#include <linux/socket.h>
-#include <linux/net.h>
-#include <linux/skbuff.h>
-#include <linux/miscdevice.h>
-#include <linux/poll.h>
-#include <linux/smp.h>
-#include <linux/capability.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/sysfs.h>
-#include <linux/pid.h>
-#include <linux/highmem.h>
-#include <linux/syscalls.h>
-
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-
-#include <net/sock.h>
-
-#include <asm/cacheflush.h>
-#include <asm/memory.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "mvp.h"
-#include "mvp_version.h"
-#include "mvpkm_types.h"
-#include "mvpkm_private.h"
-#include "mvpkm_kernel.h"
-#include "actions.h"
-#include "wscalls.h"
-#include "arm_inline.h"
-#include "tsc.h"
-#include "mksck_kernel.h"
-#include "mmu_types.h"
-#include "mvp_timer.h"
-#include "qp.h"
-#include "qp_host_kernel.h"
-#include "cpufreq_kernel.h"
-#include "mvpkm_comm_ev.h"
-#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER
-#include "mvp_balloon.h"
-#endif
-
-
-/*********************************************************************
- *
- * Definition of the file operations
- *
- *********************************************************************/
-static _Bool LockedListAdd(MvpkmVM *vm,
- __u32 mpn,
- __u32 order,
- PhysMem_RegionType forRegion);
-static _Bool LockedListDel(MvpkmVM *vm, __u32 mpn);
-static void LockedListUnlockAll(MvpkmVM *vm);
-static _Bool LockedListLookup(MvpkmVM *vm, __u32 mpn);
-static int SetupMonitor(MvpkmVM *vm);
-static int RunMonitor(MvpkmVM *vm);
-static MPN AllocZeroedFreePages(MvpkmVM *vm,
- uint32 order,
- _Bool highmem,
- PhysMem_RegionType forRegion,
- HKVA *hkvaRet);
-static HKVA MapWSPHKVA(MvpkmVM *vm, HkvaMapInfo *mapInfo);
-static void UnmapWSPHKVA(MvpkmVM *vm);
-static int MvpkmWaitForInt(MvpkmVM *vm, _Bool suspend);
-static void ReleaseVM(MvpkmVM *vm);
-
-/*
- * Mksck open request must come from this uid. It must be root until
- * it is set via an ioctl from mvpd.
- */
-uid_t Mvpkm_vmwareUid = 0;
-EXPORT_SYMBOL(Mvpkm_vmwareUid);
-
-/*
- * Minimum hidden app oom_adj, provided by mvpd, since we can't get it directly
- * from the lowmemorykiller module.
- */
-static int minHiddenAppOOMAdj;
-
-/*
- * vCPU cpu affinity to let monitor/guest run on some CPUs only (when possible)
- */
-static DECLARE_BITMAP(vcpuAffinity, NR_CPUS);
-
-/*********************************************************************
- *
- * Sysfs nodes
- *
- *********************************************************************/
-/*
- * kobject for our sysfs representation, used for global nodes.
- */
-static struct kobject *mvpkmKObj;
-
-/*
- * kobject for the balloon exports.
- */
-static struct kobject *balloonKObj;
-
-/**
- * @brief sysfs show function for global version attribute.
- *
- * @param kobj reference to kobj nested in MvpkmVM struct.
- * @param attr kobj_attribute reference, not used.
- * @param buf PAGE_SIZEd buffer to write to.
- *
- * @return number of characters printed (not including trailing null character).
- */
-static ssize_t
-version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, MVP_VERSION_FORMATSTR "\n", MVP_VERSION_FORMATARGS);
-}
-
-static struct kobj_attribute versionAttr = __ATTR_RO(version);
-
-/**
- * @brief sysfs show function for global background_pages attribute.
- *
- * Used by vmx balloon policy controller to gauge the amount of freeable
- * anonymous memory.
- *
- * @param kobj reference to kobj nested in MvpkmVM struct.
- * @param attr kobj_attribute reference, not used.
- * @param buf PAGE_SIZEd buffer to write to.
- *
- * @return number of characters printed (not including trailing null character).
- */
-static ssize_t
-background_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
-#ifndef CONFIG_ANDROID_LOW_MEMORY_KILLER
- return snprintf(buf, PAGE_SIZE, "0\n");
-#else
- return snprintf(buf, PAGE_SIZE, "%d\n", Balloon_AndroidBackgroundPages(minHiddenAppOOMAdj));
-#endif
-}
-
-static struct kobj_attribute backgroundAttr = __ATTR_RO(background);
-
-/**
- * @brief sysfs show function to export the other_file calculation in
- * lowmemorykiller.
- *
- * It's helpful, in the balloon controller, to know what the lowmemorykiller
- * module is using to know when the system has crossed a minfree threshold.
- * Since there exists a number of different other_file calculations in various
- * lowmemorykiller patches (@see{MVP-1674}), and the module itself doesn't
- * provide a clean export of this figure, we provide it on a case-by-case basis
- * for the various supported hosts here.
- *
- * @param kobj reference to kobj nested in MvpkmVM struct.
- * @param attr kobj_attribute reference, not used.
- * @param buf PAGE_SIZEd buffer to write to.
- *
- * @return number of characters printed (not including trailing null character).
- */
-static ssize_t
-other_file_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
- int32 other_file = 0;
-
-#ifndef LOWMEMKILLER_VARIANT
-#define LOWMEMKILLER_VARIANT 0
-#endif
-
-#ifndef LOWMEMKILLER_MD5
-#define LOWMEMKILLER_MD5 0
-#endif
-
-#ifndef LOWMEMKILLER_SHRINK_MD5
-#define LOWMEMKILLER_SHRINK_MD5 0
-#endif
-
- /*
- * The build system hashes the lowmemorykiller section related to the
- * other_file calculation in the kernel source for us, here we have to
- * provide the code.
- */
-#if LOWMEMKILLER_VARIANT == 1
- /*
- * This is the same as the non-exported global_reclaimable_pages() when there
- * is no swap.
- */
- other_file = global_page_state(NR_ACTIVE_FILE) +
- global_page_state(NR_INACTIVE_FILE);
-#elif LOWMEMKILLER_VARIANT == 2
- other_file = global_page_state(NR_FILE_PAGES);
-#elif LOWMEMKILLER_VARIANT == 3
- other_file = global_page_state(NR_FILE_PAGES) - global_page_state(NR_SHMEM);
-#elif LOWMEMKILLER_VARIANT == 4
- /*
- * Here free/file pages are fungible and max(free, file) isn't used, but we
- * can continue to use max(free, file) since max(free, file) = other_file in
- * this case.
- */
- other_file = global_page_state(NR_FREE_PAGES) + global_page_state(NR_FILE_PAGES);
-#elif defined(NONANDROID)
- /*
- * Non-Android host platforms don't have ballooning enabled.
- */
-#else
- /*
- * If you get this message, you need to run 'make lowmem-info' and inspect
- * lowmemorykiller.c. If the "other_file = ..." calculation in lowmem_shrink
- * appears above, simply add the "Shrink#" to an existing entry in
- * lowmemkiller-variant.sh, pointing to the variant number above. Otherwise,
- * provide a new entry above and variant number, with the appropriate
- * other_file calculation and update lowmemkiller-variant.sh accordingly.
- */
-//#warning "Unknown lowmemorykiller variant in hosted/module/mvpkm_main.c, falling back on default (see other_file_show for the remedy)"
- /*
- * Fall back on default - this may bias strangely for/against the host, but
- * nothing catastrophic should result.
- */
- other_file = global_page_state(NR_FILE_PAGES);
-#endif
-
-#define _STRINGIFY(x) #x
-#define STRINGIFY(x) _STRINGIFY(x)
- return snprintf(buf,
- PAGE_SIZE,
- "%d %d %s %s\n",
- other_file,
- LOWMEMKILLER_VARIANT,
- STRINGIFY(LOWMEMKILLER_MD5),
- STRINGIFY(LOWMEMKILLER_SHRINK_MD5));
-#undef _STRINGIFY
-#undef STRINGIFY
-}
-
-static struct kobj_attribute otherFileAttr = __ATTR_RO(other_file);
-
-/*
- * kset for our sysfs representation, used for per-VM nodes.
- */
-static struct kset *mvpkmKSet;
-
-static ssize_t MvpkmAttrShow(struct kobject *kobj,
- struct attribute *attr,
- char *buf);
-static ssize_t MvpkmAttrStore(struct kobject *kobj,
- struct attribute *attr,
- const char *buf,
- size_t count);
-
-static void MvpkmKObjRelease(struct kobject *kobj)
- __attribute__ ((optimize ("-fomit-frame-pointer")));
-
-
-/**
- * @brief Releases the vm structure containing the kobject.
- *
- * @param kobj the vm's kobject.
- */
-
-static void
-MvpkmKObjRelease(struct kobject *kobj)
-{
- MvpkmVM *vm = container_of(kobj, MvpkmVM, kobj);
-
- ReleaseVM(vm);
-
- module_put(THIS_MODULE);
-}
-
-
-/**
- * @name mvpkm ktype attribute structures for locked_pages.
- *
- * @{
- */
-static struct sysfs_ops mvpkmSysfsOps = {
- .show = MvpkmAttrShow,
- .store = MvpkmAttrStore
-};
-
-static struct attribute mvpkmLockedPagesAttr = {
- .name = "locked_pages",
- .mode = 0444,
-};
-
-static struct attribute mvpkmBalloonWatchdogAttr = {
- .name = "balloon_watchdog",
- .mode = 0666
-};
-
-static struct attribute mvpkmMonitorAttr = {
- .name = "monitor",
- .mode = 0400,
-};
-
-static struct attribute *mvpkmDefaultAttrs[] = {
- &mvpkmLockedPagesAttr,
- &mvpkmBalloonWatchdogAttr,
- &mvpkmMonitorAttr,
- NULL,
-};
-
-static struct kobj_type mvpkmKType = {
- .sysfs_ops = &mvpkmSysfsOps,
- .release = MvpkmKObjRelease,
- .default_attrs = mvpkmDefaultAttrs,
-};
-/*@}*/
-
-/*
- * As it is not very common for host kernels to have SYS_HYPERVISOR enabled and
- * you have to "hack" a Kconfig file to enable it, just include the
- * functionality inline if it is not enabled.
- */
-#ifndef CONFIG_SYS_HYPERVISOR
-struct kobject *hypervisor_kobj;
-EXPORT_SYMBOL_GPL(hypervisor_kobj);
-#endif
-
-
-/*
- * kobject and kset utilities.
- */
-
-extern struct kobject *kset_find_obj(struct kset *, const char *)
- __attribute__((weak));
-
-
-/**
- * @brief Finds a kobject in a kset. The actual implementation is copied from
- * kernel source in lib/kobject.c. Although the symbol is extern-declared,
- * it is not EXPORT_SYMBOL-ed. We use a weak reference in case the symbol
- * might be exported in future kernel versions.
- *
- * @param kset set to search.
- * @param name object name.
- *
- * @return retained kobject if found, NULL otherwise.
- */
-
-struct kobject *
-kset_find_obj(struct kset *kset,
- const char *name)
-{
- struct kobject *k;
- struct kobject *ret = NULL;
-
- spin_lock(&kset->list_lock);
- list_for_each_entry(k, &kset->list, entry) {
- if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
- ret = kobject_get(k);
- break;
- }
- }
- spin_unlock(&kset->list_lock);
- return ret;
-}
-
-
-/**
- * @brief Finds one of the VM's pre-defined ksets.
- *
- * @param vmID a VM ID.
- * @param name name of one of the VM's pre-defined ksets.
- *
- * @return retained kset if found, NULL otherwise.
- */
-
-struct kset *
-Mvpkm_FindVMNamedKSet(int vmID,
- const char *name)
-{
- MvpkmVM *vm;
- struct kobject *kobj;
- char vmName[32] = {}; /* Large enough to hold externally-formatted int32. */
- struct kset *res = NULL;
-
- if (!mvpkmKSet) {
- return NULL;
- }
-
- snprintf(vmName, sizeof vmName, "%d", vmID);
- vmName[sizeof vmName - 1] = '\0'; /* Always null-terminate, no overflow. */
-
- kobj = kset_find_obj(mvpkmKSet, vmName);
- if (!kobj) {
- return NULL;
- }
-
- vm = container_of(kobj, MvpkmVM, kobj);
-
- if (!strcmp(name, "devices")) {
- res = kset_get(vm->devicesKSet);
- } else if (!strcmp(name, "misc")) {
- res = kset_get(vm->miscKSet);
- }
-
- kobject_put(kobj);
- return res;
-}
-
-EXPORT_SYMBOL(Mvpkm_FindVMNamedKSet);
-
-
-
-/*********************************************************************
- *
- * Standard Linux miscellaneous device registration
- *
- *********************************************************************/
-
-MODULE_LICENSE("GPL"); // for kallsyms_lookup_name
-
-static int MvpkmFault(struct vm_area_struct *vma, struct vm_fault *vmf);
-
-
-/**
- * @brief Linux vma operations for /dev/mem-like kernel module mmap. We
- * enforce the restriction that only MPNs that have been allocated
- * to the opened VM may be mapped and also increment the reference
- * count (via vm_insert_page), so that even if the memory is later
- * freed by the VM, host process vma's containing the MPN can't
- * compromise the system.
- *
- * However, only trusted host processes (e.g. the vmx) should be allowed
- * to use this interface, since you can mmap the monitor's code/data/
- * page tables etc. with it. Untrusted host processes are limited to
- * typed messages for sharing memory with the monitor. Unix file system
- * access permissions are the intended method of restricting access.
- * Unfortunately, today _any_ host process utilizing Mksck requires
- * access to mvpkm to setup its Mksck pages and obtain socket info via
- * ioctls - we probably should be exporting two devices, one for trusted
- * and one for arbitrary host processes to avoid this confusion of
- * concerns.
- */
-static struct vm_operations_struct mvpkmVMOps = {
- .fault = MvpkmFault
-};
-
-/*
- * Generic kernel module file ops. These functions will be registered
- * at the time the kernel module is loaded.
- */
-static long MvpkmUnlockedIoctl(struct file *filep,
- unsigned int cmd,
- unsigned long arg);
-static int MvpkmOpen(struct inode *inode, struct file *filp);
-static int MvpkmRelease(struct inode *inode, struct file *filp);
-static int MvpkmMMap(struct file *file, struct vm_area_struct *vma);
-
-/**
- * @brief the file_operation structure contains the callback functions
- * that are registered with Linux to handle file operations on
- * the mvpkm device.
- *
- * The structure contains other members that the mvpkm device
- * does not use. Those members are auto-initialized to NULL.
- *
- * WARNING, this structure has changed after Linux kernel 2.6.19:
- * readv/writev are changed to aio_read/aio_write (neither is used here).
- */
-static const struct file_operations mvpkmFileOps = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = MvpkmUnlockedIoctl,
- .open = MvpkmOpen,
- .release = MvpkmRelease,
- .mmap = MvpkmMMap
-};
-
-/**
- * @brief The mvpkm device identifying information to be used to register
- * the device with the Linux kernel.
- */
-static struct miscdevice mvpkmDev = {
- .minor = 165,
- .name = "mvpkm",
- .fops = &mvpkmFileOps
-};
-
-/**
- * Mvpkm is loaded by mvpd and only mvpd will be allowed to open
- * it. There is a very simple way to verify that: record the process
- * id (thread group id) at the time the module is loaded and test it
- * at the time the module is opened.
- */
-static struct pid *initTgid;
-
-
-#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER
-/**
- * @name Slab shrinker for triggering balloon adjustment.
- *
- * @note shrinker us used as a trigger for guest balloon.
- *
- * @{
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
-static int MvpkmShrink(struct shrinker *this, struct shrink_control *sc);
-#else
-static int MvpkmShrink(struct shrinker *this, int nrToScan, gfp_t gfpMask);
-#endif
-
-static struct shrinker mvpkmShrinker = {
- .shrink = MvpkmShrink,
- .seeks = DEFAULT_SEEKS
-};
-/*@}*/
-#endif
-
-module_param_array(vcpuAffinity, ulong, NULL, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(vcpuAffinity, "vCPU affinity");
-
-
-/**
- * @brief Initialize the mvpkm device, register it with the Linux kernel.
- *
- * @return A zero is returned on success and a negative errno code for failure.
- * (Same as the return policy of misc_register(9).)
- */
-
-static int __init
-MvpkmInit(void)
-{
- int err = 0;
- _Bool mksckInited = false;
- _Bool cpuFreqInited = false;
-
- printk(KERN_INFO "Mvpkm: " MVP_VERSION_FORMATSTR "\n", MVP_VERSION_FORMATARGS);
- printk(KERN_INFO "Mvpkm: loaded from process %s tgid=%d, pid=%d\n",
- current->comm,
- task_tgid_vnr(current),
- task_pid_vnr(current));
-
- if (bitmap_empty(vcpuAffinity, NR_CPUS)) {
- bitmap_copy(vcpuAffinity, cpumask_bits(cpu_possible_mask), NR_CPUS);
- }
-
- if ((err = misc_register(&mvpkmDev))) {
- return -ENOENT;
- }
-
- if ((err = Mksck_Init())) {
- goto error;
- } else {
- mksckInited = true;
- }
-
- QP_HostInit();
-
- CpuFreq_Init();
- cpuFreqInited = true;
-
- /*
- * Reference mvpd (module loader) tgid struct, so that we can avoid
- * attacks based on pid number wraparound.
- */
- initTgid = get_pid(task_tgid(current));
-
-#ifndef CONFIG_SYS_HYPERVISOR
- hypervisor_kobj = kobject_create_and_add("hypervisor", NULL);
- if (!hypervisor_kobj) {
- err = -ENOMEM;
- goto error;
- }
-#endif
-
- if (!(mvpkmKObj = kobject_create_and_add("mvp", hypervisor_kobj)) ||
- !(balloonKObj = kobject_create_and_add("lowmem", mvpkmKObj)) ||
- !(mvpkmKSet = kset_create_and_add("vm", NULL, mvpkmKObj))) {
- err = -ENOMEM;
- goto error;
- }
-
- if ((err = sysfs_create_file(mvpkmKObj, &versionAttr.attr))) {
- goto error;
- }
-
- if ((err = sysfs_create_file(balloonKObj, &backgroundAttr.attr))) {
- goto error;
- }
-
- if ((err = sysfs_create_file(balloonKObj, &otherFileAttr.attr))) {
- goto error;
- }
-
-#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER
- register_shrinker(&mvpkmShrinker);
-#endif
-
- MksckPageInfo_Init();
-
- return 0;
-
-error:
- if (mvpkmKSet) {
- kset_unregister(mvpkmKSet);
- }
-
- if (balloonKObj) {
- kobject_del(balloonKObj);
- kobject_put(balloonKObj);
- }
-
- if (mvpkmKObj) {
- kobject_del(mvpkmKObj);
- kobject_put(mvpkmKObj);
- }
-
-#ifndef CONFIG_SYS_HYPERVISOR
- if (hypervisor_kobj) {
- kobject_del(hypervisor_kobj);
- kobject_put(hypervisor_kobj);
- }
-#endif
-
- if (cpuFreqInited) {
- CpuFreq_Exit();
- }
-
- if (mksckInited) {
- Mksck_Exit();
- }
-
- if (initTgid) {
- put_pid(initTgid);
- }
-
- misc_deregister(&mvpkmDev);
- return err;
-}
-
-/**
- * @brief De-register the mvpkm device with the Linux kernel.
- */
-void
-MvpkmExit(void)
-{
- PRINTK(KERN_INFO "MvpkmExit called !\n");
-
- MksckPageInfo_Exit();
-
-#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER
- unregister_shrinker(&mvpkmShrinker);
-#endif
-
- kset_unregister(mvpkmKSet);
- kobject_del(balloonKObj);
- kobject_put(balloonKObj);
- kobject_del(mvpkmKObj);
- kobject_put(mvpkmKObj);
-#ifndef CONFIG_SYS_HYPERVISOR
- kobject_del(hypervisor_kobj);
- kobject_put(hypervisor_kobj);
-#endif
-
- CpuFreq_Exit();
-
- Mksck_Exit();
-
- put_pid(initTgid);
-
- misc_deregister(&mvpkmDev);
-}
-
-/*
- * The standard module registration macros of Linux.
- */
-module_init(MvpkmInit);
-module_exit(MvpkmExit);
-
-module_param_named(minHiddenAppOOMAdj, minHiddenAppOOMAdj, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(minHiddenAppOOMAdj, "minimum hidden app oom_adj, as per lowmemorykiller");
-
-#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER
-/**
- * @brief Balloon watchdog timeout callback.
- *
- * Terminate the VM since it's not responsive.
- *
- * @param data vm reference representation.
- */
-static void
-WatchdogCB(unsigned long data)
-{
- MvpkmVM *vm = (MvpkmVM *)data;
-
- printk("Balloon watchdog expired (%d s)!\n", BALLOON_WATCHDOG_TIMEOUT_SECS);
-
- Mvpkm_WakeGuest(vm, ACTION_ABORT);
-}
-
-/**
- * @brief Slab shrinker.
- *
- * Called by Linux kernel when we're under memory pressure. We treat all locked
- * pages as a slab for this purpose, similar to the Android low memory killer.
- *
- * @param this reference to registered shrinker for callback context.
- * @param nrToScan number of entries to scan. If 0 then just return the number
- * of present entries. We ignore the value of nrToScan when > 1
- * since the shrinker is a trigger to readjust guest balloons,
- * where the actual balloon size is determined in conjunction
- * with the guest.
- * @param gfpMask ignored.
- *
- * @return number of locked pages.
- */
-static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
-MvpkmShrink(struct shrinker *this, struct shrink_control *sc)
-#else
-MvpkmShrink(struct shrinker *this, int nrToScan, gfp_t gfpMask)
-#endif
-{
- uint32 locked = 0;
- struct kobject *k;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
- int nrToScan = sc->nr_to_scan;
-#endif
-
- spin_lock(&mvpkmKSet->list_lock);
-
- list_for_each_entry(k, &mvpkmKSet->list, entry) {
- MvpkmVM *vm = container_of(k, MvpkmVM, kobj);
-
- locked += ATOMIC_GETO(vm->usedPages);
-
- /*
- * Try and grab the WSP semaphore - if we fail, we must be VM setup or
- * teardown, no point trying to wake the guest.
- */
- if (nrToScan > 0 &&
- down_read_trylock(&vm->wspSem)) {
-
- if (vm->wsp) {
- Mvpkm_WakeGuest(vm, ACTION_BALLOON);
-
- /*
- * Balloon watchdog.
- */
- if (vm->balloonWDEnabled) {
- struct timer_list *t = &vm->balloonWDTimer;
-
- if (!timer_pending(t)) {
- t->data = (unsigned long)vm;
- t->function = WatchdogCB;
- t->expires = jiffies + BALLOON_WATCHDOG_TIMEOUT_SECS * HZ;
- add_timer(t);
- }
- }
- }
-
- up_read(&vm->wspSem);
- }
- }
-
- spin_unlock(&mvpkmKSet->list_lock);
-
- return locked;
-}
-#endif
-
-
-/**
- * @brief The open file operation. Initializes the vm specific structure.
- */
-int
-MvpkmOpen(struct inode *inode, struct file *filp)
-{
- MvpkmVM *vm;
-
- if (initTgid != task_tgid(current)) {
- printk(KERN_ERR "%s: MVPKM can be opened only from MVPD (process %d).\n",
- __FUNCTION__, pid_vnr(initTgid));
- return -EPERM;
- }
- printk(KERN_DEBUG "%s: Allocating an MvpkmVM structure from process %s tgid=%d, pid=%d\n",
- __FUNCTION__,
- current->comm,
- task_tgid_vnr(current),
- task_pid_vnr(current));
-
- vm = kmalloc(sizeof(MvpkmVM), GFP_KERNEL);
- if (!vm) {
- return -ENOMEM;
- }
-
- memset(vm, 0, sizeof *vm);
-
- init_timer(&vm->balloonWDTimer);
- init_rwsem(&vm->lockedSem);
- init_rwsem(&vm->wspSem);
- init_rwsem(&vm->monThreadTaskSem);
- vm->monThreadTask = NULL;
- vm->isMonitorInited = false;
-
- filp->private_data = vm;
-
- if (!Mvpkm_vmwareUid) {
- Mvpkm_vmwareUid = current_euid();
- }
-
- return 0;
-}
-
-/**
- * @brief Releases a VMs resources
- * @param vm vm to release
- */
-static void
-ReleaseVM(MvpkmVM *vm)
-{
- del_timer_sync(&vm->balloonWDTimer);
-
- down_write(&vm->wspSem);
-
- if (vm->isMonitorInited) {
- MonitorTimer_Request(&vm->monTimer, 0);
-#ifdef CONFIG_HAS_WAKELOCK
- wake_lock_destroy(&vm->wakeLock);
-#endif
- Mksck_WspRelease(vm->wsp);
- vm->wsp = NULL;
- }
-
- up_write(&vm->wspSem);
-
- LockedListUnlockAll(vm);
-
- UnmapWSPHKVA(vm);
-
- /*
- * All sockets potentially connected to sockets of this vm's vmId will fail
- * at send now. DGRAM sockets are note required to tear down connection
- * explicitly.
- */
-
- kfree(vm);
-}
-
-/**
- * @brief The release file operation. Releases the vm specific
- * structure including all the locked pages.
- *
- * @param inode Unused
- * @param filp which VM we're dealing with
- * @return 0
- */
-int
-MvpkmRelease(struct inode *inode, struct file *filp)
-{
- MvpkmVM *vm = filp->private_data;
-
- /*
- * Tear down any queue pairs associated with this VM
- */
- if (vm->isMonitorInited) {
- ASSERT(vm->wsp);
- QP_DetachAll(vm->wsp->guestId);
- }
-
- /*
- * Release the VM's ksets.
- */
-
- kset_unregister(vm->miscKSet);
- kset_unregister(vm->devicesKSet);
-
- if (vm->haveKObj) {
- /*
- * Release the VM's kobject.
- * 'vm' will be kfree-d in its kobject's release function.
- */
-
- kobject_del(&vm->kobj);
- kobject_put(&vm->kobj);
- } else {
- ReleaseVM(vm);
- }
-
- filp->private_data = NULL;
-
- printk(KERN_INFO "%s: Released MvpkmVM structure from process %s tgid=%d, pid=%d\n",
- __FUNCTION__,
- current->comm,
- task_tgid_vnr(current),
- task_pid_vnr(current));
-
- return 0;
-}
-
-/**
- * @brief Page fault handler for /dev/mem-like regions (see mvpkmVMOps
- * block comment).
- */
-static int
-MvpkmFault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- unsigned long address = (unsigned long)vmf->virtual_address;
- MPN mpn = vmf->pgoff;
- MvpkmVM *vm = vma->vm_file->private_data;
-
-
- /*
- * Only insert pages belonging to the VM. The check is slow, O(n) in the
- * number of MPNs associated with the VM, but it doesn't matter - the mmap
- * interface should only be used by trusted processes at initialization
- * time and for debugging.
- *
- * The mpn can be either in the memory reserved the monitor or mvpd
- * through the regular mechanisms or it could be a mksck page.
- */
- if (!pfn_valid(mpn)) {
- printk(KERN_ERR "MvpkmMMap: Failed to insert %x @ %lx, mpn invalid\n",
- mpn,
- address);
- } else if (LockedListLookup(vm, mpn)) {
- if (vm_insert_page(vma, address, pfn_to_page(mpn)) == 0) {
- return VM_FAULT_NOPAGE;
- }
-
- printk(KERN_ERR "MvpkmMMap: Failed to insert %x @ %lx \n",
- mpn,
- address);
- } else if (MksckPage_LookupAndInsertPage(vma, address, mpn) == 0) {
- return VM_FAULT_NOPAGE;
- }
-
- if (vm->stubPageMPN) {
- if (vm_insert_page(vma, address, pfn_to_page(vm->stubPageMPN)) == 0) {
- printk(KERN_INFO "MvpkmMMap: mapped the stub page at %x @ %lx \n",
- mpn,
- address);
- return VM_FAULT_NOPAGE;
- }
-
- printk(KERN_ERR "MvpkmMMap: Could not insert stub page %x @ %lx \n",
- mpn,
- address);
-
- }
-
- return VM_FAULT_SIGBUS;
-}
-
-/**
- * @brief sysfs show function for per-VM locked_pages attribute.
- *
- * @param kobj reference to kobj nested in MvpkmVM struct.
- * @param attr attribute reference.
- * @param buf PAGE_SIZEd buffer to write to.
- *
- * @return number of characters printed (not including trailing null character).
- */
-static ssize_t
-MvpkmAttrShow(struct kobject *kobj,
- struct attribute *attr,
- char *buf)
-{
- if (attr == &mvpkmLockedPagesAttr) {
- MvpkmVM *vm = container_of(kobj, MvpkmVM, kobj);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", ATOMIC_GETO(vm->usedPages));
- } else if (attr == &mvpkmMonitorAttr) {
- MvpkmVM *vm = container_of(kobj, MvpkmVM, kobj);
-
- return snprintf(buf,
- PAGE_SIZE,
- "hostActions %x callno %d\n",
- ATOMIC_GETO(vm->wsp->hostActions),
- WSP_Params(vm->wsp)->callno);
- } else {
- return -EPERM;
- }
-}
-
-/**
- * @brief sysfs store function for per-VM locked_pages attribute.
- *
- * @param kobj reference to kobj nested in MvpkmVM struct.
- * @param attr attribute reference.
- * @param buf PAGE_SIZEd buffer to write to.
- * @param buf input buffer.
- * @param count input buffer length.
- *
- * @return number of bytes consumed or negative error code.
- */
-static ssize_t
-MvpkmAttrStore(struct kobject *kobj,
- struct attribute *attr,
- const char *buf,
- size_t count)
-{
- if (attr == &mvpkmBalloonWatchdogAttr) {
- MvpkmVM *vm = container_of(kobj, MvpkmVM, kobj);
-
- /*
- * Enable balloon watchdog on first write. This includes all ballooning
- * capable guest.
- */
- vm->balloonWDEnabled = true;
- del_timer_sync(&vm->balloonWDTimer);
-
- return 1;
- } else {
- return -EPERM;
- }
-}
-
-/**
- * @brief Map machine address space region into host process.
- *
- * @param file file reference (ignored).
- * @param vma Linux virtual memory area defining the region.
- *
- * @return 0 on success, otherwise error code.
- */
-static int
-MvpkmMMap(struct file *file, struct vm_area_struct *vma)
-{
- vma->vm_ops = &mvpkmVMOps;
-
- return 0;
-}
-
-#ifdef CONFIG_ARM_LPAE
-/**
- * @brief Determine host cacheability/shareability attributes.
- *
- * Used to ensure monitor/guest shared mappings are consistent with
- * those of host user/kernel.
- *
- * @param[out] attribMAN when setting up the HW monitor this provides the
- * attributes in the generic ARM_MemAttrNormal form,
- * suitable for configuring the monitor and guest's
- * [H]MAIR0 and setting the shareability attributes of
- * the LPAE descriptors.
- */
-static void
-DetermineMemAttrLPAE(ARM_MemAttrNormal *attribMAN)
-{
- /*
- * We use set_pte_ext to sample what {S,TEX,CB} bits Linux is using for
- * normal kernel/user L2D mappings. These bits should be consistent both
- * with each other and what we use in the monitor since we share various
- * pages with both host processes, the kernel module and monitor, and the
- * ARM ARM requires that synonyms have the same cacheability attributes,
- * see end of A3.5.{4,7} ARM DDI 0406A.
- */
- HKVA hkva = __get_free_pages(GFP_KERNEL, 0);
-
- ARM_LPAE_L3D *pt = (ARM_LPAE_L3D *)hkva;
- ARM_LPAE_L3D *kernL3D = &pt[0], *userL3D = &pt[1];
- uint32 attr, mair0, mair1;
-
- set_pte_ext((pte_t *)kernL3D, pfn_pte(0, PAGE_KERNEL), 0);
- set_pte_ext((pte_t *)userL3D, pfn_pte(0, PAGE_NONE), 0);
-
- printk(KERN_INFO
- "DetermineMemAttr: Kernel L3D AttrIndx=%x SH=%x\n",
- kernL3D->blockS1.attrIndx,
- kernL3D->blockS1.sh);
-
- printk(KERN_INFO
- "DetermineMemAttr: User L3D AttrIndx=%x SH=%x\n",
- userL3D->blockS1.attrIndx,
- userL3D->blockS1.sh);
-
- ASSERT(kernL3D->blockS1.attrIndx == userL3D->blockS1.attrIndx);
- ASSERT(kernL3D->blockS1.sh == userL3D->blockS1.sh);
-
- switch (kernL3D->blockS1.sh) {
- case 0: {
- attribMAN->share = ARM_SHARE_ATTR_NONE;
- break;
- }
- case 2: {
- attribMAN->share = ARM_SHARE_ATTR_OUTER;
- break;
- }
- case 3: {
- attribMAN->share = ARM_SHARE_ATTR_INNER;
- break;
- }
- default: {
- FATAL();
- }
- }
-
- ARM_MRC_CP15(MAIR0, mair0);
- ARM_MRC_CP15(MAIR1, mair1);
-
- attr = MVP_EXTRACT_FIELD(kernL3D->blockS1.attrIndx >= 4 ? mair1 : mair0,
- 8 * (kernL3D->blockS1.attrIndx % 4),
- 8);
-
- /*
- * See B4-1615 ARM DDI 0406C-2c for magic.
- */
-#define MAIR_ATTR_2_CACHE_ATTR(x, y) \
- switch (x) { \
- case 2: { \
- (y) = ARM_CACHE_ATTR_NORMAL_WT; \
- break; \
- } \
- case 3: { \
- (y) = ARM_CACHE_ATTR_NORMAL_WB; \
- break; \
- } \
- default: { \
- FATAL(); \
- } \
- }
-
- MAIR_ATTR_2_CACHE_ATTR(MVP_EXTRACT_FIELD(attr, 2, 2), attribMAN->innerCache);
- MAIR_ATTR_2_CACHE_ATTR(MVP_EXTRACT_FIELD(attr, 6, 2), attribMAN->outerCache);
-
-#undef MAIR_ATTR_2_CACHE_ATTR
-
- printk(KERN_INFO
- "DetermineMemAttr: innerCache %x outerCache %x share %x\n",
- attribMAN->innerCache,
- attribMAN->outerCache,
- attribMAN->share);
-
- free_pages(hkva, 0);
-}
-
-#else
-
-/**
- * @brief Determine host cacheability/shareability attributes.
- *
- * Used to ensure monitor/guest shared mappings are consistent with
- * those of host user/kernel.
- *
- * @param[out] attribL2D when setting up the LPV monitor a template L2D
- * containing cacheability attributes {S, TEX,CB} used by
- * host kernel for normal memory mappings. These may be
- * used directly for monitor/guest mappings, since both
- * worlds share a common {TRE, PRRR, NMRR}.
- * @param[out] attribMAN when setting up TTBR0 in the LPV monitor and the page
- * tables for the HW monitor this provides the attributes
- * in the generic ARM_MemAttrNormal form, suitable for
- * configuring TTBR0 + the monitor and guest's [H]MAIR0
- * and setting the shareability attributes of the LPAE
- * descriptors.
- */
-static void
-DetermineMemAttrNonLPAE(ARM_L2D *attribL2D, ARM_MemAttrNormal *attribMAN)
-{
- /*
- * We use set_pte_ext to sample what {S,TEX,CB} bits Linux is using for
- * normal kernel/user L2D mappings. These bits should be consistent both
- * with each other and what we use in the monitor since we share various
- * pages with both host processes, the kernel module and monitor, and the
- * ARM ARM requires that synonyms have the same cacheability attributes,
- * see end of A3.5.{4,7} ARM DDI 0406A.
- */
- HKVA hkva = __get_free_pages(GFP_KERNEL, 0);
- uint32 sctlr;
- ARM_L2D *pt = (ARM_L2D *)hkva;
- ARM_L2D *kernL2D = &pt[0], *userL2D = &pt[1];
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
- /*
- * Linux uses the magic 2048 offset in set_pte_ext. See include/asm/pgtable.h
- * for PAGE_NONE and PAGE_KERNEL semantics.
- */
- const uint32 set_pte_ext_offset = 2048;
-#else
- /*
- * Linux 2.6.38 switched the order of Linux vs hardware page tables.
- * See mainline d30e45eeabefadc6039d7f876a59e5f5f6cb11c6.
- */
- const uint32 set_pte_ext_offset = 0;
-#endif
-
- set_pte_ext((pte_t *)(kernL2D + set_pte_ext_offset/sizeof(ARM_L2D)),
- pfn_pte(0, PAGE_KERNEL),
- 0);
- set_pte_ext((pte_t *)(userL2D + set_pte_ext_offset/sizeof(ARM_L2D)),
- pfn_pte(0, PAGE_NONE),
- 0);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
- /*
- * Linux 2.6.38 switched the order of Linux vs hardware page tables.
- * See mainline d30e45eeabefadc6039d7f876a59e5f5f6cb11c6.
- */
- kernL2D += 2048/sizeof(ARM_L2D);
- userL2D += 2048/sizeof(ARM_L2D);
-#endif
-
- printk(KERN_INFO
- "DetermineMemAttr: Kernel L2D TEX=%x CB=%x S=%x\n",
- kernL2D->small.tex,
- kernL2D->small.cb,
- kernL2D->small.s);
-
- printk(KERN_INFO
- "DetermineMemAttr: User L2D TEX=%x CB=%x S=%x\n",
- userL2D->small.tex,
- userL2D->small.cb,
- userL2D->small.s);
-
- ASSERT((kernL2D->small.tex & 1) == (userL2D->small.tex & 1));
- ASSERT(kernL2D->small.cb == userL2D->small.cb);
- ASSERT(kernL2D->small.s == userL2D->small.s);
-
- *attribL2D = *kernL2D;
-
- /*
- * We now decode TEX remap and obtain the more generic form for use in
- * the LPV monitor's TTBR0 initialization and the HW monitor.
- */
-
- ARM_MRC_CP15(CONTROL_REGISTER, sctlr);
-
- if (sctlr & ARM_CP15_CNTL_TRE) {
- uint32 prrr, nmrr, indx, type, innerCache, outerCache, outerShare,
- share;
-
- printk(KERN_INFO
- "DetermineMemAttr: TEX remapping enabled\n");
-
- ARM_MRC_CP15(PRIMARY_REGION_REMAP, prrr);
- ARM_MRC_CP15(NORMAL_MEMORY_REMAP, nmrr);
-
- printk(KERN_INFO
- "DetermineMemAttr: PRRR=%x NMRR=%x\n",
- prrr,
- nmrr);
-
- /*
- * Decode PRRR/NMRR below. See B3.7 ARM DDI 0406B for register
- * encodings, tables and magic numbers.
- */
-
- indx = (MVP_BIT(kernL2D->small.tex, 0) << 2) | kernL2D->small.cb;
-
- /*
- * Only normal memory makes sense here.
- */
- type = MVP_EXTRACT_FIELD(prrr, 2 * indx, 2);
- ASSERT(type == 2);
-
- innerCache = MVP_EXTRACT_FIELD(nmrr, 2 * indx, 2);
- outerCache = MVP_EXTRACT_FIELD(nmrr, 16 + 2 * indx, 2);
- outerShare = !MVP_BIT(prrr, 24 + indx);
- share = MVP_BIT(prrr, 18 + kernL2D->small.s);
-
- printk(KERN_INFO
- "DetermineMemAttr: type %x innerCache %x outerCache %x"
- " share %x outerShare %x\n",
- type,
- innerCache,
- outerCache,
- share,
- outerShare);
-
- if (share) {
- if (outerShare) {
- attribMAN->share = ARM_SHARE_ATTR_OUTER;
- } else {
- attribMAN->share = ARM_SHARE_ATTR_INNER;
- }
- } else {
- attribMAN->share = ARM_SHARE_ATTR_NONE;
- }
-
- attribMAN->innerCache = innerCache;
- attribMAN->outerCache = outerCache;
- } else {
- NOT_IMPLEMENTED_JIRA(1849);
- }
-
- free_pages(hkva, 0);
-}
-#endif
-
-/**
- * @brief The ioctl file operation.
- *
- * The ioctl command is the main communication method between the
- * vmx and the mvpkm kernel module.
- *
- * @param filp which VM we're dealing with
- * @param cmd select which cmd function needs to be performed
- * @param arg argument for command
- * @return error code, 0 on success
- */
-long
-MvpkmUnlockedIoctl(struct file *filp,
- unsigned int cmd,
- unsigned long arg)
-{
- MvpkmVM *vm = filp->private_data;
- int retval = 0;
-
- switch (cmd) {
-
-
- case MVPKM_DISABLE_FAULT: {
- if (!vm->stubPageMPN) {
- uint32 *ptr;
-
- vm->stubPageMPN =
- AllocZeroedFreePages(vm, 0, false, MEMREGION_MAINMEM, (HKVA*)&ptr);
- if (!vm->stubPageMPN) {
- break;
- }
- ptr[0] = MVPKM_STUBPAGE_BEG;
- ptr[PAGE_SIZE/sizeof(uint32) - 1] = MVPKM_STUBPAGE_END;
- }
- break;
- }
-
- /*
- * Allocate some pinned pages from kernel.
- * Returns -ENOMEM if no host pages available for allocation.
- */
- case MVPKM_LOCK_MPN: {
- struct MvpkmLockMPN buf;
-
- if (copy_from_user(&buf, (void *)arg, sizeof buf)) {
- return -EFAULT;
- }
-
- buf.mpn = AllocZeroedFreePages(vm,
- buf.order,
- false,
- buf.forRegion,
- NULL);
- if (buf.mpn == 0) {
- return -ENOMEM;
- }
-
- if (copy_to_user((void *)arg, &buf, sizeof buf)) {
- return -EFAULT;
- }
- break;
- }
-
- case MVPKM_UNLOCK_MPN: {
- struct MvpkmLockMPN buf;
-
- if (copy_from_user(&buf, (void *)arg, sizeof buf)) {
- return -EFAULT;
- }
-
- if (!LockedListDel(vm, buf.mpn)) {
- return -EINVAL;
- }
- break;
- }
-
- case MVPKM_MAP_WSPHKVA: {
- MvpkmMapHKVA mvpkmMapInfo;
- HkvaMapInfo mapInfo[WSP_PAGE_COUNT];
-
- if (copy_from_user(&mvpkmMapInfo, (void *)arg, sizeof mvpkmMapInfo)) {
- return -EFAULT;
- }
-
- if (copy_from_user(mapInfo, (void *)mvpkmMapInfo.mapInfo, sizeof mapInfo)) {
- return -EFAULT;
- }
-
- mvpkmMapInfo.hkva = MapWSPHKVA(vm, mapInfo);
- BUG_ON(mvpkmMapInfo.hkva == 0);
-
- if (mvpkmMapInfo.forRegion == MEMREGION_WSP) {
- vm->wsp = (WorldSwitchPage *) mvpkmMapInfo.hkva;
- }
-
- if (copy_to_user((void *)arg, &mvpkmMapInfo, sizeof mvpkmMapInfo)) {
- return -EFAULT;
- }
- break;
- }
-
- case MVPKM_RUN_MONITOR: {
- if (!vm->isMonitorInited) {
- vm->isMonitorInited = ((retval = SetupMonitor(vm)) == 0);
- }
-
- if (vm->isMonitorInited) {
- retval = RunMonitor(vm);
- }
-
- break;
- }
-
- case MVPKM_ABORT_MONITOR: {
- if (!vm->isMonitorInited) {
- return -EINVAL;
- }
-
- ASSERT(vm->wsp != NULL);
-
- Mvpkm_WakeGuest(vm, ACTION_ABORT);
- break;
- }
-
- case MVPKM_CPU_INFO: {
- struct MvpkmCpuInfo buf;
- uint32 mpidr;
-
-#ifdef CONFIG_ARM_LPAE
- DetermineMemAttrLPAE(&buf.attribMAN);
- /**
- * We need to add support to the LPV monitor for LPAE page tables if we
- * want to use it on a LPAE host, due to the costs involved in
- * transitioning between LPAE and non-LPAE page tables without Hyp
- * assistance.
- *
- * @knownjira{MVP-2184}
- */
- buf.attribL2D.u = 0;
-#else
- DetermineMemAttrNonLPAE(&buf.attribL2D, &buf.attribMAN);
-#endif
- /*
- * Are MP extensions implemented? See B4-1618 ARM DDI 0406C-2c for
- * magic.
- */
- ARM_MRC_CP15(MPIDR, mpidr);
-
- buf.mpExt = mpidr & ARM_CP15_MPIDR_MP;
-
- if (copy_to_user((int *)arg, &buf, sizeof(struct MvpkmCpuInfo))) {
- retval = -EFAULT;
- }
- break;
- }
-
- default: {
- retval = -EINVAL;
- break;
- }
- }
-
- PRINTK(KERN_INFO "returning from IOCTL(%d) retval = %d %s\n",
- cmd, retval, signal_pending(current)?"(pending signal)":"" );
-
- return retval;
-}
-
-
-
-/*********************************************************************
- *
- * Locked page management
- *
- *********************************************************************/
-
-/*
- * Pages locked by the kernel module are remembered so an unlockAll
- * operation can be performed when the vmm is closed. The locked page
- * identifiers are stored in a red-black tree to support O(log n)
- * removal and search (required for /dev/mem-like mmap).
- */
-
-/**
- * @brief Descriptor of a locked page range
- */
-typedef struct {
- struct {
- __u32 mpn : 20; ///< MPN.
- __u32 order : 6; ///< Size/alignment exponent for page.
- __u32 forRegion : 6; ///< Annotation to identify guest page allocation
- } page;
- struct rb_node rb;
-} LockedPage;
-
-static void FreeLockedPages(LockedPage *lp);
-
-/**
- * @brief Search for an mpn inside a RB tree of LockedPages. The mpn
- * will match a LockedPage as long as it is covered by the
- * entry, i.e. in a non-zero order entry it doesn't have to be
- * the base MPN.
- *
- * This must be called with the relevant vm->lockedSem held.
- *
- * @param root RB tree root.
- * @param mpn MPN to search for.
- *
- * @return reference to LockedPage entry if found, otherwise NULL.
- */
-static LockedPage *
-LockedListSearch(struct rb_root *root, __u32 mpn)
-{
- struct rb_node *n = root->rb_node;
-
- while (n) {
- LockedPage *lp = rb_entry(n, LockedPage, rb);
-
- if (lp->page.mpn == (mpn & (~0UL << lp->page.order))) {
- return lp;
- }
-
- if (mpn < lp->page.mpn) {
- n = n->rb_left;
- } else {
- n = n->rb_right;
- }
- }
-
- return NULL;
-}
-
-/**
- * @brief Delete an mpn from the list of locked pages.
- *
- * @param vm Mvpkm module control structure pointer
- * @param mpn MPN to be unlocked and freed for reuse
- * @return true if list contained MPN and it was deleted from list
- */
-
-static _Bool
-LockedListDel(MvpkmVM *vm, __u32 mpn)
-{
- LockedPage *lp;
-
- down_write(&vm->lockedSem);
-
- lp = LockedListSearch(&vm->lockedRoot, mpn);
-
- /*
- * The MPN should be in the locked pages RB tree and it should be the
- * base of an entry, i.e. we can't fragment existing allocations for
- * a VM.
- */
- if (lp == NULL || lp->page.mpn != mpn) {
- up_write(&vm->lockedSem);
- return false;
- }
-
- FreeLockedPages(lp);
-
- if (lp->page.forRegion == MEMREGION_MAINMEM) {
- ATOMIC_SUBV(vm->usedPages, 1U << lp->page.order);
- }
-
- rb_erase(&lp->rb, &vm->lockedRoot);
- kfree(lp);
-
- up_write(&vm->lockedSem);
-
- return true;
-}
-
-/**
- * @brief Scan the list of locked pages to see if an MPN matches.
- *
- * @param vm Mvpkm module control structure pointer
- * @param mpn MPN to check
- *
- * @return true iff list contains MPN.
- */
-static _Bool
-LockedListLookup(MvpkmVM *vm, __u32 mpn)
-{
- LockedPage *lp;
-
- down_read(&vm->lockedSem);
-
- lp = LockedListSearch(&vm->lockedRoot, mpn);
-
- up_read(&vm->lockedSem);
-
- return lp != NULL;
-}
-
-/**
- * @brief Add a new mpn to the locked pages RB tree.
- *
- * @param vm control structure pointer
- *
- * @param mpn mpn of page that was locked with get_user_pages or some sort of
- * get that is undone by put_page.
- * The mpn is assumed to be non-zero
- * @param order size/alignment exponent for page
- * @param forRegion Annotation for Page pool to identify guest page allocations
- *
- * @return false: couldn't allocate internal memory to record mpn in<br>
- * true: successful.
- */
-static _Bool
-LockedListAdd(MvpkmVM *vm,
- __u32 mpn,
- __u32 order,
- PhysMem_RegionType forRegion)
-{
- struct rb_node *parent, **p;
- LockedPage *tp, *lp = kmalloc(sizeof *lp, GFP_KERNEL);
-
- if (!lp) {
- return false;
- }
-
- lp->page.mpn = mpn;
- lp->page.order = order;
- lp->page.forRegion = forRegion;
-
- down_write(&vm->lockedSem);
-
- if (forRegion == MEMREGION_MAINMEM) {
- ATOMIC_ADDV(vm->usedPages, 1U << order);
- }
-
- /*
- * Insert as a red leaf in the tree (see include/linux/rbtree.h).
- */
- p = &vm->lockedRoot.rb_node;
- parent = NULL;
-
- while (*p) {
- parent = *p;
- tp = rb_entry(parent, LockedPage, rb);
-
- /*
- * MPN should not already exist in the tree.
- */
- ASSERT(tp->page.mpn != (mpn & (~0UL << tp->page.order)));
-
- if (mpn < tp->page.mpn) {
- p = &(*p)->rb_left;
- } else {
- p = &(*p)->rb_right;
- }
- }
-
- rb_link_node(&lp->rb, parent, p);
-
- /*
- * Restructure tree if necessary (see include/linux/rbtree.h).
- */
- rb_insert_color(&lp->rb, &vm->lockedRoot);
-
- up_write(&vm->lockedSem);
-
- return true;
-}
-
-/**
- * @brief Traverse RB locked tree, freeing every entry.
- *
- * This must be called with the relevant vm->lockedSem held.
- *
- * @param node reference to RB node at root of subtree.
- */
-static void
-LockedListNuke(struct rb_node *node)
-{
- while (node) {
- if (node->rb_left) {
- node = node->rb_left;
- } else if (node->rb_right) {
- node = node->rb_right;
- } else {
- /*
- * We found a leaf, free it and go back to parent.
- */
- LockedPage *lp = rb_entry(node, LockedPage, rb);
-
- if ((node = rb_parent(node))) {
- if (node->rb_left) {
- node->rb_left = NULL;
- } else {
- node->rb_right = NULL;
- }
- }
-
- FreeLockedPages(lp);
- kfree(lp);
- }
- }
-}
-
-/**
- * @brief Unlock all pages at vm close time.
- *
- * @param vm control structure pointer
- */
-static void
-LockedListUnlockAll(MvpkmVM *vm)
-{
-
- down_write(&vm->lockedSem);
-
- LockedListNuke(vm->lockedRoot.rb_node);
-
- ATOMIC_SETV(vm->usedPages, 0);
-
- up_write(&vm->lockedSem);
-}
-
-
-/**
- * @brief Allocate zeroed free pages
- *
- * @param[in] vm which VM the pages are for so they will be freed when the vm
- * closes
- * @param[in] order log2(number of contiguous pages to allocate)
- * @param[in] highmem is it OK to allocate this page in ZONE_HIGHMEM? This
- * option should only be specified for pages the host kernel
- * will not need to address directly.
- * @param[out] hkvaRet where to return host kernel virtual address of the
- * allocated pages, if non-NULL, and ONLY IF !highmem.
- * @param forRegion Annotation for Page pool to identify guest page allocations
- * @return 0: no host memory available<br>
- * else: starting MPN<br>
- * *hkvaRet = filled in
- */
-static MPN
-AllocZeroedFreePages(MvpkmVM *vm,
- uint32 order,
- _Bool highmem,
- PhysMem_RegionType forRegion,
- HKVA *hkvaRet)
-{
- MPN mpn;
- struct page *page;
-
- if (order > PAGE_ALLOC_COSTLY_ORDER) {
- printk(KERN_WARNING "Order %d allocation for region %d exceeds the safe "
- "maximum order %d\n",
- order,
- forRegion,
- PAGE_ALLOC_COSTLY_ORDER);
- }
-
- /*
- * Get some pages for the requested range. They will be physically
- * contiguous and have the requested alignment. They will also
- * have a kernel virtual mapping if !highmem.
- *
- * We allocate out of ZONE_MOVABLE even though we can't just pick up our
- * bags. We do this to support platforms that explicitly configure
- * ZONE_MOVABLE, such as the Qualcomm MSM8960, to enable deep power down of
- * memory banks. When the kernel attempts to take a memory bank offline, it
- * will try and place the pages on the isolate LRU - only pages already on an
- * LRU, such as anon/file, can get there, so it will not be able to
- * migrate/move our pages (and hence the bank will not be offlined). The
- * other alternative is to live withing ZONE_NORMAL, and only have available
- * a small fraction of system memory. Long term we plan on hooking the
- * offlining callback in mvpkm and perform our own migration with the
- * cooperation of the monitor, but we don't have dev board to support this
- * today.
- *
- * @knownjira{MVP-3477}
- */
- page = alloc_pages(GFP_USER | __GFP_COMP | __GFP_ZERO |
- (highmem ? __GFP_HIGHMEM | __GFP_MOVABLE : 0),
- order);
-
- if (page == NULL) {
- return 0;
- }
-
- /*
- * Return the corresponding page number.
- */
- mpn = page_to_pfn(page);
- ASSERT(mpn != 0);
-
- /*
- * Remember to unlock the pages when the FD is closed.
- */
- if (!LockedListAdd(vm, mpn, order, forRegion)) {
- __free_pages(page, order);
- return 0;
- }
-
- if (hkvaRet) {
- *hkvaRet = highmem ? 0 : __phys_to_virt(page_to_phys(page));
- }
-
- return mpn;
-}
-
-/**
- * @brief Map already-pinned WSP memory in host kernel virtual address(HKVA)
- * space. Assumes 2 world switch pages on an 8k boundary.
- *
- * @param[in] vm which VM the HKVA Area is to be mapped for
- * @param[in] mapInfo array of MPNs and execute permission flags to be used in
- inserting a new contiguous map in HKVA space
- * @return 0: HKVA space could not be mapped
- else: HKVA where mapping was inserted
- */
-static HKVA
-MapWSPHKVA(MvpkmVM *vm, HkvaMapInfo *mapInfo)
-{
- unsigned int i;
- struct page **pages = NULL;
- struct page **pagesPtr;
- pgprot_t prot;
- int retval;
- int allocateCount = WSP_PAGE_COUNT + 1; // Reserve one page for alignment
- int pageIndex = 0;
- HKVA dummyPage = (HKVA)NULL;
- HKVA start;
- HKVA startSegment;
- HKVA endSegment;
-
- /*
- * Add one page for alignment purposes in case __get_vm_area returns an
- * unaligned address.
- */
- ASSERT(allocateCount == 3);
- ASSERT_ON_COMPILE(WSP_PAGE_COUNT == 2);
-
- /*
- * NOT_IMPLEMENTED if MapHKVA is called more than once.
- */
- BUG_ON(vm->wspHkvaArea);
-
- /*
- * Reserve virtual address space.
- */
- vm->wspHkvaArea = __get_vm_area((allocateCount * PAGE_SIZE), VM_ALLOC, MODULES_VADDR, MODULES_END);
- if (!vm->wspHkvaArea) {
- return 0;
- }
-
- pages = kmalloc(allocateCount * sizeof(struct page *), GFP_TEMPORARY);
- if (!pages) {
- goto err;
- }
- pagesPtr = pages;
-
- /*
- * Use a dummy page to boundary align the section, if needed.
- */
- dummyPage = __get_free_pages(GFP_KERNEL, 0);
- if (!dummyPage) {
- goto err;
- }
- vm->wspHKVADummyPage = dummyPage;
-
- /*
- * Back every entry with the dummy page.
- */
- for (i = 0; i < allocateCount; i++) {
- pages[i] = virt_to_page(dummyPage);
- }
-
- /*
- * World switch pages must not span a 1MB boundary in order to maintain only
- * a single L2 page table.
- */
- start = (HKVA)vm->wspHkvaArea->addr;
- startSegment = start & ~(ARM_L1D_SECTION_SIZE - 1);
- endSegment = (start + PAGE_SIZE) & ~(ARM_L1D_SECTION_SIZE - 1);
- /*
- * Insert dummy page at pageIndex, if needed.
- */
- pageIndex = (startSegment != endSegment);
-
- /*
- * Back the rest with the actual world switch pages
- */
- for (i = pageIndex; i < pageIndex + WSP_PAGE_COUNT; i++) {
- pages[i] = pfn_to_page(mapInfo[i - pageIndex].mpn);
- }
-
- /*
- * Given the lack of functionality in the kernel for being able to mark
- * mappings for a given vm area with different sets of protection bits,
- * we simply mark the entire vm area as PAGE_KERNEL_EXEC for now
- * (i.e., union of all the protection bits). Given that the kernel
- * itself does something similar while loading modules, this should be a
- * reasonable workaround for now. In the future, we should set the
- * protection bits to strictly adhere to what has been requested in the
- * mapInfo parameter.
- */
- prot = PAGE_KERNEL_EXEC;
-
- retval = map_vm_area(vm->wspHkvaArea, prot, &pagesPtr);
- if (retval < 0) {
- goto err;
- }
-
- kfree(pages);
-
- return (HKVA)(vm->wspHkvaArea->addr) + pageIndex * PAGE_SIZE;
-
-err:
- if (dummyPage) {
- free_pages(dummyPage, 0);
- vm->wspHKVADummyPage = (HKVA)NULL;
- }
-
- if (pages) {
- kfree(pages);
- }
-
- free_vm_area(vm->wspHkvaArea);
- vm->wspHkvaArea = (HKVA)NULL;
-
- return 0;
-}
-
-static void
-UnmapWSPHKVA(MvpkmVM *vm)
-{
- if (vm->wspHkvaArea) {
- free_vm_area(vm->wspHkvaArea);
- }
-
- if (vm->wspHKVADummyPage) {
- free_pages(vm->wspHKVADummyPage, 0);
- vm->wspHKVADummyPage = (HKVA)NULL;
- }
-}
-
-/**
- * @brief Clean and release locked pages
- *
- * @param lp Reference to the locked pages
- */
-static void
-FreeLockedPages(LockedPage *lp)
-{
- struct page *page;
- int count;
-
- page = pfn_to_page(lp->page.mpn);
- count = page_count(page);
-
- if (count == 0) {
- printk(KERN_ERR "%s: found locked page with 0 reference (mpn %05x)\n",
- __func__, lp->page.mpn);
- return;
- }
-
- if (count == 1) {
- int i;
-
- /*
- * There is no other user for this page, clean it.
- *
- * We don't bother checking if the page was highmem or not, clear_highmem
- * works for both.
- * We clear the content of the page, and rely on the fact that the previous
- * worldswitch has cleaned the potential VIVT I-CACHE.
- */
- for (i = 0; i < (1 << lp->page.order); i++) {
- clear_highpage(page + i);
- }
- } else if (lp->page.forRegion != MEMREGION_MAINMEM) {
- printk(KERN_WARNING "%s: mpn 0x%05x for region %d is still in use\n",
- __func__, lp->page.mpn, lp->page.forRegion);
- }
-
- __free_pages(page, lp->page.order);
-}
-
-/*********************************************************************
- *
- * Communicate with monitor
- *
- *********************************************************************/
-
-/**
- * @brief Register a new monitor page.
- *
- * @param vm which virtual machine we're running
- * @return 0: successful<br>
- * else: -errno
- */
-static int
-SetupMonitor(MvpkmVM *vm)
-{
- int retval;
- WorldSwitchPage *wsp = vm->wsp;
-
- if (!wsp ||
- wsp->wspHKVA != (HKVA)wsp) {
- return -EINVAL;
- }
-
- if ((retval = Mksck_WspInitialize(vm))) {
- return retval;
- }
-
- vm->kobj.kset = mvpkmKSet;
- retval = kobject_init_and_add(&vm->kobj, &mvpkmKType, NULL, "%d", wsp->guestId);
- if (retval) {
- goto error;
- }
-
- /*
- * Get a reference to this module such that it cannot be unloaded until
- * our kobject's release function completes.
- */
-
- __module_get(THIS_MODULE);
- vm->haveKObj = true;
-
- /*
- * Caution: From here on, if we fail, we must not call kobject_put()
- * on vm->kobj since that may / will deallocate 'vm'. Unregistering VM
- * ksets on failures, is fine and should be done for proper ref counting.
- */
-
- vm->devicesKSet = kset_create_and_add("devices", NULL, &vm->kobj);
- if (!vm->devicesKSet) {
- retval = -ENOMEM;
- goto error;
- }
-
- vm->miscKSet = kset_create_and_add("misc", NULL, &vm->kobj);
- if (!vm->miscKSet) {
- kset_unregister(vm->devicesKSet);
- vm->devicesKSet = NULL;
- retval = -ENOMEM;
- goto error;
- }
-
- down_write(&vm->wspSem);
-
- /*
- * The VE monitor needs to issue a SMC to bootstrap Hyp mode.
- */
- if (wsp->monType == MONITOR_TYPE_VE) {
- /*
- * Here we assemble the monitor's HMAIR0 based on wsp->memAttr. We map
- * from the inner/outer normal page cacheability attributes obtained
- * from DetermineCacheabilityAttribs to the format required in 4.2.8
- * ARM PRD03-GENC-008469 13.0 (see this document for the magic numbers).
- *
- * Where a choice is available, we opt for read and/or write allocation.
- */
- static const uint32 normalCacheAttr2MAIR[4] = { 0x4, 0xf, 0xa, 0xe };
-
- uint32 hmair0 =
- ((normalCacheAttr2MAIR[wsp->memAttr.innerCache] |
- (normalCacheAttr2MAIR[wsp->memAttr.outerCache] << 4))
- << 8 * MVA_MEMORY) |
- (0x4 << 8 * MVA_DEVICE);
-
- /*
- * See B4.1.74 ARM DDI 0406C-2c for the HTCR magic.
- */
- uint32 htcr =
- 0x80000000 |
- (wsp->memAttr.innerCache << 8) |
- (wsp->memAttr.outerCache << 10) |
- (wsp->memAttr.share << 12);
-
- /**
- * @knownjira{MVP-377}
- * Set HSCTLR to enable MMU and caches. We should really run the
- * monitor WXN, in non-MVP_DEVEL builds. See
- * 13.18 ARM PRD03-GENC-008353 11.0 for the magic.
- */
- static const uint32 hsctlr = 0x30c5187d;
-
- register uint32 r0 asm("r0") = wsp->monVA.excVec;
- register uint32 r1 asm("r1") = wsp->regSave.ve.mHTTBR;
- register uint32 r2 asm("r2") = htcr;
- register uint32 r3 asm("r3") = hmair0;
- register uint32 r4 asm("r4") = hsctlr;
-
- asm volatile (
- ".arch_extension sec\n"
- "smc 0"
- :
- : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4)
- : "memory"
- );
- }
-
- /*
- * Initialize guest wait-for-interrupt waitqueue.
- */
- init_waitqueue_head(&vm->wfiWaitQ);
-
- MonitorTimer_Setup(vm);
-
-#ifdef CONFIG_HAS_WAKELOCK
- wake_lock_init(&vm->wakeLock, WAKE_LOCK_SUSPEND, "mvpkm");
-#endif
-
- wsp->mvpkmVersion = MVP_VERSION_CODE;
- up_write(&vm->wspSem);
- /*
- * Ensure coherence of monitor loading and page tables.
- */
- flush_cache_all();
- return 0;
-
-error:
- Mksck_WspRelease(wsp);
- vm->wsp = NULL;
- return retval;
-}
-
-/**
- * @brief dummy function to drop the info parameter
- * @param info ignored
- */
-static
-void FlushAllCpuCaches(void *info)
-{
- flush_cache_all();
-}
-
-/**
- * @brief return to where monitor called worldswitch
- *
- * @param vm which virtual machine we're running
- * @return 0: successful, just call back when ready<br>
- * 1: successful, process code in WSP_Params(wsp)->callno<br>
- * else: -errno
- */
-static int
-RunMonitor(MvpkmVM *vm)
-{
- int ii;
- unsigned long flags;
- WorldSwitchPage *wsp = vm->wsp;
- int retval = 0;
-
- ASSERT(wsp);
-
-#ifdef CONFIG_HAS_WAKELOCK
- wake_lock(&vm->wakeLock);
-#endif
-
- /*
- * Set VCPUThread affinity
- */
- if (cpumask_intersects(to_cpumask(vcpuAffinity), cpu_active_mask)) {
- set_cpus_allowed_ptr(current, to_cpumask(vcpuAffinity));
- }
-
- /*
- * Record the the current task structure, so an ABORT will know,
- * who to wake.
- */
- down_write(&vm->monThreadTaskSem);
- vm->monThreadTask = get_current();
- up_write(&vm->monThreadTaskSem);
-
- /*
- * Keep going as long as the monitor is in critical section or
- * there are no pending signals such as SIGINT or SIGKILL. Block
- * interrupts before checking so any IPI sent will remain pending
- * if our check just misses detecting the signal.
- */
- local_irq_save(flags);
- while (wsp->critSecCount > 0 ||
- (!signal_pending(current) &&
- !(ATOMIC_GETO(wsp->hostActions) & ACTION_ABORT))) {
- /*
- * ARMv7 Performance counters are per CPU core and might be disabled over
- * CPU core sleep if there is nothing else in the system to re-enable
- * them, so now that we have been allocated a CPU core to run the guest,
- * enable them and in particular the TSC (CCNT) which is used for monitor
- * timing between world switches.
- */
- {
- uint32 pmnc;
- uint32 pmcnt;
-
- /* make sure that the Performance Counters are enabled */
- ARM_MRC_CP15(PERF_MON_CONTROL_REGISTER, pmnc);
- if ((pmnc & (ARM_PMNC_E | ARM_PMNC_D)) != (ARM_PMNC_E)) {
- pmnc |= ARM_PMNC_E; // Enable TSC
- pmnc &= ~ARM_PMNC_D; // Disable cycle count divider
- ARM_MCR_CP15(PERF_MON_CONTROL_REGISTER, pmnc);
- }
-
- /* make sure that the CCNT is enabled */
- ARM_MRC_CP15(PERF_MON_COUNT_SET, pmcnt);
- if ((pmcnt & ARM_PMCNT_C) != ARM_PMCNT_C) {
- pmcnt |= ARM_PMCNT_C;
- ARM_MCR_CP15(PERF_MON_COUNT_SET, pmcnt);
- }
- }
-
- /*
- * Update TSC to RATE64 ratio
- */
- {
- struct TscToRate64Cb *ttr = &__get_cpu_var(tscToRate64);
- wsp->tscToRate64Mult = ttr->mult;
- wsp->tscToRate64Shift = ttr->shift;
- }
-
- /*
- * Save the time of day for the monitor's timer facility. The timing
- * facility in the vmm needs to compute current time in the host linux's
- * time representation. It uses the formula:
- * now = wsp->switchedAt64 + (uint32)(TSC_READ() - wsp->lowerTSC)
- *
- * Read the timestamp counter *immediately after* ktime_get() as that
- * will give the most consistent offset between reading the hardware
- * clock register in ktime_get() and reading the hardware timestamp
- * counter with TSC_READ().
- */
- ASSERT_ON_COMPILE(MVP_TIMER_RATE64 == NSEC_PER_SEC);
- {
- ktime_t now = ktime_get();
- TSC_READ(wsp->switchedAtTSC);
- wsp->switchedAt64 = ktime_to_ns(now);
- }
-
- /*
- * Save host FPU contents and load monitor contents.
- */
- SWITCH_VFP_TO_MONITOR;
-
- /*
- * Call into the monitor to run guest instructions until it wants us to
- * do something for it. Note that any hardware interrupt request will
- * cause it to volunteer.
- */
- switch (wsp->monType) {
- case MONITOR_TYPE_LPV: {
- uint32 hostVBAR;
-
- ARM_MRC_CP15(VECTOR_BASE, hostVBAR);
- (*wsp->switchToMonitor)(&wsp->regSave);
- ARM_MCR_CP15(VECTOR_BASE, hostVBAR);
- break;
- }
- case MONITOR_TYPE_VE: {
- register uint32 r1 asm("r1") = wsp->regSave.ve.mHTTBR;
-
- asm volatile (
- ".word " MVP_STRINGIFY(ARM_INSTR_HVC_A1_ENC(0))
- : "=r" (r1) : "r" (r1) : "r0", "r2", "memory"
- );
- break;
- }
- default: FATAL();
- }
-
- /*
- * Save monitor FPU contents and load host contents.
- */
- SWITCH_VFP_TO_HOST;
-
- /*
- * Re-enable local interrupts now that we are back in the host world
- */
- local_irq_restore(flags);
-
-
- /*
- * Maybe the monitor wrote some messages to monitor->host sockets.
- * This will wake the corresponding host threads to receive them.
- */
- /**
- * @todo This lousy loop is in the critical path. It should be changed
- * to some faster algorithm to wake blocked host sockets.
- */
- for (ii = 0; ii < MKSCK_MAX_SHARES; ii++) {
- if (wsp->isPageMapped[ii]) {
- Mksck_WakeBlockedSockets(MksckPage_GetFromIdx(ii));
- }
- }
-
- switch (WSP_Params(wsp)->callno) {
- case WSCALL_ACQUIRE_PAGE: {
- uint32 i;
-
- for (i = 0; i < WSP_Params(wsp)->pages.pages; ++i) {
- MPN mpn = AllocZeroedFreePages(vm,
- WSP_Params(wsp)->pages.order,
- true,
- WSP_Params(wsp)->pages.forRegion,
- NULL);
- if (mpn == 0) {
- printk(KERN_WARNING "WSCALL_ACQUIRE_PAGE: no order %u pages available\n",
- WSP_Params(wsp)->pages.order);
- WSP_Params(wsp)->pages.pages = i;
- break;
- }
-
- WSP_Params(wsp)->pages.mpns[i] = mpn;
- }
-
- break;
- }
- case WSCALL_RELEASE_PAGE: {
- uint32 i;
-
- for (i = 0; i < WSP_Params(wsp)->pages.pages; ++i) {
- if (!LockedListDel(vm, WSP_Params(wsp)->pages.mpns[i])) {
- WSP_Params(wsp)->pages.pages = i;
- break;
- }
- }
-
- break;
- }
- case WSCALL_MUTEXLOCK: {
- retval = Mutex_Lock((void *)WSP_Params(wsp)->mutex.mtxHKVA,
- WSP_Params(wsp)->mutex.mode);
-
- if (retval < 0) {
- WSP_Params(wsp)->mutex.ok = false;
- goto monitorExit;
- }
-
- /*
- * The locking succeeded. From this point on the monitor
- * is in critical section. Even if an interrupt comes
- * right here, it must return to the monitor to unlock the
- * mutex.
- */
- wsp->critSecCount++;
- WSP_Params(wsp)->mutex.ok = true;
- break;
- }
- case WSCALL_MUTEXUNLOCK: {
- Mutex_Unlock((void *)WSP_Params(wsp)->mutex.mtxHKVA,
- WSP_Params(wsp)->mutex.mode);
- break;
- }
- case WSCALL_MUTEXUNLSLEEP: {
- /*
- * The vcpu has just come back from the monitor. During
- * the transition interrupts were disabled. Above,
- * however, interrupts were enabled again and it is
- * possible that a context switch happened into a thread
- * (serve_vmx) that instructed the vcpu thread to
- * abort. After returning to this thread the vcpu may
- * enter a sleep below never to return from it. To avoid
- * this deadlock we need to test the abort flag in
- * Mutex_UnlSleepTest.
- */
- retval =
- Mutex_UnlSleepTest((void *)WSP_Params(wsp)->mutex.mtxHKVA,
- WSP_Params(wsp)->mutex.mode,
- WSP_Params(wsp)->mutex.cvi,
- &wsp->hostActions,
- ACTION_ABORT);
- if (retval < 0) {
- goto monitorExit;
- }
- break;
- }
- case WSCALL_MUTEXUNLWAKE: {
- Mutex_UnlWake((void *)WSP_Params(wsp)->mutex.mtxHKVA,
- WSP_Params(wsp)->mutex.mode,
- WSP_Params(wsp)->mutex.cvi,
- WSP_Params(wsp)->mutex.all);
- break;
- }
-
- /*
- * The monitor wants us to block (allowing other host threads to run)
- * until an async message is waiting for the monitor to process.
- *
- * If MvpkmWaitForInt() returns an error, it should only be if there
- * is another signal pending (such as SIGINT). So we pretend it
- * completed normally, as the monitor is ready to be called again (it
- * will see no messages to process and wait again), and return to user
- * mode so the signals can be processed.
- */
- case WSCALL_WAIT: {
-#ifdef CONFIG_HAS_WAKELOCK
- if (WSP_Params(wsp)->wait.suspendMode) {
- /* guest has ok'ed suspend mode, so release SUSPEND wakelock */
- wake_unlock(&vm->wakeLock);
- retval = MvpkmWaitForInt(vm, true);
- wake_lock(&vm->wakeLock);
- WSP_Params(wsp)->wait.suspendMode = 0;
- } else {
- /* guest has asked for WFI not suspend so keep holding SUSPEND
- * wakelock */
- retval = MvpkmWaitForInt(vm, false);
- }
-#else
- retval = MvpkmWaitForInt(vm, WSP_Params(wsp)->wait.suspendMode);
-#endif
- if (retval < 0) {
- goto monitorExit;
- }
- break;
- }
-
- /*
- * The only reason the monitor returned was because there was a
- * pending hardware interrupt. The host serviced and cleared that
- * interrupt when we enabled interrupts above. Now we call the
- * scheduler in case that interrupt woke another thread, we want to
- * allow that thread to run before returning to do more guest code.
- */
- case WSCALL_IRQ: {
- break;
- }
-
- case WSCALL_GET_PAGE_FROM_VMID: {
- MksckPage *mksckPage;
- mksckPage = MksckPage_GetFromVmIdIncRefc(WSP_Params(wsp)->pageMgmnt.vmId);
-
- if (mksckPage) {
- int ii;
-
- WSP_Params(wsp)->pageMgmnt.found = true;
- for (ii = 0; ii < MKSCKPAGE_TOTAL; ii++) {
- WSP_Params(wsp)->pageMgmnt.mpn[ii] =
- vmalloc_to_pfn( (void*)(((HKVA)mksckPage) + ii*PAGE_SIZE) );
- }
-
- ASSERT(!wsp->isPageMapped[MKSCK_VMID2IDX(mksckPage->vmId)]);
- wsp->isPageMapped[MKSCK_VMID2IDX(mksckPage->vmId)] = true;
- } else {
- WSP_Params(wsp)->pageMgmnt.found = false;
- }
- break;
- }
-
- case WSCALL_REMOVE_PAGE_FROM_VMID: {
- MksckPage *mksckPage;
- mksckPage = MksckPage_GetFromVmId(WSP_Params(wsp)->pageMgmnt.vmId);
- ASSERT(wsp->isPageMapped[MKSCK_VMID2IDX(mksckPage->vmId)]);
- wsp->isPageMapped[MKSCK_VMID2IDX(mksckPage->vmId)] = false;
- MksckPage_DecRefc(mksckPage);
- break;
- }
-
- /*
- * Read current wallclock time.
- */
- case WSCALL_READTOD: {
- struct timeval nowTV;
- do_gettimeofday(&nowTV);
- WSP_Params(wsp)->tod.now = nowTV.tv_sec;
- WSP_Params(wsp)->tod.nowusec = nowTV.tv_usec;
- break;
- }
-
- case WSCALL_LOG: {
- int len = strlen(WSP_Params(wsp)->log.messg);
- printk(KERN_INFO
- "VMM: %s%s",
- WSP_Params(wsp)->log.messg,
- (WSP_Params(wsp)->log.messg[len-1] == '\n') ? "" : "\n");
- break;
- }
-
- case WSCALL_ABORT: {
- retval = WSP_Params(wsp)->abort.status;
- goto monitorExit;
- }
-
- case WSCALL_QP_GUEST_ATTACH: {
- int32 rc;
- QPInitArgs args;
- uint32 base;
- uint32 nrPages;
-
- args.id = WSP_Params(wsp)->qp.id;
- args.capacity = WSP_Params(wsp)->qp.capacity;
- args.type = WSP_Params(wsp)->qp.type;
- base = WSP_Params(wsp)->qp.base;
- nrPages = WSP_Params(wsp)->qp.nrPages;
-
- rc = QP_GuestAttachRequest(vm, &args, base, nrPages);
-
- WSP_Params(wsp)->qp.rc = rc;
- WSP_Params(wsp)->qp.id = args.id;
- break;
- }
-
- case WSCALL_QP_NOTIFY: {
- QPInitArgs args;
-
- args.id = WSP_Params(wsp)->qp.id;
- args.capacity = WSP_Params(wsp)->qp.capacity;
- args.type = WSP_Params(wsp)->qp.type;
-
- WSP_Params(wsp)->qp.rc = QP_NotifyListener(&args);
- break;
- }
-
- case WSCALL_MONITOR_TIMER: {
- MonitorTimer_Request(&vm->monTimer, WSP_Params(wsp)->timer.when64);
- break;
- }
-
- case WSCALL_COMM_SIGNAL: {
- Mvpkm_CommEvSignal(&WSP_Params(wsp)->commEvent.transpID,
- WSP_Params(wsp)->commEvent.event);
- break;
- }
-
- case WSCALL_FLUSH_ALL_DCACHES: {
- /*
- * Broadcast Flush DCache request to all cores.
- * Block while waiting for all of them to get done.
- */
- on_each_cpu(FlushAllCpuCaches, NULL, 1);
- break;
- }
- default: {
- retval = -EPIPE;
- goto monitorExit;
- }
- }
-
- /*
- * The params.callno callback was handled in kernel mode and completed
- * successfully. Repeat for another call without returning to user mode,
- * unless there are signals pending.
- *
- * But first, call the Linux scheduler to switch threads if there is
- * some other thread Linux wants to run now.
- */
- if (need_resched()) {
- schedule();
- }
-
- /*
- * Check if cpus allowed mask has to be updated.
- * Updating it must be done outside of an atomic context.
- */
- if (cpumask_intersects(to_cpumask(vcpuAffinity), cpu_active_mask) &&
- !cpumask_equal(to_cpumask(vcpuAffinity), &current->cpus_allowed)) {
- set_cpus_allowed_ptr(current, to_cpumask(vcpuAffinity));
- }
-
- local_irq_save(flags);
- }
-
- /*
- * There are signals pending so don't try to do any more monitor/guest
- * stuff. But since we were at the point of just about to run the monitor,
- * return success status as user mode can simply call us back to run the
- * monitor again.
- */
- local_irq_restore(flags);
-
-monitorExit:
- ASSERT(wsp->critSecCount == 0);
-
- if (ATOMIC_GETO(wsp->hostActions) & ACTION_ABORT) {
- PRINTK(KERN_INFO "Monitor has ABORT flag set.\n");
- retval = ExitStatusHostRequest;
- }
-
-#ifdef CONFIG_HAS_WAKELOCK
- wake_unlock(&vm->wakeLock);
-#endif
-
- down_write(&vm->monThreadTaskSem);
- vm->monThreadTask = NULL;
- up_write(&vm->monThreadTaskSem);
-
- return retval;
-}
-
-/**
- * @brief Guest is waiting for interrupts, sleep if necessary
- *
- * @param vm which virtual machine we're running
- * @param suspend is the guest entering suspend or just WFI?
- * @return 0: woken up, hostActions should have pending events
- * -ERESTARTSYS: broke out because other signals are pending
- *
- * This function is called in the VCPU context after the world switch to wait
- * for an incoming message. If any message gets queued to this VCPU, the
- * sender will wake us up.
- */
-int
-MvpkmWaitForInt(MvpkmVM *vm, _Bool suspend)
-{
- WorldSwitchPage *wsp = vm->wsp;
- wait_queue_head_t *q = &vm->wfiWaitQ;
-
- if (suspend) {
- return wait_event_interruptible(*q, ATOMIC_GETO(wsp->hostActions) != 0);
- } else {
- int ret;
- ret = wait_event_interruptible_timeout(*q, ATOMIC_GETO(wsp->hostActions) != 0, 10*HZ);
- if (ret == 0) {
- printk("MvpkmWaitForInt: guest stuck for 10s in WFI! (hostActions %08x)\n",
- ATOMIC_GETO(wsp->hostActions));
- }
- return ret > 0 ? 0 : ret;
- }
-}
-
-
-/**
- * @brief Force the guest to evaluate its hostActions flag field
- *
- * @param vm which guest needs waking
- * @param why why should be guest be woken up?
- *
- * This function updates the hostAction flag field as and wakes up the guest as
- * required so that it can evaluate it. The guest could be executing guest
- * code in an SMP system, in that case send an IPI; or it could be sleeping, in
- * the case wake it up.
- */
-void
-Mvpkm_WakeGuest(MvpkmVM *vm, int why)
-{
- ASSERT(why != 0);
-
- /* set the host action */
- if (ATOMIC_ORO(vm->wsp->hostActions, why) & why) {
- /* guest has already been woken up so no need to do it again */
- return;
- }
-
- /*
- * VCPU is certainly in 'wait for interrupt' wait. Wake it up !
- */
-#ifdef CONFIG_HAS_WAKELOCK
- /*
- * To prevent the system to go in suspend mode before the monitor had a
- * chance on being scheduled, we will hold the VM wakelock from now.
- * As the wakelocks are not managed as reference counts, this is not an
- * an issue to take a wake_lock twice in a row.
- */
- wake_lock(&vm->wakeLock);
-#endif
-
- /*
- * On a UP system, we ensure the monitor thread isn't blocked.
- *
- * On an MP system the other CPU might be running the guest. This
- * is noop on UP.
- *
- * When the guest is running, it is an invariant that monThreadTaskSem is not
- * held as a write lock, so we should not fail to acquire the lock.
- * Mvpkm_WakeGuest may be called from an atomic context, so we can't sleep
- * here.
- */
- if (down_read_trylock(&vm->monThreadTaskSem)) {
- if (vm->monThreadTask) {
- wake_up_process(vm->monThreadTask);
- kick_process(vm->monThreadTask);
- }
- up_read(&vm->monThreadTaskSem);
- } else {
- printk("Unexpected failure to acquire monThreadTaskSem!\n");
- }
-}
diff --git a/arch/arm/mvp/mvpkm/mvpkm_private.h b/arch/arm/mvp/mvpkm/mvpkm_private.h
deleted file mode 100644
index 3dfc8d4..0000000
--- a/arch/arm/mvp/mvpkm/mvpkm_private.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Private interface between user level wrappers and kernel module.
- * The communication uses the ioctl linux call. The command operand is one
- * of the MVPKM_xxx macros defined below, the custom operand is a pointer
- * to the respective structure below.
- */
-
-
-#ifndef _MVPKMPRIVATE_H
-#define _MVPKMPRIVATE_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include <linux/ioctl.h>
-/*
- * For details how to create ioctl numbers, see
- * Documentation/ioctl/ioctl-number.txt. The letter '9' is
- * unused. The 0xa0-0xaf block is even more unused. Note however, that
- * ioctl numbers are desired to be unique for debug purposes, they
- * may conflict.
- */
-#define MVP_IOCTL_LETTER '9'
-#define MVPKM_DISABLE_FAULT _IO( MVP_IOCTL_LETTER, 0xa0)
-#define MVPKM_LOCK_MPN _IOW(MVP_IOCTL_LETTER, 0xa1, MvpkmLockMPN)
-#define MVPKM_UNLOCK_MPN _IOW(MVP_IOCTL_LETTER, 0xa2, MvpkmLockMPN)
-#define MVPKM_RUN_MONITOR _IO( MVP_IOCTL_LETTER, 0xa3)
-#define MVPKM_CPU_INFO _IOR(MVP_IOCTL_LETTER, 0xa4, MvpkmCpuInfo)
-#define MVPKM_ABORT_MONITOR _IO( MVP_IOCTL_LETTER, 0xa5)
-#define MVPKM_MAP_WSPHKVA _IOW(MVP_IOCTL_LETTER, 0xa7, MvpkmMapHKVA)
-
-#include "mksck.h"
-#include "monva_common.h"
-#include "mvpkm_types.h"
-
-/**
- * @brief Operand for the MVPKM_LOCK_MPN call
- */
-typedef struct MvpkmLockMPN {
- uint32 order; /* IN */
- PhysMem_RegionType forRegion; /* IN */
- uint32 mpn; /* OUT */
-} MvpkmLockMPN;
-
-/**
- * @brief Operand for the MVPKM_MAP_HKVA call
- */
-typedef struct MvpkmMapHKVA {
- HkvaMapInfo *mapInfo; /* IN */
- PhysMem_RegionType forRegion; /* IN */
- HKVA hkva; /* OUT */
-} MvpkmMapHKVA;
-
-#define WSP_PAGE_COUNT 2
-
-/**
- * @brief Operand for the MVPKM_CPU_INFO call
- */
-typedef struct MvpkmCpuInfo {
- ARM_L2D attribL2D; /* OUT */
- ARM_MemAttrNormal attribMAN; /* OUT */
- _Bool mpExt; /* OUT */
-} MvpkmCpuInfo;
-
-/**
- * @brief These magic numbers mark the beginning and end of the
- * special page that is mapped into the virtual address space of MVPD
- * when it's monitor coredumper requests an unavailable page.
- */
-#define MVPKM_STUBPAGE_BEG 0x78d10c67
-#define MVPKM_STUBPAGE_END 0x8378f3dd
-#endif
diff --git a/arch/arm/mvp/mvpkm/mvpkm_types.h b/arch/arm/mvp/mvpkm/mvpkm_types.h
deleted file mode 100644
index ce23554..0000000
--- a/arch/arm/mvp/mvpkm/mvpkm_types.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Types used in the interface between users, user level wrappers,
- * and the kernel module implementation.
- */
-
-
-#ifndef _MVPKMTYPES_H
-#define _MVPKMTYPES_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-
-/**
- * @brief HkvaMapInfo structure describing the mpn and execute permission
- * flag to use to map a given page in HKVA space
- */
-typedef struct HkvaMapInfo {
- uint32 mpn;
- _Bool write;
- _Bool exec;
-} HkvaMapInfo;
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/nottested.h b/arch/arm/mvp/mvpkm/nottested.h
deleted file mode 100644
index 5226a22..0000000
--- a/arch/arm/mvp/mvpkm/nottested.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief NOT_TESTED() and related.
- */
-
-#ifndef _NOTTESTED_H
-#define _NOTTESTED_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include <stdbool.h>
-
-#ifdef NOT_TESTED_ENABLED
-#define NotTestedEnabled true
-#else
-#define NotTestedEnabled false
-#endif
-
-#define NOT_TESTED() NOT_TESTED_JIRA(0)
-#define NOT_TESTED_JIRA(_tkt,...) NotTested(_tkt, __FILE__, __LINE__)
-
-void NotTested(int tkt, char const *file, int line);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/platdefx.h b/arch/arm/mvp/mvpkm/platdefx.h
deleted file mode 100644
index 70fb8d7..0000000
--- a/arch/arm/mvp/mvpkm/platdefx.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Basic platform definitions needed various places.
- */
-
-#ifndef _PLATDEFX_H
-#define _PLATDEFX_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define PAGE_ORDER 12
-
-#ifndef PAGE_SIZE
-#define PAGE_SIZE (1UL << PAGE_ORDER)
-#endif
-#if PAGE_SIZE != 4096
-#error bad page size PAGE_SIZE
-#endif
-
-#define PA_2_PPN(_pa) ((_pa) / PAGE_SIZE)
-#define PPN_2_PA(_ppn) ((_ppn) * PAGE_SIZE)
-
-#define VMM_DOMAIN 0x0
-#define VMM_DOMAIN_NO_ACCESS 0x3
-#define VMM_DOMAIN_CLIENT 0x1
-#define VMM_DOMAIN_MANAGER 0x4
-
-#define INVALID_CVA (-(CVA)1)
-#define INVALID_GVA (-(GVA)1)
-#define INVALID_MVA (-(MVA)1)
-#define INVALID_HKVA (-(HKVA)1)
-#define INVALID_HUVA (-(HUVA)1)
-
-#define INVALID_MPN (((MPN)-1) >> ARM_L2D_SMALL_ORDER)
-#define INVALID_PPN (((PPN)-1) >> ARM_L2D_SMALL_ORDER)
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/psr_defs.h b/arch/arm/mvp/mvpkm/psr_defs.h
deleted file mode 100644
index 4fa53bc..0000000
--- a/arch/arm/mvp/mvpkm/psr_defs.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Constant definitions for ARM CPSR/SPSR registers. See A2.5
- * ARM DDI 0100I.
- */
-
-#ifndef _PSR_DEFS_H_
-#define _PSR_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define ARM_PSR_MODE_USER 0x10
-#define ARM_PSR_MODE_FIQ 0x11
-#define ARM_PSR_MODE_IRQ 0x12
-#define ARM_PSR_MODE_SUPERVISOR 0x13
-#define ARM_PSR_MODE_ABORT 0x17
-#define ARM_PSR_MODE_HVC 0x1a
-#define ARM_PSR_MODE_UNDEFINED 0x1b
-#define ARM_PSR_MODE_SYSTEM 0x1f
-
-/* Bit 31: N */
-#define ARM_PSR_N (1 << 31)
-
-/* Bit 30: Z */
-#define ARM_PSR_Z (1 << 30)
-
-/* Bit 29: C */
-#define ARM_PSR_C (1 << 29)
-
-/* Bit 28: V */
-#define ARM_PSR_V (1 << 28)
-
-/* Bit 27: Q */
-#define ARM_PSR_Q (1 << 27)
-
-#define ARM_PSR_COND_FLAGS \
- (ARM_PSR_N | ARM_PSR_Z | ARM_PSR_C | ARM_PSR_V | ARM_PSR_Q)
-
-/* Bits 26..25: ITSTATE<1..0> */
-#define ARM_PSR_ITSTATE_LOW MVP_MASK(25, 2)
-
-/* Bit 24: J */
-#define ARM_PSR_J (1 << 24)
-
-/* Bits 23..20 are reserved as of ARMv7 */
-#define ARM_PSR_RESERVED MVP_MASK(20, 4)
-
-/* Bits 19..16: GE<3..0> */
-#define ARM_PSR_GE MVP_MASK(16, 4)
-
-/* Bits 15..10: ITSTATE<7..2> */
-#define ARM_PSR_ITSTATE_HIGH MVP_MASK(10, 6)
-#define ARM_PSR_ITSTATE (ARM_PSR_ITSTATE_LOW | ARM_PSR_ITSTATE_HIGH)
-
-/* Bit 9: E */
-#define ARM_PSR_E_POS (9)
-#define ARM_PSR_E (1 << ARM_PSR_E_POS)
-
-/* Bit 8: A */
-#define ARM_PSR_A_POS (8)
-#define ARM_PSR_A (1 << ARM_PSR_A_POS)
-
-/* Bit 7: I */
-#define ARM_PSR_I_POS (7)
-#define ARM_PSR_I (1 << ARM_PSR_I_POS)
-
-/* Bit 6: F */
-#define ARM_PSR_F_POS (6)
-#define ARM_PSR_F (1 << ARM_PSR_F_POS)
-
-/* Bit 5: T */
-#define ARM_PSR_T_POS (5)
-#define ARM_PSR_T (1 << ARM_PSR_T_POS)
-
-/* Bits 4..0: Mode */
-#define ARM_PSR_MODE_MASK 0x1f
-
-#define ARM_PSR_MODE(cpsr) ((cpsr) & ARM_PSR_MODE_MASK)
-#define ARM_PSR_USER_MODE(cpsr) (ARM_PSR_MODE(cpsr) == ARM_PSR_MODE_USER)
-
-
-/*
- * We shadow the 10 LSBs in the CPSR, with the exception of the T bit, as they
- * are managed by the VMM on behalf of the guest and are potentially different
- * than the physical CPSR during DE.
- */
-#define ARM_PSR_MONITOR_BITS 10
-#define ARM_PSR_MONITOR_MASK (((1 << ARM_PSR_MONITOR_BITS) - 1) & ~ARM_PSR_T)
-
-#endif /// ifndef _PSR_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/qp.h b/arch/arm/mvp/mvpkm/qp.h
deleted file mode 100644
index a8d7ac1..0000000
--- a/arch/arm/mvp/mvpkm/qp.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP Queue Pairs function and structure declarations
- *
- * MVP Queue Pairs:
- *
- * Queue pairs are intended to be a generic bulk data transport mechanism
- * between the guest and host kernels. The queue pair abstraction is based
- * on two ring buffers (queues) placed on a shared memory region mapped
- * into both guest and host kernel address spaces.
- *
- * NOTE: Queue pairs are SINGLE-READER, SINGLE-WRITER. Any caller is
- * responsible for multi-reader/writer serialization!!!
- *
- * There are a maximum of QP_MAX_QUEUE_PAIRS in the system, with a maximum
- * size of QP_MAX_CAPACITY per pair. Each queue pair is identified by
- * an ID.
- *
- * Each peer follows a producer-consumer model in which one side is the
- * producer on one queue, and the other side is the consumer on that queue
- * (and vice-versa for its pair).
- *
- * Data is enqueued and dequeued into the pair in transactional stages,
- * meaning each enqueue/dequeue can be followed by zero or more
- * enqueue/dequeues, but the enqueue/dequeue is not visible to the peer
- * until it has been committed with the *Commit() function.
- * In PVTCP, for example, this is used to enqueue a short header, then
- * followed by 'segments' of iovecs, then followed by a commit. This
- * model prevents a peer from reading the header, expecting a payload,
- * but not being able to read the payload because it hasn't been
- * enqueued yet.
- *
- * Queue Pair setup:
- *
- * Before data can be passed, the guest and host kernel must perform
- * the following connection handshake:
- *
- * 1). A host kernel service registers a listener with the queue pair
- * subsystem with a callback to be called when guests create
- * and attach to a shared memory region.
- *
- * 2). Guest initiates an QP_Attach() operation to a shared memory region
- * keyed by ID. This step allocates memory, maps it into the host
- * address space, and optionally notifies any host services who are
- * listening for attach requests from the guest (see previous step).
- * Host listeners are provided with a copy of the initialization
- * arguments used by the guest (id, size, service type). All registered
- * listeners are iterated over until one of them handles the attach
- * request and acknowledges with QP_SUCCESS.
- *
- * 3). The registered host callback is called, notifying the host that
- * the guest has attached.
- *
- * 4). The host can now QP_Attach() to the shared memory region with the same
- * arguments as the guest. The queue pair is now well formed and enqueues
- * and dequeues can proceed on either side.
- *
- * Queue Pair teardown:
- *
- * 1). As before, teardowns are initiated by the guest. Hosts can register
- * a callback to be called upon detach. Guests initiate a teardown
- * through a call to QP_Detach().
- *
- * 2). Registered hosts are notified through the aforementioned callback.
- * 3). The host service can call QP_Detach() at its own leisure. Memory
- * is freed, the queue pair is destroyed.
- *
- * If at any point the guest unexpectedly shuts down, the host will be
- * notified at monitor shutdown time. Memory is freed, and the queue
- * pair is destroyed.
- *
- */
-
-#ifndef _QP_H
-#define _QP_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-//#define QP_DEBUG 1
-
-typedef enum QPState {
- QP_STATE_FREE = 0x1, ///< No peers, not memory-backed
- QP_STATE_CONNECTED, ///< Both peers attached , memory backed
- QP_STATE_GUEST_ATTACHED, ///< Guest allocated memory, host not yet attached
- QP_STATE_MAX // leave this at the end!
-} QPState;
-
-typedef struct QPId {
- uint32 context;
- uint32 resource;
-} QPId;
-
-/*
- * Initialization arguments for each queue pair
- */
-typedef struct QPInitArgs {
- QPId id; ///< Shared memory region ID
- uint32 capacity; ///< Total size of shared region in bytes
- uint32 type; ///< Type of queue pair (PVTCP, other)...
-} QPInitArgs;
-
-/*
- * Placed on the shared region, two per region
- */
-typedef struct QHandle {
- volatile uint32 head; ///< queue head offset
- volatile uint32 tail; ///< queue tail offset
- volatile uint32 phantom_head; ///< queue shadow head offset
- volatile uint32 phantom_tail; ///< queue shadow tail offset
- uint8 data[0]; ///< start of data, runs off
- // the struct
-} QHandle;
-
-/*
- * Local to each peer
- */
-typedef struct QPHandle {
- QPId id; ///< shared memory region ID
- uint32 capacity; ///< size of region in bytes
- QHandle *produceQ; ///< producer queue
- QHandle *consumeQ; ///< consumer queue
- uint32 queueSize; ///< size of each queue in bytes
- uint32 type; ///< type of queue pair
-
- /*
- * Following fields unused by guest
- */
- QPState state;
- void (*peerDetachCB)(void* data); ///< detach notification callback
- void *detachData; ///< data for the detach cb
- struct page **pages; ///< page pointers for shared region
-} QPHandle;
-
-/*
- * QP Error codes
- */
-#define QP_SUCCESS 0
-#define QP_ERROR_NO_MEM (-1)
-#define QP_ERROR_INVALID_HANDLE (-2)
-#define QP_ERROR_INVALID_ARGS (-3)
-#define QP_ERROR_ALREADY_ATTACHED (-4)
-
-/*
- * Hard-coded limits
- */
-#define QP_MIN_CAPACITY (PAGE_SIZE * 2)
-#define QP_MAX_CAPACITY (1024*1024) // 1M
-#define QP_MAX_QUEUE_PAIRS 32
-#define QP_MAX_ID QP_MAX_QUEUE_PAIRS
-#define QP_MAX_LISTENERS QP_MAX_QUEUE_PAIRS
-#define QP_MAX_PAGES (QP_MAX_CAPACITY/PAGE_SIZE) // 256 pages
-
-#define QP_INVALID_ID 0xFFFFFFFF
-#define QP_INVALID_SIZE 0xFFFFFFFF
-#define QP_INVALID_REGION 0xFFFFFFFF
-#define QP_INVALID_TYPE 0xFFFFFFFF
-
-#ifdef __KERNEL__
-/**
- * @brief Utility function to sanity check arguments
- * @param args argument structure to check
- * @return true if arguments are sane, false otherwise
- */
-static inline
-_Bool QP_CheckArgs(QPInitArgs *args)
-{
- if (!args ||
- !is_power_of_2(args->capacity) ||
- (args->capacity < QP_MIN_CAPACITY) ||
- (args->capacity > QP_MAX_CAPACITY) ||
- !(args->id.resource < QP_MAX_ID || args->id.resource == QP_INVALID_ID) ||
- (args->type == QP_INVALID_TYPE)) {
- return false;
- } else {
- return true;
- }
-}
-#endif
-
-
-/**
- * @brief Utility function to sanity check a queue pair handle
- * @param qp handle to the queue pair
- * @return true if the handle is sane, false otherwise
- */
-static inline
-_Bool QP_CheckHandle(QPHandle *qp)
-{
-#ifdef MVP_DEBUG
- if (!(qp) ||
- !(qp->produceQ) ||
- !(qp->consumeQ) ||
- (qp->state >= (uint32)QP_STATE_MAX) ||
- !(qp->queueSize < (QP_MAX_CAPACITY/2))) {
- return false;
- } else {
- return true;
- }
-#else
- return true;
-#endif
-}
-
-
-/**
- * @brief Initializes an invalid handle
- * @param[in, out] qp handle to the queue pair
- */
-static inline void
-QP_MakeInvalidQPHandle(QPHandle *qp)
-{
- if (!qp) {
- return;
- }
-
- qp->id.context = QP_INVALID_ID;
- qp->id.resource = QP_INVALID_ID;
- qp->capacity = QP_INVALID_SIZE;
- qp->produceQ = NULL;
- qp->consumeQ = NULL;
- qp->queueSize = QP_INVALID_SIZE;
- qp->type = QP_INVALID_TYPE;
- qp->state = QP_STATE_FREE;
- qp->peerDetachCB = NULL;
- qp->detachData = NULL;
-}
-
-/*
- * Host only
- */
-typedef int32 (*QPListener)(const QPInitArgs*);
-int32 QP_RegisterListener(const QPListener);
-int32 QP_UnregisterListener(const QPListener);
-int32 QP_RegisterDetachCB(QPHandle *qp, void (*callback)(void*), void *data);
-
-
-/*
- * Host and guest specific implementations, see qp_host.c and qp_guest.c
- */
-int32 QP_Attach(QPInitArgs *args, QPHandle** qp);
-int32 QP_Detach(QPHandle* qp);
-int32 QP_Notify(QPInitArgs *args);
-
-/*
- * Common implementation, see qp_common.c
- */
-int32 QP_EnqueueSpace(QPHandle *qp);
-int32 QP_EnqueueSegment(QPHandle *qp, const void *buf, size_t length);
-int32 QP_EnqueueCommit(QPHandle *qp);
-int32 QP_EnqueueReset(QPHandle *qp);
-
-static inline int32
-QP_EnqueueAtomic(QPHandle *qp, const void *buf, size_t length)
-{
- int32 rc;
- QP_EnqueueReset(qp);
- rc = QP_EnqueueSegment(qp, buf, length);
- if (rc < 0) {
- return rc;
- } else {
- QP_EnqueueCommit(qp);
- }
- return rc;
-}
-
-int32 QP_DequeueSpace(QPHandle *qp);
-int32 QP_DequeueSegment(QPHandle *qp, const void *buf, size_t length);
-int32 QP_DequeueReset(QPHandle *qp);
-int32 QP_DequeueCommit(QPHandle *qp);
-
-static inline int32
-QP_DequeueAtomic(QPHandle *qp, const void *buf, size_t length)
-{
- int32 rc;
- QP_DequeueReset(qp);
- rc = QP_DequeueSegment(qp, buf, length);
- if (rc < 0) {
- return rc;
- } else {
- QP_DequeueCommit(qp);
- }
- return rc;
-}
-
-/*
- * HVC methods and signatures
- */
-#define MVP_QP_SIGNATURE 0x53525051 ///< 'QPRS'
-#define MVP_QP_ATTACH (MVP_OBJECT_CUSTOM_BASE + 0) ///< attach to a queue pair
-#define MVP_QP_DETACH (MVP_OBJECT_CUSTOM_BASE + 1) ///< detach from a queue pair
-#define MVP_QP_NOTIFY (MVP_OBJECT_CUSTOM_BASE + 2) ///< notify host of attach
-#define MVP_QP_LAST (MVP_OBJECT_CUSTOM_BASE + 3) ///< Number of methods
-
-/*
- * Debug macros
- */
-#ifdef QP_DEBUG
- #ifdef IN_MONITOR
- #define QP_DBG(...) Log(__VA_ARGS__)
- #else
- #define QP_DBG(...) printk(KERN_INFO __VA_ARGS__)
- #endif
-#else
- #define QP_DBG(...)
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/qp_common.c b/arch/arm/mvp/mvpkm/qp_common.c
deleted file mode 100644
index 8d121a1..0000000
--- a/arch/arm/mvp/mvpkm/qp_common.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP Queue Pairs common enqueue and dequeue functions.
- * Does not include Attach(), and Detach(), as this will be specific
- * to host/guest
- * implementations.
- */
-
-#include <linux/module.h>
-
-#include "mvp_types.h"
-#include "comm_os.h"
-#include "qp.h"
-
-
-/**
- * @brief Calculate free space in the queue, convenience function
- * @param head queue head offset
- * @param tail queue tail offset
- * @param queueSize size of queue
- * @return free space in the queue
- */
-static inline int32
-FreeSpace(uint32 head, uint32 tail, uint32 queueSize) {
- /* Leave 1 byte free to resolve ambiguity between empty
- * and full conditions */
- return (tail >= head) ? (queueSize - (tail - head) - 1) :
- (head - tail - 1);
-}
-
-
-/**
- * @brief Returns available space for enqueue, in bytes
- * @param qp handle to the queue pair
- * @return available space in bytes in the queue for enqueue operations,
- * QP_ERROR_INVALID_HANDLE if the handle is malformed
- */
-int32
-QP_EnqueueSpace(QPHandle *qp)
-{
- uint32 head;
- uint32 phantom;
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- head = qp->produceQ->head;
- phantom = qp->produceQ->phantom_tail;
-
- if (head >= qp->queueSize ||
- phantom >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- return FreeSpace(head, phantom, qp->queueSize);
-}
-
-
-/**
- * @brief Enqueues a segment of data into the producer queue
- * @param qp handle to the queue pair
- * @param buf data to enqueue
- * @param bufSize size in bytes to enqueue
- * @return number of bytes enqueued on success, appropriate error
- * code otherwise
- * @sideeffects May move phantom tail pointer
- */
-int32
-QP_EnqueueSegment(QPHandle *qp, const void *buf, size_t bufSize)
-{
- int32 freeSpace;
- uint32 head;
- uint32 phantom;
-
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- head = qp->produceQ->head;
- phantom = qp->produceQ->phantom_tail;
-
- /*
- * This check must go after the assignment above,
- * otherwise a malicious guest could write bogus
- * offsets to the queue and cause the memcpy to
- * copy into unpleasant places.
- */
- if (head >= qp->queueSize ||
- phantom >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- freeSpace = FreeSpace(head, phantom, qp->queueSize);
-
- if (bufSize <= freeSpace) {
- if (bufSize + phantom < qp->queueSize) {
- memcpy(qp->produceQ->data + phantom, buf, bufSize);
- phantom += bufSize;
- } else {
- uint32 written = qp->queueSize - phantom;
- memcpy(qp->produceQ->data + phantom, buf, written);
- memcpy(qp->produceQ->data, (uint8*)buf + written, bufSize - written);
- phantom = bufSize - written;
- }
- } else {
- return QP_ERROR_NO_MEM;
- }
-
- qp->produceQ->phantom_tail = phantom;
-
- return bufSize;
-}
-
-
-/**
- * @brief Commits any previous EnqueueSegment operations to the queue
- * pair
- * @param qp handle to the queue pair.
- * @return QP_SUCCESS on success, appropriate error code otherwise.
- * @sideeffects May move tail pointer
- */
-int32
-QP_EnqueueCommit(QPHandle *qp)
-{
- uint32 phantom;
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- phantom = qp->produceQ->phantom_tail;
- if (phantom >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- qp->produceQ->tail = phantom;
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Returns any available bytes for dequeue
- * @param qp handle to the queue pair
- * @return available bytes for dequeue, appropriate error code
- * otherwise
- */
-int32
-QP_DequeueSpace(QPHandle *qp)
-{
- uint32 tail;
- uint32 phantom;
- int32 bytesAvailable;
-
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- tail = qp->consumeQ->tail;
- phantom = qp->consumeQ->phantom_head;
-
- if (tail >= qp->queueSize ||
- phantom >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- bytesAvailable = (tail - phantom);
- if ((int32)bytesAvailable < 0) {
- bytesAvailable += qp->queueSize;
- }
- return bytesAvailable;
-}
-
-
-/**
- * @brief Dequeues a segment of data from the consumer queue into
- * a buffer
- * @param qp handle to the queue pair
- * @param[out] buf buffer to copy to
- * @param bytesDesired number of bytes to dequeue
- * @return number of bytes dequeued on success, appropriate error
- * code otherwise
- * @sideeffects May move phantom head pointer
- */
-int32
-QP_DequeueSegment(QPHandle *qp, const void *buf, size_t bytesDesired)
-{
- uint32 tail;
- uint32 phantom;
- int32 bytesAvailable = 0;
-
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- tail = qp->consumeQ->tail;
- phantom = qp->consumeQ->phantom_head;
-
- /*
- * This check must go after the assignment above,
- * otherwise a malicious guest could write bogus
- * offsets to the queue and cause the memcpy to
- * copy into unpleasant places.
- */
- if (tail >= qp->queueSize ||
- phantom >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- bytesAvailable = (tail - phantom);
- if ((int32)bytesAvailable < 0) {
- bytesAvailable += qp->queueSize;
- }
-
- if (bytesDesired <= bytesAvailable) {
- if (bytesDesired + phantom < qp->queueSize) {
- memcpy((void*)buf, qp->consumeQ->data + phantom, bytesDesired);
- phantom += bytesDesired;
- } else {
- uint32 written = qp->queueSize - phantom;
- memcpy((void*)buf, qp->consumeQ->data + phantom, written);
- memcpy((uint8*)buf + written, qp->consumeQ->data, bytesDesired - written);
- phantom = bytesDesired - written;
- }
- } else {
- return QP_ERROR_NO_MEM;
- }
-
- qp->consumeQ->phantom_head = phantom;
-
- return bytesDesired;
-}
-
-
-/**
- * @brief Commits any previous DequeueSegment operations to the queue
- * pair
- * @param qp handle to the queue pair
- * @return QP_SUCCESS on success, QP_ERROR_INVALID_HANDLE if the handle
- * is malformed
- * @sideeffects Moves the head pointer
- */
-int32
-QP_DequeueCommit(QPHandle *qp)
-{
- uint32 phantom;
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- phantom = qp->consumeQ->phantom_head;
- if (phantom >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- qp->consumeQ->head = phantom;
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Resets the phantom tail pointer and discards any pending
- * enqueues
- * @param qp handle to the queue pair
- * @return QP_SUCCESS on success, QP_ERROR_INVALID_HANDLE if the handle
- * is malformed
- * @sideeffects Resets the phantom tail pointer
- */
-int32
-QP_EnqueueReset(QPHandle *qp)
-{
- uint32 tail;
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- tail = qp->produceQ->tail;
- if (tail >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- qp->produceQ->phantom_tail = tail;
- return QP_SUCCESS;
-}
-
-/**
- * @brief Resets the phantom head pointer and discards any pending
- * dequeues
- * @param qp handle to the queue pair
- * @return QP_SUCCESS on success, QP_ERROR_INVALID_HANDLE if the handle
- * is malformed
- * @sideeffects Resets the phantom head pointer
- */
-int32
-QP_DequeueReset(QPHandle *qp)
-{
- uint32 head;
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- head = qp->consumeQ->head;
- if (head >= qp->queueSize) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- qp->consumeQ->phantom_head = head;
- return QP_SUCCESS;
-}
-
-EXPORT_SYMBOL(QP_EnqueueSpace);
-EXPORT_SYMBOL(QP_EnqueueSegment);
-EXPORT_SYMBOL(QP_EnqueueCommit);
-EXPORT_SYMBOL(QP_DequeueSpace);
-EXPORT_SYMBOL(QP_DequeueSegment);
-EXPORT_SYMBOL(QP_DequeueCommit);
-EXPORT_SYMBOL(QP_EnqueueReset);
-EXPORT_SYMBOL(QP_DequeueReset);
diff --git a/arch/arm/mvp/mvpkm/qp_host_kernel.c b/arch/arm/mvp/mvpkm/qp_host_kernel.c
deleted file mode 100644
index c53f315..0000000
--- a/arch/arm/mvp/mvpkm/qp_host_kernel.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP host kernel implementation of the queue pairs API
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-
-#include "mvp.h"
-#include "mvpkm_kernel.h"
-#include "qp.h"
-#include "qp_host_kernel.h"
-
-static QPHandle queuePairs[QP_MAX_QUEUE_PAIRS];
-static QPListener listeners[QP_MAX_LISTENERS];
-
-/*
- * Protect listeners and queuePairs.
- */
-static DEFINE_MUTEX(qpLock);
-
-#define QPLock() mutex_lock(&qpLock)
-#define QPUnlock() mutex_unlock(&qpLock)
-
-/**
- * @brief Map a vector of pages into virtually contiguous kernel space
- * @param vm this vm's vm struct
- * @param base base machine page number that lists pages to map
- * @param nrPages number of pages to map
- * @param[out] qp handle to qp to set up
- * @param[out] hkva virtual address mapping
- * @return QP_SUCCESS on success, error code otherwise. Mapped address
- * is returned in hkva
- */
-
-static int32
-MapPages(MvpkmVM *vm,
- MPN base,
- uint32 nrPages,
- QPHandle *qp,
- HKVA *hkva)
-{
- HKVA *va;
- uint32 i;
- uint32 rc;
- struct page *basepfn = pfn_to_page(base);
- struct page **pages;
-
- BUG_ON(!vm); // this would be very bad.
-
- if (!hkva) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- pages = kmalloc(nrPages * sizeof (MPN), GFP_KERNEL);
- if (!pages) {
- return QP_ERROR_NO_MEM;
- }
-
- /*
- * Map in the first page, read out the MPN vector
- */
- down_write(&vm->lockedSem);
- va = kmap(basepfn);
- if (!va) {
- rc = QP_ERROR_INVALID_ARGS;
- kfree(pages);
- qp->pages = NULL;
- goto out;
- }
-
- /*
- * Grab references and translate MPNs->PFNs
- */
- for (i = 0; i < nrPages; i++) {
- pages[i] = pfn_to_page(((MPN*)va)[i]);
- get_page(pages[i]);
- }
-
- /*
- * Clean up the first mapping and remap the entire vector
- */
- kunmap(basepfn);
- va = vmap(pages, nrPages, VM_MAP, PAGE_KERNEL);
- if (!va) {
- rc = QP_ERROR_NO_MEM;
- for (i = 0; i < nrPages; i++) {
- put_page(pages[i]);
- }
- kfree(pages);
- qp->pages = NULL;
- goto out;
- } else {
- *hkva = (HKVA)va;
- qp->pages = pages;
- }
-
- /*
- * Let's not leak mpns..
- */
- memset(va, 0x0, nrPages * PAGE_SIZE);
-
- rc = QP_SUCCESS;
-
-out:
- up_write(&vm->lockedSem);
- return rc;
-}
-
-/**
- * @brief Initialize all free queue pair entries and listeners
- */
-
-void
-QP_HostInit(void)
-{
- uint32 i;
-
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- QP_MakeInvalidQPHandle(&queuePairs[i]);
- }
-
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- listeners[i] = NULL;
- }
-}
-
-
-/**
- * @brief Detaches a guest from a queue pair and notifies
- * any registered listeners through the detach callback
- * @param id id that guest requested a detach from, detaches all
- * queue pairs associated with a VM if the resource id == QP_INVALID_ID
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_GuestDetachRequest(QPId id)
-{
- QPHandle *qp;
- uint32 i;
-
- if (id.resource >= QP_MAX_ID && id.resource != QP_INVALID_ID) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- QPLock();
-
- /*
- * Invalidate all queue pairs associated with this VM if
- * resource == QP_INVALID_ID
- */
- if (id.resource == QP_INVALID_ID) {
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- qp = &queuePairs[i];
- if (qp->id.context == id.context && qp->peerDetachCB) {
- qp->peerDetachCB(qp->detachData);
- }
- }
- } else {
- qp = &queuePairs[id.resource];
- if (qp->peerDetachCB) {
- qp->peerDetachCB(qp->detachData);
- }
- }
-
- QPUnlock();
-
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Attaches a guest to shared memory region
- * @param vm guest to attach
- * @param args queue pair args structure:
- * - args->id: id of the region to attach to, if id.resource == QP_INVALID_ID, then
- * an id is assigned
- * - args->capacity: total size of the region in bytes
- * - args->type: type of queue pair (e.g PVTCP)
- * @param base base machine page number that lists pages to map
- * @param nrPages number of pages to map
- * @return QP_SUCCESS on success, appropriate error code otherwise.
- */
-
-int32
-QP_GuestAttachRequest(MvpkmVM *vm,
- QPInitArgs *args,
- MPN base,
- uint32 nrPages)
-{
- int32 rc;
- HKVA hkva = 0;
- QPHandle *qp;
- uint32 i;
-
- if ((!QP_CheckArgs(args)) ||
- (vm->wsp->guestId != (Mksck_VmId)args->id.context) ||
- (args->capacity != (nrPages * PAGE_SIZE))) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- QP_DBG("%s: Guest requested attach to [%u:%u] capacity: %u type: %x base: %x nrPages: %u\n",
- __FUNCTION__,
- args->id.context,
- args->id.resource,
- args->capacity,
- args->type,
- base,
- nrPages);
-
- QPLock();
-
- /*
- * Assign a resource id if id == QP_INVALID_ID
- */
- if (args->id.resource == QP_INVALID_ID) {
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- if (queuePairs[i].state == QP_STATE_FREE) {
- args->id.resource = i;
- QP_DBG("%s: Guest requested anonymous region, assigning resource id %u\n",
- __FUNCTION__, args->id.resource);
- goto found;
- }
- }
-
- rc = QP_ERROR_NO_MEM;
- goto out;
- }
-
-found:
- qp = queuePairs + args->id.resource;
-
- if (qp->state != QP_STATE_FREE) {
- rc = QP_ERROR_ALREADY_ATTACHED;
- goto out;
- }
-
- /*
- * Brand new queue pair, allocate some memory to back it and
- * initialize the entry
- */
- rc = MapPages(vm, base, nrPages, qp, &hkva);
- if (rc != QP_SUCCESS) {
- goto out;
- }
-
- /* NB: reversed from the guest */
- qp->id = args->id;
- qp->capacity = args->capacity;
- qp->produceQ = (QHandle*)hkva;
- qp->consumeQ = (QHandle*)(hkva + args->capacity/2);
- qp->queueSize = args->capacity/2 - sizeof(QHandle);
- qp->type = args->type;
- qp->state = QP_STATE_GUEST_ATTACHED;
-
- /*
- * The qp is now assumed to be well-formed
- */
- QP_DBG("%s: Guest attached to region [%u:%u] capacity: %u HKVA: %x\n",
- __FUNCTION__,
- args->id.context,
- args->id.resource,
- args->capacity,
- (uint32)hkva);
- rc = QP_SUCCESS;
-
-out:
- QPUnlock();
- if (rc != QP_SUCCESS) {
- QP_DBG("%s: Failed to attach: %u\n", __FUNCTION__, rc);
- }
- return rc;
-}
-
-
-/**
- * @brief Attaches the host to the shared memory region. The guest
- * MUST have allocated the shmem region already or else this will fail.
- * @param args structure with the shared memory region id to attach to,
- * total size of the region in bytes, and type of queue pair (e.g PVTCP)
- * @param[in, out] qp handle to the queue pair to return
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_Attach(QPInitArgs *args,
- QPHandle** qp)
-{
- uint32 rc;
-
- if (!qp || !QP_CheckArgs(args)) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- QP_DBG("%s: Attaching to id: [%u:%u] capacity: %u\n",
- __FUNCTION__,
- args->id.context,
- args->id.resource,
- args->capacity);
-
- QPLock();
- *qp = queuePairs + args->id.resource;
-
- if (!QP_CheckHandle(*qp)) {
- *qp = NULL;
- rc = QP_ERROR_INVALID_HANDLE;
- goto out;
- }
-
- if ((*qp)->state == QP_STATE_CONNECTED) {
- rc = QP_ERROR_ALREADY_ATTACHED;
- goto out;
- }
-
- if ((*qp)->state != QP_STATE_GUEST_ATTACHED) {
- rc = QP_ERROR_INVALID_HANDLE;
- goto out;
- }
-
- (*qp)->state = QP_STATE_CONNECTED;
-
- QP_DBG("%s: Attached!\n", __FUNCTION__);
- rc = QP_SUCCESS;
-
-out:
- QPUnlock();
- return rc;
-}
-
-/**
- * @brief Detaches the host to the shared memory region.
- * @param[in, out] qp handle to the queue pair
- * @return QP_SUCCESS on success, appropriate error code otherwise
- * @sideeffects Frees memory
- */
-
-int32
-QP_Detach(QPHandle* qp)
-{
- uint32 rc;
- uint32 i;
-
- QPLock();
- if (!QP_CheckHandle(qp)) {
- rc = QP_ERROR_INVALID_HANDLE;
- goto out;
- }
-
- QP_DBG("%s: Freeing queue pair [%u:%u]\n",
- __FUNCTION__,
- qp->id.context,
- qp->id.resource);
-
- BUG_ON(!qp->produceQ);
- BUG_ON(!qp->pages);
- BUG_ON((qp->state != QP_STATE_CONNECTED) &&
- (qp->state != QP_STATE_GUEST_ATTACHED));
-
- vunmap(qp->produceQ);
-
- for (i = 0; i < qp->capacity/PAGE_SIZE; i++) {
- put_page(qp->pages[i]);
- }
- kfree(qp->pages);
-
- QP_DBG("%s: Host detached from [%u:%u]\n",
- __FUNCTION__,
- qp->id.context,
- qp->id.resource);
-
- QP_MakeInvalidQPHandle(qp);
- rc = QP_SUCCESS;
-
-out:
- QPUnlock();
- return rc;
-}
-
-
-/**
- * @brief Detaches and destroys all queue pairs associated with a given guest
- * @param vmID which VM to clean up
- * @sideeffects Destroys all queue pairs for guest vmID
- */
-
-void QP_DetachAll(Mksck_VmId vmID) {
- QPId id = {
- .context = (uint32)vmID,
- .resource = QP_INVALID_ID
- };
-
- QP_DBG("%s: Detaching all queue pairs from vmId context %u\n", __FUNCTION__, vmID);
- QP_GuestDetachRequest(id);
-}
-
-/**
- * @brief Registers a listener into the queue pair system. Callbacks are
- * called with interrupts disabled and must not sleep.
- * @param listener listener to be called
- * @return QP_SUCCESS on success, QP_ERROR_NO_MEM if no more
- * listeners can be registered
- */
-
-int32
-QP_RegisterListener(const QPListener listener)
-{
- uint32 i;
- int32 rc = QP_ERROR_NO_MEM;
-
- QPLock();
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- if (!listeners[i]) {
- listeners[i] = listener;
- QP_DBG("%s: Registered listener\n", __FUNCTION__);
- rc = QP_SUCCESS;
- break;
- }
- }
- QPUnlock();
-
- return rc;
-}
-
-
-/**
- * @brief Unregister a listener service from the queue pair system.
- * @param listener listener to unregister
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_UnregisterListener(const QPListener listener)
-{
- uint32 i;
- int32 rc = QP_ERROR_INVALID_HANDLE;
-
- QPLock();
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- if (listeners[i] == listener) {
- listeners[i] = NULL;
- QP_DBG("%s: Unregistered listener\n", __FUNCTION__);
- rc = QP_SUCCESS;
- break;
- }
- }
- QPUnlock();
-
- return rc;
-}
-
-
-/**
- * @brief Registers a callback to be called when the guest detaches
- * from a queue pair. Callbacks are called with interrupts and
- * must not sleep.
- * @param qp handle to the queue pair
- * @param callback callback to be called
- * @param data data to deliver to the callback
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_RegisterDetachCB(QPHandle *qp,
- void (*callback)(void*),
- void *data)
-{
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- if (!callback) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- qp->peerDetachCB = callback;
- qp->detachData = data;
- QP_DBG("%s: Registered detach callback\n", __FUNCTION__);
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Noop on the host, only guests can initiate a notify
- * @param args noop
- * @return QP_SUCCESS
- */
-
-
-int32 QP_Notify(QPInitArgs *args) {
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Notify any registered listeners for the given queue pair
- * @param args initialization arguments used by the guest
- * @return QP_SUCCESS on success, error otherwise
- */
-
-int32 QP_NotifyListener(QPInitArgs *args) {
- int32 i;
- QPHandle *qp = NULL;
-
- if (!QP_CheckArgs(args)) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- /*
- * Iterate over listeners until one of them reports they handled it
- */
- QPLock();
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- if (listeners[i]) {
- QP_DBG("Delivering attach event to listener...\n");
- if (listeners[i](args) == QP_SUCCESS) {
- break;
- }
- }
- }
-
- if (i == QP_MAX_LISTENERS) {
- /*
- * No listener successfully probed this QP.
- * The guest DETACH HVC isn't implemented; we need compensate for it
- * by deallocating the QP here.
- * This is a workaround which assumes, more-or-less correctly, that
- * unsuccessful QP probes never lead to subsequent host-attaching.
- */
-
- qp = &queuePairs[args->id.resource];
- }
-
- QPUnlock();
-
- if (qp) {
- QP_Detach(qp);
- }
- return QP_SUCCESS;
-}
-
-
-EXPORT_SYMBOL(QP_Attach);
-EXPORT_SYMBOL(QP_Detach);
-EXPORT_SYMBOL(QP_RegisterListener);
-EXPORT_SYMBOL(QP_UnregisterListener);
-EXPORT_SYMBOL(QP_RegisterDetachCB);
-EXPORT_SYMBOL(QP_Notify);
diff --git a/arch/arm/mvp/mvpkm/qp_host_kernel.h b/arch/arm/mvp/mvpkm/qp_host_kernel.h
deleted file mode 100644
index 111524a..0000000
--- a/arch/arm/mvp/mvpkm/qp_host_kernel.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief QP host function prototypes
- */
-
-
-#ifndef _QP_HOST_KERNEL_H
-#define _QP_HOST_KERNEL_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-void QP_HostInit(void);
-int32 QP_GuestAttachRequest(MvpkmVM *vm,
- QPInitArgs *args,
- MPN base,
- uint32 nr_pages);
-int32 QP_GuestDetachRequest(QPId id);
-void QP_DetachAll(Mksck_VmId vmID);
-int32 QP_NotifyListener(QPInitArgs *args);
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/tsc.h b/arch/arm/mvp/mvpkm/tsc.h
deleted file mode 100644
index 0b3149b..0000000
--- a/arch/arm/mvp/mvpkm/tsc.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Time stamp and event counters.
- */
-
-#ifndef _TSC_H_
-#define _TSC_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "arm_inline.h"
-
-#define ARM_PMNC_E (1 << 0)
-#define ARM_PMNC_D (1 << 3)
-
-#define ARM_PMCNT_C (1 << 31)
-
-#define ARM_PMNC_INVALID_EVENT -1
-
-#define TSC_READ(_reg) ARM_MRC_CP15(CYCLE_COUNT, (_reg))
-#define TSC_WRITE(_reg) ARM_MCR_CP15(CYCLE_COUNT, (_reg))
-
-#endif // ifndef _TSC_H_
diff --git a/arch/arm/mvp/mvpkm/utils.h b/arch/arm/mvp/mvpkm/utils.h
deleted file mode 100644
index 1fc56e9..0000000
--- a/arch/arm/mvp/mvpkm/utils.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief General architecture-independent definitions, typedefs, and macros.
- */
-
-#ifndef _UTILS_H
-#define _UTILS_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_WORKSTATION
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define MAX_FILENAME 128
-
-// Round address up to given size boundary
-// Note: ALIGN() conflicts with Linux
-
-#define MVP_ALIGN(_v, _n) (((_v) + (_n) - 1) & -(_n))
-
-#define ALIGNVA(_addr, _size) MVP_ALIGN(_addr, _size)
-
-#define alignof(t) offsetof(struct { char c; typeof(t) x; }, x)
-
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#define KB(_X_) ((_X_)*1024U)
-#define MB(_X_) (KB(_X_)*1024)
-#define GB(_X_) (MB(_X_)*1024)
-
-#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
-
-/*
- * x in [low,high)
- * args evaluated once
- */
-#define RANGE(x,low,high) \
- ({ \
- typeof(x) _x = (x); \
- typeof(x) _low = (typeof(x))(low); \
- typeof(x) _high =(typeof(x))(high); \
- (_Bool)( (_low <= _x) && (_x < _high)); \
- })
-
-#define OBJECTS_PER_PAGE(_type) (PAGE_SIZE / sizeof(_type))
-
-#define MA_2_MPN(_ma) ((MPN)((_ma) / PAGE_SIZE))
-#define MPN_2_MA(_mpn) ((MA)((_mpn) * PAGE_SIZE))
-
-#define VA_2_VPN(_va) ((_va) / PAGE_SIZE)
-#define VPN_2_vA(_vpn) ((_vpn) * PAGE_SIZE)
-
-/*
- * The following convenience macro can be used in a following situation
- *
- * send(..., &foo, sizeof(foo)) --> send(..., PTR_N_SIZE(foo))
- */
-
-#define PTR_N_SIZE(_var) &(_var), sizeof(_var)
-
-
-/*
- *
- * BIT-PULLING macros
- *
- */
-#define MVP_BIT(val,n) ( ((val)>>(n))&1)
-#define MVP_BITS(val,m,n) (((val)<<(31-(n))) >> ((31-(n))+(m)) )
-#define MVP_EXTRACT_FIELD(w, m, n) MVP_BITS((w), (m), ((m) + (n) - 1))
-#define MVP_MASK(m, n) (MVP_EXTRACT_FIELD(~(uint32)0U, (m), (n)) << (m))
-#define MVP_UPDATE_FIELD(old_val, field_val, m, n) \
- (((old_val) & ~MVP_MASK((m), (n))) | (MVP_EXTRACT_FIELD((field_val), 0, (n)) << (m)))
-
-/*
- *
- * 64BIT-PULLING macros
- *
- */
-#define MVP_BITS64(val,m,n) (((val)<<(63-(n))) >> ((63-(n))+(m)) )
-#define MVP_EXTRACT_FIELD64(w, m, n) MVP_BITS64((w), (m), ((m) + (n) - 1))
-#define MVP_MASK64(m, n) (MVP_EXTRACT_FIELD64(~(uint64)0ULL, (m), (n)) << (m))
-#define MVP_UPDATE_FIELD64(old_val, field_val, m, n) \
- (((old_val) & ~MVP_MASK64((m), (n))) | (MVP_EXTRACT_FIELD64(((uint64)(field_val)), 0ULL, (n)) << (m)))
-
-/*
- *
- * BIT-CHANGING macros
- *
- */
-#define MVP_SETBIT(val,n) ((val)|=(1<<(n)))
-#define MVP_CLRBIT(val,n) ((val)&=(~(1<<(n))))
-
-/*
- * Fixed bit-width sign extension.
- */
-#define MVP_SIGN_EXTEND(val,width) \
- (((val) ^ (1 << ((width) - 1))) - (1 << ((width) - 1)))
-
-
-/*
- * Assembler helpers.
- */
-#define _MVP_HASH #
-#define MVP_HASH() _MVP_HASH
-
-#define _MVP_STRINGIFY(...) #__VA_ARGS__
-#define MVP_STRINGIFY(...) _MVP_STRINGIFY(__VA_ARGS__)
-
-#ifndef __ASSEMBLER__
-
-#include <stddef.h>
-#include <stdbool.h>
-
-/*
- * Constant equivalents of build-flags.
- *
- * Test these when possible instead of using #ifdef so that your code
- * gets parsed.
- */
-#ifdef MVP_DEBUG
-static const _Bool mvpDebug = true;
-#else
-static const _Bool mvpDebug = false;
-#endif
-
-#ifdef MVP_STATS
-static const _Bool mvpStats = true;
-#else
-static const _Bool mvpStats = false;
-#endif
-
-#ifdef MVP_DEVEL
-static const _Bool mvpDevel = true;
-#else
-static const _Bool mvpDevel = false;
-#endif
-
-#endif
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/ve_defs.h b/arch/arm/mvp/mvpkm/ve_defs.h
deleted file mode 100644
index bd1d975..0000000
--- a/arch/arm/mvp/mvpkm/ve_defs.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Virtualization extension definitions.
- *
- * See ARM PRD03-GENC-008353 11.0.
- */
-#ifndef _VE_DEFS_H_
-#define _VE_DEFS_H_
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define ARM_VE_HSR_EC_BIT_POS 26
-#define ARM_VE_HSR_EC_LENGTH 6
-
-#define ARM_VE_HSR_EC_UNKNOWN 0x00
-#define ARM_VE_HSR_EC_WFI_WFE 0x01
-#define ARM_VE_HSR_EC_MCR_MRC_CP15 0x03
-#define ARM_VE_HSR_EC_MCRR_MRRC_CP15 0x04
-#define ARM_VE_HSR_EC_MCR_MRC_CP14 0x05
-#define ARM_VE_HSR_EC_LDC_STC_CP14 0x06
-#define ARM_VE_HSR_EC_HCPTR 0x07
-#define ARM_VE_HSR_EC_MRC_CP10 0x08
-#define ARM_VE_HSR_EC_JAZELLE 0x09
-#define ARM_VE_HSR_EC_BXJ 0x0a
-#define ARM_VE_HSR_EC_MRRC_CP14 0x0c
-#define ARM_VE_HSR_EC_SVC_HYP 0x11
-#define ARM_VE_HSR_EC_HVC 0x12
-#define ARM_VE_HSR_EC_SMC 0x13
-#define ARM_VE_HSR_EC_IABORT_SND 0x20
-#define ARM_VE_HSR_EC_IABORT_HYP 0x21
-#define ARM_VE_HSR_EC_DABORT_SND 0x24
-#define ARM_VE_HSR_EC_DABORT_HYP 0x25
-
-#define ARM_VE_HSR_FS_BIT_POS 0
-#define ARM_VE_HSR_FS_LENGTH 6
-
-#define ARM_VE_HSR_FS_TRANS_L1 0x5
-#define ARM_VE_HSR_FS_TRANS_L2 0x6
-#define ARM_VE_HSR_FS_TRANS_L3 0x7
-
-#define ARM_VE_HSR_FS_PERM_L1 0xd
-#define ARM_VE_HSR_FS_PERM_L2 0xe
-#define ARM_VE_HSR_FS_PERM_L3 0xf
-
-#endif /// ifndef _VE_DEFS_H_
diff --git a/arch/arm/mvp/mvpkm/vfp_switch.S b/arch/arm/mvp/mvpkm/vfp_switch.S
deleted file mode 100644
index 49d3987..0000000
--- a/arch/arm/mvp/mvpkm/vfp_switch.S
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#include "arm_defs.h"
-#include "platdefx.h"
-#include "arm_as_macros.h"
-
-/**
- * @file
- *
- * @brief Save and Load VFP entire VFP state.
- */
-
- .text
-
-/**
- * @brief Save VFP context
- * @param R0 = save area pointer:
- * .long fpexc,fpscr,fpinst,fpinst2,cpacr,fpexc'
- * .double d0..d15
- * .double d16..d31
- * Note: VFP is left in an enable state regardless of initial state.
- */
- .align 4
- .global SaveVFP
-SaveVFP:
- /*
- * Save registers. GCC does not expect us to preserve R0..R3,R12,LR.
- */
- stmdb sp!, {r4-r6}
-
- /*
- * Save Coproc Access Control register.
- */
- mrc_p15 COPROC_ACCESS_CONTROL, r5
-
- /*
- * If CP10/11 are disabled, enable them so we can save VFP state.
- * The host (or guest) may have left data in the data registers that
- * must be preserved.
- */
- orr r2, r5, #CPACR_CP10_CP11_PRIV_ONLY
- mcr_p15 COPROC_ACCESS_CONTROL, r2
- isb
-
- /*
- * Follow procedure on AppxB-22 ARM DDI0406B to save FPINST[2].
- * Also enable VFP access with FPEXC_EN.
- */
- fmrx r1, fpexc @ get existing FPEXC system register
- orr r6, r1, #ARM_VFP_SYSTEM_REG_FPEXC_EX|ARM_VFP_SYSTEM_REG_FPEXC_FP2V|ARM_VFP_SYSTEM_REG_FPEXC_EN
-#if !defined(MVP_HOST_CODE_forceon)
- fmxr fpexc, r6 @ set FPEXC.EX, .FP2V and .EN
- fmrx r6, fpexc @ read them back
- tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_EX @ see if either one is valid
- beq 1000f @ neither, skip it all
- fmrx r3, FPINST @ FPINST is valid, save it
- tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_FP2V @ see if FPINST2 is valid
- beq 1000f
- fmrx r4, FPINST2 @ FPINST2 is valid, save it
-1000:
-#else
- mov r6, r1
-#endif
- fmrx r2, FPSCR @ always save FPSCR system register
-
- /*
- * At this point:
- * R1 = original FPEXC
- * R2 = FPSCR
- * R3 = FPINST
- * R4 = FPINST2
- * R5 = original CPACR
- * R6 = FPEXC readback with FPEXC.EX, .FP2V and .EN set
- * telling us whether FPINST/2 are valid
- */
- stmia r0!, {r1-r6}
-
- /*
- * Save floating point data registers.
- */
- vstmia r0!, {d0-d15} @ Save d0 thru d15
-
- /**
- * @todo We should probably just read MVFR0 once at boot/initialization
- * time and store it in some variable, to save having to do what might
- * be expensive coprocessor accesses.
- */
- fmrx r1, MVFR0 @ Read Media and VFP Feature Register 0
- and r1, r1, #ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK @ A_SIMD field
- cmp r1, #2 @ 32 x 64bit registers?
- bne 2000f
- vstmia r0!, {d16-d31}
-2000:
-
- /*
- * Restore scratch registers and return.
- */
- ldmia sp!, {r4-r6}
- mov pc, lr
-
-
-/**
- * @brief Load VFP context
- * @param R0 = load area pointer:
- * .long fpexc,fpscr,fpinst,fpinst2,cpacr,fpexc'
- * .double d0..d15
- * .double d16..d31
- * @note VFP is assumed to be in an enabled state on entry.
- */
- .align 4
- .global LoadVFP
-LoadVFP:
- /*
- * Save registers. GCC does not expect us to preserve R0..R3,R12,LR.
- */
- stmdb sp!, {r4-r6}
-
- /*
- * Get status register contents:
- * R1 = original FPEXC
- * R2 = FPSCR
- * R3 = FPINST
- * R4 = FPINST2
- * R5 = original CPACR
- * R6 = FPEXC readback with FPEXC.EX, .FP2V and .EN set
- * telling us whether FPINST/2 are valid
- */
- ldmia r0!, {r1-r6}
-
- /*
- * Restore some initial FP status registers.
- */
- fmxr fpexc, r6 @ with FPEXC.EX, .FP2V and .EN set
- fmxr FPSCR, r2 @ always load FPSCR system register
-
- /*
- * Follow procedure on AppxB-22 ARM DDI0406B to load FPINST[2].
- */
-#if !defined(MVP_HOST_CODE_forceon)
- fmrx r6, fpexc @ initial call might have different bits
- @ ... because FPEXC.EX, .FP2V and .EN
- @ are forced set by init code in
- @ mvpd.c SetupMonitor()
- tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_EX @ see if either one is valid
- beq 1000f @ neither, skip it all
- fmxr FPINST, r3 @ FPINST is valid, save it
- tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_FP2V @ see if FPINST2 is valid
- beq 1000f
- fmxr FPINST2, r4 @ FPINST2 is valid, save it
-1000:
-#endif
-
- /*
- * Load floating point data registers.
- */
- vldmia r0!, {d0-d15}
-
- /**
- * @todo We should probably just read MVFR0 once at boot/initialization
- * time and store it in some variable, to save having to do what might
- * be expensive coprocessor accesses.
- */
- fmrx r3, MVFR0 @ Read Media and VFP Feature Register 0
- and r3, r3, #ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK @ A_SIMD field
- cmp r3, #2 @ 32 x 64bit registers?
- bne 2000f
- vldmia r0!, {d16-d31}
-2000:
-
- /*
- * Now that VFP registers are all loaded, we put the restored values
- * back in the registers, possibly disabling the VFP.
- */
- fmxr fpexc, r1 @ with original FPEXC.EX, FPEXC.FP2V
- @ and FPEXC.EN values
-
- /*
- * Load Coproc Access Control CP10/CP11 enable bits, possibly disabling
- * VFP access.
- */
- mrc_p15 COPROC_ACCESS_CONTROL, r0
- bic r0, r0, #CPACR_CP10_CP11_MASK
- and r5, r5, #CPACR_CP10_CP11_MASK
- orr r0, r0, r5
- mcr_p15 COPROC_ACCESS_CONTROL, r0
- isb
-
- /*
- * Restore scratch registers and return.
- */
- ldmia sp!, {r4-r6}
- mov pc, lr
-
- .align 4
- .global GetFPEXC
-GetFPEXC:
- fmrx r0, fpexc @ get existing FPEXC system register
- mov pc, lr
diff --git a/arch/arm/mvp/mvpkm/vmid.h b/arch/arm/mvp/mvpkm/vmid.h
deleted file mode 100644
index dd89965..0000000
--- a/arch/arm/mvp/mvpkm/vmid.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-#ifndef _VMID_H
-#define _VMID_H
-
-/**
- * @file
- *
- * @brief The vmid definition
- */
-
-
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_HOSTUSER
-#define INCLUDE_ALLOW_GUESTUSER
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define VMID_UNDEF (uint16)0xffff
-typedef uint16 VmId;
-
-#endif
diff --git a/arch/arm/mvp/mvpkm/worldswitch.h b/arch/arm/mvp/mvpkm/worldswitch.h
deleted file mode 100644
index 785f2cd..0000000
--- a/arch/arm/mvp/mvpkm/worldswitch.h
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Definition of the world switch page
- *
- * Two pages are maintained to facilitate switching from the vmx to
- * the monitor - a data and code page. The data page contains:
- * - the necessary information about itself (its MPN, KVA, ...)
- * - the saved register file of the other world (including some cp15 regs)
- * - some information about the monitor's address space (the monVA member)
- * that needed right after the w.s before any communication channels
- * could have been established
- * - a world switch related L2 table of the monitor -- this could be
- * elsewhere.
- *
- * The code page contains:
- * - the actual switching code that saves/restores the registers
- *
- * The world switch data page is mapped into the user, kernel, and the monitor
- * address spaces. In case of the user and monitor spaces the global variable
- * wsp points to the world switch page (in the vmx and the monitor
- * respectively). The kernel address of the world switch page is saved on
- * the page itself: wspHKVA.
- *
- * The kernel virtual address for both code and data pages is mapped into
- * the monitor's space temporarily at the time of the actual switch. This is
- * needed to provide a stable code and data page while the L1 page table
- * base is changing. As the monitor does not need the world switch data page
- * at its KVA for its internal operation, that map is severed right after the
- * switching to the monitor and re-established before switching back.
- */
-#ifndef _WORLDSWITCH_H
-#define _WORLDSWITCH_H
-
-#define INCLUDE_ALLOW_MVPD
-#define INCLUDE_ALLOW_VMX
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/**
- * @brief Area for saving the monitor/kernel register files.
- *
- * The order of the registers in this structure was designed to
- * facilitate the organization of the switching code. For example
- * all Supervisor Mode registers are grouped together allowing the
- * @code
- * switch to svc,
- * stm old svc regs
- * ldm new svc regs
- * @endcode
- * code to work using a single base register for both the store and
- * load area.
- */
-#define MAX_REGISTER_SAVE_SIZE 464
-
-#ifndef __ASSEMBLER__
-typedef struct {
- uint32 kSPSR_svc;
- uint32 kr13_svc;
- uint32 kr14_svc;
- uint32 mSPSR_svc;
- uint32 mR13_svc;
- uint32 mR14_svc;
-
- uint32 kSPSR_abt;
- uint32 kr13_abt;
- uint32 kr14_abt;
- uint32 mSPSR_abt;
- uint32 mR13_abt;
- uint32 mR14_abt;
-
- uint32 kSPSR_und;
- uint32 kr13_und;
- uint32 kr14_und;
- uint32 mSPSR_und;
- uint32 mR13_und;
- uint32 mR14_und;
-
- uint32 kSPSR_irq;
- uint32 kr13_irq;
- uint32 kr14_irq;
- uint32 mSPSR_irq;
- uint32 mR13_irq;
- uint32 mR14_irq;
-
- uint32 kSPSR_fiq;
- uint32 kr8_fiq;
- uint32 kr9_fiq;
- uint32 kr10_fiq;
- uint32 kr11_fiq;
- uint32 kr12_fiq;
- uint32 kr13_fiq;
- uint32 kr14_fiq;
- uint32 mSPSR_fiq;
- uint32 mR8_fiq;
- uint32 mR9_fiq;
- uint32 mR10_fiq;
- uint32 mR11_fiq;
- uint32 mR12_fiq;
- uint32 mR13_fiq;
- uint32 mR14_fiq;
-} BankedRegisterSave;
-
-/**
- * @brief Registers for monitor execution context.
- */
-typedef struct {
- uint32 mCPSR;
- uint32 mR1;
- uint32 mR4;
- uint32 mR5;
- uint32 mR6;
- uint32 mR7;
- uint32 mR8;
- uint32 mR9;
- uint32 mR10;
- uint32 mR11;
- uint32 mSP;
- uint32 mLR; // =mPC
-} MonitorRegisterSave;
-
-/**
- * @brief LPV monitor register save/restore.
- */
-typedef struct {
- uint32 kR2; // =kCPSR
- uint32 kR4;
- uint32 kR5;
- uint32 kR6;
- uint32 kR7;
- uint32 kR8;
- uint32 kR9;
- uint32 kR10;
- uint32 kR11;
- uint32 kR13;
- uint32 kR14; // =kPC
-
- BankedRegisterSave bankedRegs;
-
- uint32 kCtrlReg;
- uint32 kTTBR0;
- uint32 kDACR;
- uint32 kASID;
- uint32 kTIDUserRW;
- uint32 kTIDUserRO;
- uint32 kTIDPrivRW;
- uint32 kCSSELR;
- uint32 kPMNCIntEn;
- uint32 kPMNCCCCNT;
- uint32 kPMNCOvFlag;
- uint32 kOpEnabled;
- uint32 mCtrlReg;
- uint32 mTTBR0;
- uint32 mASID;
- uint32 mTIDUserRW;
- uint32 mTIDUserRO;
- uint32 mTIDPrivRW;
- uint32 mCSSELR;
-
- MonitorRegisterSave monRegs;
-} RegisterSaveLPV;
-
-/**
- * @brief VE monitor register save/restore.
- */
-typedef struct {
- uint32 mHTTBR;
-
- uint32 kR3;
- uint32 kR4;
- uint32 kR5;
- uint32 kR6;
- uint32 kR7;
- uint32 kR8;
- uint32 kR9;
- uint32 kR10;
- uint32 kR11;
- uint32 kR12;
- uint32 kCPSR;
- uint32 kRet;
-
- BankedRegisterSave bankedRegs;
-
- uint32 kCSSELR;
- uint32 kCtrlReg;
- uint32 kTTBR0[2];
- uint32 kTTBR1[2];
- uint32 kTTBRC;
- uint32 kDACR;
- uint32 kDFSR;
- uint32 kIFSR;
- uint32 kAuxDFSR;
- uint32 kAuxIFSR;
- uint32 kDFAR;
- uint32 kIFAR;
- uint32 kPAR[2];
- uint32 kPRRR;
- uint32 kNMRR;
- uint32 kASID;
- uint32 kTIDUserRW;
- uint32 kTIDUserRO;
- uint32 kTIDPrivRW;
- uint32 mCSSELR;
- uint32 mCtrlReg;
- uint32 mTTBR0[2];
- uint32 mTTBR1[2];
- uint32 mTTBRC;
- uint32 mDACR;
- uint32 mDFSR;
- uint32 mIFSR;
- uint32 mAuxDFSR;
- uint32 mAuxIFSR;
- uint32 mDFAR;
- uint32 mIFAR;
- uint32 mPAR[2];
- uint32 mPRRR;
- uint32 mNMRR;
- uint32 mASID;
- uint32 mTIDUserRW;
- uint32 mTIDUserRO;
- uint32 mTIDPrivRW;
-
- uint32 mHCR;
- uint32 mHDCR;
- uint32 mHCPTR;
- uint32 mHSTR;
- uint32 mVTTBR[2];
- uint32 mVTCR;
-
- MonitorRegisterSave monRegs;
-} RegisterSaveVE;
-
-typedef union {
- unsigned char reserve_space[MAX_REGISTER_SAVE_SIZE];
- RegisterSaveLPV lpv;
- RegisterSaveVE ve;
-} RegisterSave;
-
-MY_ASSERTS(REGSAVE,
- ASSERT_ON_COMPILE(sizeof(RegisterSave) == MAX_REGISTER_SAVE_SIZE);
-)
-
-/**
- * @brief Area for saving the monitor/kernel VFP state.
- */
-typedef struct VFPSave {
- uint32 fpexc, fpscr, fpinst, fpinst2, cpacr, fpexc_;
-
- uint64 fpregs[32]; // Hardware requires that this must be 8-byte (64-bit)
- // aligned, however the SaveVFP/LoadVFP code does not
- // align its pointer before accessing so we don't have
- // an 'aligned(8)' attribute here. However, the
- // alignment is checked via asserts in SetupMonitor()
- // where it initializes the contents.
-
- // So if the preceding uint32's are changed and fpregs[]
- // is no longer 8-byte aligned, the assert will fire.
- // Then the uint32's will have to be fixed AND THE CODE
- // in SaveVFP/LoadVFP will have to be CHANGED EQUALLY to
- // compensate, as simply padding the uint32's (or
- // sticking an aligned(8) attribute here) will leave the
- // this structure mismatched with the code.
-
-} VFPSave __attribute__((aligned(8)));
- // Keep the aligned(8) attribute here though so the
- // VFPSave structures begin on an 8-byte boundary.
-
-typedef struct WorldSwitchPage WorldSwitchPage;
-typedef void (SwitchToMonitor)(RegisterSave *regSave);
-typedef void (SwitchToUser)(RegisterSave *regSaveEnd);
-
-#include "atomic.h"
-#include "monva_common.h"
-#include "mksck_shared.h"
-
-struct WorldSwitchPage {
- uint32 mvpkmVersion; ///< The version number of mvpkm
-
- HKVA wspHKVA; ///< host kernel virtual address of this page
- ARM_L1D wspKVAL1D; ///< The l1D entry at the above location
-
- SwitchToMonitor*switchToMonitor;///< entrypoint of the switching function
- SwitchToUser *switchToUser; ///< ditto
-
- MonVA monVA; ///< monitor virtual address space description
- union {
- ARM_L2D monAttribL2D; ///< {S,TEX,CB} attributes for monitor mappings (LPV)
- ARM_MemAttrNormal memAttr; ///< Normal memory attributes for monitor (VE)
- };
-
- MonitorType monType; ///< the type of the monitor. Used by mvpkm
- _Bool allowInts; ///< true: monitor runs with ints enabled as much as possible (normal)
- ///< false: monitor runs with ints blocked as much as possible (debug)
-
- struct {
- uint64 switchedAt64; ///< approx time CP15 TSC was set to...
- uint32 switchedAtTSC; ///< CP15 TSC value on entry from monitor
- uint32 tscToRate64Mult; ///< multiplier to convert TSC_READ()s to our RATE64s
- uint32 tscToRate64Shift; ///< shift to convert TSC_READ()s to our RATE64s
- };
-
- struct {
- AtmUInt32 hostActions; ///< actions for monitor on instruction boundary
- Mksck_VmId guestId; ///< vmId of the monitor page
- };
-
- struct { ///< Mksck attributes needed by Mksck_WspRelease()
- uint32 critSecCount; ///< if >0 the monitor is in critical section
- ///< and expects to regain control
- _Bool isPageMapped[MKSCK_MAX_SHARES]; ///< host mksckPages known to the monitor
- _Bool guestPageMapped;///< the guest Mksck page has been mapped in MVA space
- uint32 isOpened; ///< bitfield indicating which mkscks
- ///< are open on the guest's mksckPage.
- /* Note that isOpened is per VM not per VCPU. Also note
- * that this and other bitfields in the MksckPage structure
- * limit the number of sockets to 32.
- */
- };
-
-#define WSP_PARAMS_SIZE 512
- uint8 params_[WSP_PARAMS_SIZE]; ///< opaque worldswitch call parameters
-
- RegisterSave regSave; ///< Save area for the worldswitch code below
- VFPSave hostVFP; ///< Save areas for monitor/kernel VFP state
- VFPSave monVFP;
-
-__attribute__((aligned(ARM_L2PT_COARSE_SIZE)))
- ARM_L2D wspDoubleMap[ARM_L2PT_COARSE_ENTRIES]; ///< maps worldswitch page at its HKVA
- uint8 secondHalfPadding[ARM_L2PT_COARSE_SIZE];
-};
-
-/*
- * These asserts duplicate the assert at the beginning of SetL1L2esc.
- */
-MY_ASSERTS(WSP,
- ASSERT_ON_COMPILE(offsetof(struct WorldSwitchPage, wspDoubleMap) %
- ARM_L2PT_COARSE_SIZE == 0);
-)
-
-extern void SaveVFP(VFPSave *);
-extern void LoadVFP(VFPSave *);
-
-#define SWITCH_VFP_TO_MONITOR \
- do { \
- SaveVFP(&wsp->hostVFP); \
- LoadVFP(&wsp->monVFP); \
- } while(0)
-
-#define SWITCH_VFP_TO_HOST \
- do { \
- SaveVFP(&wsp->monVFP); \
- LoadVFP(&wsp->hostVFP); \
- } while(0)
-
-#endif /// __ASSEMBLER__
-
-#define OFFSETOF_KR3_REGSAVE_VE_WSP 616
-
-#endif /// _WORLDSWITCH_H
diff --git a/arch/arm/mvp/mvpkm/wscalls.h b/arch/arm/mvp/mvpkm/wscalls.h
deleted file mode 100644
index 4864f21..0000000
--- a/arch/arm/mvp/mvpkm/wscalls.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Worldswitch call parameters
- */
-
-#ifndef _WSCALLS_H
-#define _WSCALLS_H
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#define WSCALL_ACQUIRE_PAGE 1
-#define WSCALL_FLUSH_ALL_DCACHES 2
-#define WSCALL_IRQ 3
-#define WSCALL_ABORT 4
-#define WSCALL_LOG 5
-#define WSCALL_WAIT 6
-#define WSCALL_MUTEXLOCK 7
-#define WSCALL_MUTEXUNLOCK 8
-#define WSCALL_MUTEXUNLSLEEP 9
-#define WSCALL_MUTEXUNLWAKE 10
-#define WSCALL_GET_PAGE_FROM_VMID 11
-#define WSCALL_REMOVE_PAGE_FROM_VMID 12
-#define WSCALL_RELEASE_PAGE 13
-#define WSCALL_READTOD 14
-#define WSCALL_QP_GUEST_ATTACH 15
-#define WSCALL_MONITOR_TIMER 16
-#define WSCALL_COMM_SIGNAL 17
-#define WSCALL_QP_NOTIFY 18
-/*
- * MVPKM V0.5.2.0 supports all the calls above. If new API calls are
- * introduced then make sure that the calling function (probably in
- * mkhost.c) checks the mvpkm's version stored in wsp->mvpkmVersion
- * and invokes the wscall only when it is supported.
- */
-
-#define WSCALL_MAX_CALLNO 20
-
-#define WSCALL_LOG_MAX 256
-
-#define WSCALL_MAX_MPNS 16
-
-#include "exitstatus.h"
-#include "mutex.h"
-#include "mksck_shared.h"
-#include "qp.h"
-#include "comm_transp.h"
-#include "comm_transp_impl.h"
-
-typedef struct WSParams {
- uint32 callno;
- union {
- /**
- * @brief Used for both WSCALL_ACQUIRE_PAGE and WSCALL_RELEASE_PAGE.
- */
- struct {
- uint16 pages; ///< IN Number of pages
- uint16 order; /**< IN Size of each page -
- 2^(12+order) sized and aligned
- in machine space.
- (WSCALL_ACQUIRE_PAGE only) */
- PhysMem_RegionType forRegion; /**< IN Region identifier for pages
- (WSCALL_ACQUIRE_PAGE only) */
- MPN mpns[WSCALL_MAX_MPNS]; /**< OUT (on WSCALL_ACQUIRE_PAGE)
- IN (on WSCALL_RELEASE_PAGE)
- Vector of page base MPNs. */
- } pages;
-
- union {
- MPN mpn; ///< IN MPN to query refcount.
- _Bool referenced; ///< OUT Do host page tables contain the MPN?
- } refCount;
-
- struct {
- ExitStatus status; ///< IN the final status of the monitor
- } abort;
-
- struct {
- int level;
- char messg[WSCALL_LOG_MAX];
- } log;
-
- struct {
- HKVA mtxHKVA; ///< IN mutex's host kernel virt addr
- MutexMode mode; ///< IN shared or exclusive
- uint32 cvi; ///< IN condition variable index
- _Bool all; ///< IN wake all waiting threads?
- _Bool ok; ///< OUT Mutex_Lock completed
- } mutex;
-
- struct {
- Mksck_VmId vmId; ///< IN translate and lock this vmID
- _Bool found; /**< OUT true if the lookup was successful,
- page is found, and refc incremented */
- MPN mpn[MKSCKPAGE_TOTAL]; ///< OUT array of MPNs of the requested vmId
- } pageMgmnt;
-
- struct {
- unsigned int now; ///< OUT current time-of-day seconds
- unsigned int nowusec; ///< OUT current time-of-day microseconds
- } tod;
-
- struct {
- QPId id; ///< IN/OUT shared memory id
- uint32 capacity; ///< IN size of shared region requested
- uint32 type; ///< IN type of queue pair
- uint32 base; ///< IN base MPN of PA vector page
- uint32 nrPages; ///< IN number of pages to map
- int32 rc; ///< OUT return code
- } qp;
-
- struct {
- CommTranspID transpID;
- CommTranspIOEvent event;
- } commEvent;
-
- struct {
- uint64 when64; ///< IN timer request
- } timer;
-
- struct {
- _Bool suspendMode; ///< Is the guest in suspend mode?
- } wait;
-
- }; ///< anonymous union
-} WSParams;
-
-
-/**
- * @brief Cast the opaque param_ member of the wsp to WSParams type
- * @param wsp_ the world switch page structure pointer
- * @return the cast pointer
- */
-static inline WSParams* UNUSED
-WSP_Params(WorldSwitchPage *wsp_) {
- return (WSParams*)(wsp_->params_);
-}
-
-MY_ASSERTS(WSParFn,
- ASSERT_ON_COMPILE(sizeof(WSParams) <= WSP_PARAMS_SIZE);
-)
-#endif
diff --git a/arch/arm/mvp/pvtcpkm/COPYING b/arch/arm/mvp/pvtcpkm/COPYING
deleted file mode 100644
index 10828e0..0000000
--- a/arch/arm/mvp/pvtcpkm/COPYING
+++ /dev/null
@@ -1,341 +0,0 @@
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/arch/arm/mvp/pvtcpkm/Kbuild b/arch/arm/mvp/pvtcpkm/Kbuild
deleted file mode 100644
index d2ec844..0000000
--- a/arch/arm/mvp/pvtcpkm/Kbuild
+++ /dev/null
@@ -1,9 +0,0 @@
-# Warning: autogenerated
-obj-m := pvtcpkm.o
-pvtcpkm-objs := check_kconfig.o pvtcp_off_io_linux.o pvtcp_off_linux.o comm_os_linux.o comm_os_mod_linux.o pvtcp.o pvtcp_off.o pvtcp_off_linux_shim.o
-
-ccflags-y += -fno-pic -fno-dwarf2-cfi-asm -march=armv7-a -D__linux__
-ccflags-y += -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -DPVTCP_BUILDING_SERVER
-ccflags-y += -mfpu=neon -DIN_MODULE -DGPLED_CODE
-ccflags-y += --std=gnu89 -O2 -g2 -ggdb -mapcs -fno-optimize-sibling-calls -mno-sched-prolog
-ccflags-$(CONFIG_VMWARE_MVP_DEBUG) += -DMVP_DEBUG
diff --git a/arch/arm/mvp/pvtcpkm/Makefile b/arch/arm/mvp/pvtcpkm/Makefile
deleted file mode 100644
index 16eb389..0000000
--- a/arch/arm/mvp/pvtcpkm/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-# Warning: autogenerated
diff --git a/arch/arm/mvp/pvtcpkm/check_kconfig.c b/arch/arm/mvp/pvtcpkm/check_kconfig.c
deleted file mode 100644
index 6fc27a1..0000000
--- a/arch/arm/mvp/pvtcpkm/check_kconfig.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- * @brief Check for required kernel configuration
- *
- * Check to make sure that the kernel options that the MVP hypervisor requires
- * have been enabled in the kernel that this kernel module is being built
- * against.
- */
-#include <linux/version.h>
-
-/*
- * Minimum kernel version
- * - network namespace support is only really functional starting in 2.6.29
- * - Android Gingerbread requires 2.6.35
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
-#error "MVP requires a host kernel newer than 2.6.35"
-#endif
-
-/* module loading ability */
-#ifndef CONFIG_MODULES
-#error "MVP requires kernel loadable module support be enabled (CONFIG_MODULES)"
-#endif
-#ifndef CONFIG_MODULE_UNLOAD
-#error "MVP requires kernel module unload support be enabled (CONFIG_MODULE_UNLOAD)"
-#endif
-
-/* sysfs */
-#ifndef CONFIG_SYSFS
-#error "MVP requires sysfs support (CONFIG_SYSFS)"
-#endif
-
-/* network traffic isolation */
-#ifndef CONFIG_NAMESPACES
-#error "MVP networking support requires namespace support (CONFIG_NAMESPACES)"
-#endif
-#ifndef CONFIG_NET_NS
-#error "MVP networking support requires Network Namespace support to be enabled (CONFIG_NET_NS)"
-#endif
-
-/* TCP/IP networking */
-#ifndef CONFIG_INET
-#error "MVP networking requires IPv4 support (CONFIG_INET)"
-#endif
-#ifndef CONFIG_IPV6
-#error "MVP networking requires IPv6 support (CONFIG_IPV6)"
-#endif
-
-/* VPN support */
-#if !defined(CONFIG_TUN) && !defined(CONFIG_TUN_MODULE)
-#error "MVP VPN support requires TUN device support (CONFIG_TUN)"
-#endif
-
-#if !defined(CONFIG_NETFILTER) && !defined(PVTCP_DISABLE_NETFILTER)
-#error "MVP networking support requires netfilter support (CONFIG_NETFILTER)"
-#endif
-
-/* Force /proc/config.gz support for eng/userdebug builds */
-#ifdef MVP_DEBUG
-#if !defined(CONFIG_IKCONFIG) || !defined(CONFIG_IKCONFIG_PROC)
-#error "MVP kernel /proc/config.gz support required for debuggability (CONFIG_IKCONFIG_PROC)"
-#endif
-#endif
-
-/* Sanity check we're only dealing with the memory hotplug + migrate and/or
- * compaction combo */
-#ifdef CONFIG_MIGRATION
-#if defined(CONFIG_NUMA) || defined(CONFIG_CPUSETS) || defined(CONFIG_MEMORY_FAILURE)
-#error "MVP not tested with migration features other than CONFIG_MEMORY_HOTPLUG and CONFIG_COMPACTION"
-#endif
-#endif
diff --git a/arch/arm/mvp/pvtcpkm/comm.h b/arch/arm/mvp/pvtcpkm/comm.h
deleted file mode 100644
index 877731d..0000000
--- a/arch/arm/mvp/pvtcpkm/comm.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Communication functions based on queue pair transport APIs.
- *
- * Comm is a shared memory-based mechanism that facilitates the implementation
- * of kernel components that require host-to-guest, or guest-to-guest
- * communication.
- * This facility assumes the availability of a minimal shared memory queue pair
- * implementation, such as MVP queue pairs or VMCI queue pairs. The latter must
- * provide primitives for queue pair creation and destruction, and reading and
- * writing from/to queue pairs.
- * Comm assumes that the queue pair (transport) layer is not concerned with
- * multi-threading, locking or flow control, and does not require such features.
- */
-
-#ifndef _COMM_H_
-#define _COMM_H_
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "comm_os.h"
-#include "comm_transp.h"
-
-
-/* Default/maximum Comm timeouts (in milliseconds). */
-#define COMM_MAX_TO 60000ULL
-#define COMM_MAX_TO_UNINT (COMM_MAX_TO + 1)
-
-#define COMM_OPF_SET_ERR(flags) ((flags) |= 128)
-#define COMM_OPF_CLEAR_ERR(flags) ((flags) &= 127)
-#define COMM_OPF_TEST_ERR(flags) ((flags) & 128)
-
-#define COMM_OPF_SET_VAL(flags, val) ((flags) |= ((val) & 127))
-#define COMM_OPF_GET_VAL(flags) ((flags) & 127)
-
-/**
- * Packet (header) structure.
- * NB: Do not change this structure, especially the first three fields; there
- * will be consequences. It may be extended, but it's not recommended: all
- * operations carry this header, so it's better kept in its minimal form.
- */
-
-typedef struct CommPacket {
- unsigned int len; // Total length
- unsigned char flags; // Operation flags
- unsigned char opCode; // Operation to call
- unsigned short data16; // Auxiliary data
- unsigned long long data64;
- unsigned long long data64ex;
- union {
- struct {
- unsigned int data32;
- unsigned int data32ex;
- };
- unsigned long long data64ex2;
- };
-} CommPacket;
-
-
-/* Opaque structure representing a communication channel. */
-
-struct CommChannelPriv;
-typedef struct CommChannelPriv *CommChannel;
-
-
-/* Input operations associated with a comm channel. */
-
-typedef void (*CommOperationFunc)(CommChannel channel,
- void *state,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen);
-
-
-/* Helper macros */
-
-#define COMM_DEFINE_OP(funcName) \
-void \
-funcName(CommChannel channel, \
- void *state, \
- CommPacket *packet, \
- struct kvec *vec, \
- unsigned int vecLen)
-
-
-/* Comm-based implementations. */
-
-typedef struct CommImpl {
- struct module *owner;
- int (*checkArgs)(CommTranspInitArgs *transpArgs);
- void *(*stateCtor)(CommChannel channel);
- void (*stateDtor)(void *state);
- void *(*dataAlloc)(unsigned int dataLen);
- void (*dataFree)(void *data);
- const CommOperationFunc *operations;
- void (*closeNtf)(void *closeNtfData,
- const CommTranspInitArgs *transpArgs,
- int inBH);
- void *closeNtfData;
- void (*activateNtf)(void *activateNtfData,
- CommChannel channel);
- void *activateNtfData;
- unsigned long long openAtMillis;
- unsigned long long openTimeoutAtMillis;
- CommTranspID ntfCenterID;
-} CommImpl;
-
-
-int Comm_Init(unsigned int maxChannels);
-int Comm_Finish(unsigned long long *timeoutMillis);
-int Comm_RegisterImpl(const CommImpl *impl);
-void Comm_UnregisterImpl(const CommImpl *impl);
-int Comm_IsActive(CommChannel channel);
-CommTranspInitArgs Comm_GetTranspInitArgs(CommChannel channel);
-void *Comm_GetState(CommChannel channel);
-int Comm_Dispatch(CommChannel channel);
-unsigned int Comm_DispatchAll(void);
-void Comm_Put(CommChannel channel);
-void Comm_DispatchUnlock(CommChannel channel);
-int Comm_Lock(CommChannel channel);
-void Comm_Unlock(CommChannel channel);
-int Comm_Zombify(CommChannel channel, int inBH);
-
-int
-Comm_Alloc(const CommTranspInitArgs *transpArgs,
- const CommImpl *impl,
- int inBH,
- CommChannel *newChannel);
-
-
-int
-Comm_Write(CommChannel channel,
- const CommPacket *packet,
- unsigned long long *timeoutMillis);
-
-int
-Comm_WriteVec(CommChannel channel,
- const CommPacket *packet,
- struct kvec **vec,
- unsigned int *vecLen,
- unsigned long long *timeoutMillis,
- unsigned int *iovOffset);
-
-unsigned int Comm_RequestInlineEvents(CommChannel channel);
-unsigned int Comm_ReleaseInlineEvents(CommChannel channel);
-
-#endif // _COMM_H_
diff --git a/arch/arm/mvp/pvtcpkm/comm_os.h b/arch/arm/mvp/pvtcpkm/comm_os.h
deleted file mode 100644
index 91305f1..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_os.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Cross-platform base type definitions and function declarations.
- * Includes OS-specific base type definitions and function declarations.
- */
-
-#ifndef _COMM_OS_H_
-#define _COMM_OS_H_
-
-/* For-ever timeout constant (in milliseconds). */
-#define COMM_OS_4EVER_TO ((unsigned long long)(~0UL >> 1))
-
-/* Condition function prototype. Returns 1: true, 0: false, < 0: error code. */
-typedef int (*CommOSWaitConditionFunc)(void *arg1, void *arg2);
-
-/* Dispatch function prototype. Called by input (dispatch) kernel threads. */
-typedef unsigned int (*CommOSDispatchFunc)(void);
-
-/* Module initialization and exit callback functions. */
-extern int (*commOSModInit)(void *args);
-extern void (*commOSModExit)(void);
-
-/* Macro to assign Init and Exit callbacks. */
-#define COMM_OS_MOD_INIT(init, exit) \
- int (*commOSModInit)(void *args) = init; \
- void (*commOSModExit)(void) = exit
-
-
-/*
- * OS-specific implementations must provide the following:
- * 1. Types:
- * CommOSAtomic
- * CommOSSpinlock
- * CommOSMutex
- * CommOSWaitQueue
- * CommOSWork
- * CommOSWorkFunc
- * CommOSList
- * CommOSModule
- * struct kvec
- *
- * 2. Definition, initializers:
- * CommOSSpinlock_Define()
- *
- * 3. Functions:
- * void CommOS_Debug(const char *format, ...);
- * void CommOS_Log(const char *format, ...);
- * void CommOS_WriteAtomic(CommOSAtomic *atomic, int val);
- * int CommOS_ReadAtomic(CommOSAtomic *atomic);
- * int CommOS_AddReturnAtomic(CommOSAtomic *atomic, int val);
- * int CommOS_SubReturnAtomic(CommOSAtomic *atomic, int val);
- * void CommOS_SpinlockInit(CommOSSpinlock *lock);
- * void CommOS_SpinLockBH(CommOSSpinlock *lock);
- * int CommOS_SpinTrylockBH(CommOSSpinlock *lock);
- * void CommOS_SpinUnlockBH(CommOSSpinlock *lock);
- * void CommOS_SpinLock(CommOSSpinlock *lock);
- * int CommOS_SpinTrylock(CommOSSpinlock *lock);
- * void CommOS_SpinUnlock(CommOSSpinlock *lock);
- * void CommOS_MutexInit(CommOSMutex *mutex);
- * void CommOS_MutexLock(CommOSMutex *mutex);
- * int CommOS_MutexLockUninterruptible(CommOSMutex *mutex);
- * int CommOS_MutexTrylock(CommOSMutex *mutex);
- * void CommOS_MutexUnlock(CommOSMutex *mutex);
- * void CommOS_WaitQueueInit(CommOSWaitQueue *wq);
- * CommOS_DoWait(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc cond,
- * void *condArg1,
- * void *condArg2,
- * unsigned long long *timeoutMillis,
- * int interruptible);
- * int CommOS_Wait(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc func,
- * void *funcArg1,
- * void *funcArg2,
- * unsigned long long *timeoutMillis);
- * int CommOS_WaitUninterruptible(CommOSWaitQueue *wq,
- * CommOSWaitConditionFunc func,
- * void *funcArg1,
- * void *funcArg2,
- * unsigned long long *timeoutMillis);
- * void CommOS_WakeUp(CommOSWaitQueue *wq);
- * void *CommOS_KmallocNoSleep(unsigned int size);
- * void *CommOS_Kmalloc(unsigned int size);
- * void CommOS_Kfree(void *arg);
- * void CommOS_Yield(void);
- * unsigned long long CommOS_GetCurrentMillis(void);
- * void CommOS_ListInit(CommOSList *list);
- * int CommOS_ListEmpty(CommOSList *list);
- * void CommOS_ListAdd(CommOSList *list, CommOSList *listElem);
- * void CommOS_ListAddTail(CommOSList *list, CommOSList *listElem);
- * void int CommOS_ListDel(CommOSList *listElem);
- * Macros:
- * CommOS_ListForEach(*list, *item, itemListFieldName);
- * CommOS_ListForEachSafe(*list, *item, *tmp, itemListFieldName);
- * void CommOS_ListSplice(CommOSList *list, CommOSList *listToAdd);
- * void CommOS_ListSpliceTail(CommOSList *list, CommOSList *listToAdd);
- * CommOSModule CommOS_ModuleSelf(void);
- * int CommOS_ModuleGet(CommOSModule module);
- * void CommOS_ModulePut(CommOSModule module);
- * void CommOS_MemBarrier(void);
- *
- * These cannot be defined here: a) non-pointer type definitions need size
- * information, and b) functions may or may not be inlined, or macros may
- * be used instead.
- */
-
-
-#ifdef __linux__
-#include "comm_os_linux.h"
-#else
-#error "Unsupported OS"
-#endif
-
-/* Functions to start and stop the dispatch and aio kernel threads. */
-void CommOS_StopIO(void);
-void CommOS_ScheduleDisp(void);
-void CommOS_InitWork(CommOSWork *work, CommOSWorkFunc func);
-int CommOS_ScheduleAIOWork(CommOSWork *work);
-void CommOS_FlushAIOWork(CommOSWork *work);
-
-int
-CommOS_StartIO(const char *dispatchTaskName,
- CommOSDispatchFunc dispatchHandler,
- unsigned int interval,
- unsigned int maxCycles,
- const char *aioTaskName);
-
-
-#endif /* _COMM_OS_H_ */
diff --git a/arch/arm/mvp/pvtcpkm/comm_os_linux.c b/arch/arm/mvp/pvtcpkm/comm_os_linux.c
deleted file mode 100644
index 61ce929..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_os_linux.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Linux-specific functions/types.
- */
-
-#include "comm_os.h"
-
-#define DISPATCH_MAX_CYCLES 8192
-
-/* Type definitions */
-
-typedef struct workqueue_struct CommOSWorkQueue;
-
-
-/* Static data */
-
-static volatile int running;
-static int numCpus;
-static CommOSWorkQueue *dispatchWQ;
-static CommOSDispatchFunc dispatch;
-static CommOSWork dispatchWorksNow[NR_CPUS];
-static CommOSWork dispatchWorks[NR_CPUS];
-static unsigned int dispatchInterval = 1;
-static unsigned int dispatchMaxCycles = 2048;
-static CommOSWorkQueue *aioWQ;
-
-
-/**
- * @brief Initializes a workqueue consisting of per-cpu kernel threads.
- * @param name workqueue name
- * @return workqueue handle if successful, NULL otherwise
- */
-
-static inline CommOSWorkQueue *
-CreateWorkqueue(const char *name)
-{
- return create_workqueue(name);
-}
-
-
-/**
- * @brief Destroys a workqueue and stops its threads.
- * @param[in,out] wq workqueue to destroy.
- * @return workqueue handle is successful, NULL otherwise.
- */
-
-static inline void
-DestroyWorkqueue(CommOSWorkQueue *wq)
-{
- destroy_workqueue(wq);
-}
-
-
-/**
- * @brief Force execution of a work item.
- * @param[in,out] work work item to dequeue.
- */
-
-static inline void
-FlushDelayedWork(CommOSWork *work)
-{
- flush_delayed_work(work);
-}
-
-
-/**
- * @brief Enqueue a work item to a workqueue for execution on a given cpu
- * and after the specified interval.
- * @param cpu cpu number. If negative, work item is enqueued on current cpu.
- * @param[in,out] wq target work queue.
- * @param[in,out] work work item to enqueue.
- * @param jif delay interval.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-QueueDelayedWorkOn(int cpu,
- CommOSWorkQueue *wq,
- CommOSWork *work,
- unsigned long jif)
-{
- if (cpu < 0) {
- return !queue_delayed_work(wq, work, jif) ? -1 : 0;
- } else {
- return !queue_delayed_work_on(cpu, wq, work, jif) ? -1 : 0;
- }
-}
-
-
-/**
- * @brief Enqueues a work item to a workqueue for execution on the current cpu
- * and after the specified interval.
- * @param[in,out] wq target work queue.
- * @param[in,out] work work item to enqueue.
- * @param jif delay interval.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-QueueDelayedWork(CommOSWorkQueue *wq,
- CommOSWork *work,
- unsigned long jif)
-{
- return QueueDelayedWorkOn(-1, wq, work, jif);
-}
-
-
-/**
- * @brief Cancels a queued delayed work item and synchronizes with its
- * completion.
- * @param[in,out] work work item to cancel
- */
-
-static inline void
-WaitForDelayedWork(CommOSWork *work)
-{
- cancel_delayed_work_sync(work);
-}
-
-
-/**
- * @brief Discards work items queued to the specified workqueue.
- * @param[in,out] wq work queue to flush.
- */
-
-static inline void
-FlushWorkqueue(CommOSWorkQueue *wq)
-{
- flush_workqueue(wq);
-}
-
-
-/**
- * @brief Schedules dispatcher threads for immediate execution.
- */
-
-void
-CommOS_ScheduleDisp(void)
-{
- CommOSWork *work = &dispatchWorksNow[get_cpu()];
-
- put_cpu();
- if (running) {
- QueueDelayedWork(dispatchWQ, work, 0);
- }
-}
-
-
-/**
- * @brief Default delayed work callback function implementation.
- * Calls the input function specified at initialization.
- * @param[in,out] work work item.
- */
-
-static void
-DispatchWrapper(CommOSWork *work)
-{
- unsigned int misses;
-
- for (misses = 0; running && (misses < dispatchMaxCycles); ) {
- /* We run for at most dispatchMaxCycles worth of channel no-ops. */
-
- if (!dispatch()) {
- /* No useful work was done, on any of the channels. */
-
- misses++;
- if ((misses % 32) == 0) {
- CommOS_Yield();
- }
- } else {
- misses = 0;
- }
- }
-
- if (running &&
- (work >= &dispatchWorks[0]) &&
- (work <= &dispatchWorks[NR_CPUS - 1])) {
- /*
- * If still running _and_ this was a regular, time-based run, then
- * re-arm the timer.
- */
-
- QueueDelayedWork(dispatchWQ, work, dispatchInterval);
- }
-}
-
-
-/**
- * @brief Initializes work item with specified callback function.
- * @param[in,out] work work queue to initialize.
- * @param func work item to initialize the queue with.
- */
-
-void
-CommOS_InitWork(CommOSWork *work,
- CommOSWorkFunc func)
-{
- INIT_DELAYED_WORK(work, (work_func_t)func);
-}
-
-
-/**
- * @brief Flush execution of a work item
- * @param{in,out] work work item to dequeue
- */
-void
-CommOS_FlushAIOWork(CommOSWork *work)
-{
- if (aioWQ && work) {
- FlushDelayedWork(work);
- }
-}
-
-
-/**
- * @brief Queue a work item to the AIO workqueue.
- * @param[in,out] work work item to enqueue.
- * @return zero if work enqueued, non-zero otherwise.
- */
-
-int
-CommOS_ScheduleAIOWork(CommOSWork *work)
-{
- if (running && aioWQ && work) {
- return QueueDelayedWork(aioWQ, work, 0);
- }
- return -1;
-}
-
-
-/**
- * @brief Initializes the base IO system.
- * @param dispatchTaskName dispatch thread(s) name.
- * @param dispatchFunc dispatch function.
- * @param intervalMillis periodic interval in milliseconds to call dispatch.
- * The floor is 1 jiffy, regardless of how small intervalMillis is
- * @param maxCycles number of cycles to do adaptive polling before scheduling.
- * The maximum number of cycles is DISPATCH_MAX_CYCLES.
- * @param aioTaskName AIO thread(s) name. If NULL, AIO threads aren't started.
- * @return zero is successful, -1 otherwise.
- * @sideeffects Dispatch threads, and if applicable, AIO threads are started.
- */
-
-int
-CommOS_StartIO(const char *dispatchTaskName, // IN
- CommOSDispatchFunc dispatchFunc, // IN
- unsigned int intervalMillis, // IN
- unsigned int maxCycles, // IN
- const char *aioTaskName) // IN
-{
- int rc;
- int cpu;
-
- if (running) {
- CommOS_Debug(("%s: I/O tasks already running.\n", __FUNCTION__));
- return 0;
- }
-
- /*
- * OK, let's test the handler against NULL. Though, the whole concept
- * of checking for NULL pointers, outside cases where NULL is meaningful
- * to the implementation, is relatively useless: garbage, random pointers
- * rarely happen to be all-zeros.
- */
-
- if (!dispatchFunc) {
- CommOS_Log(("%s: a NULL Dispatch handler was passed.\n", __FUNCTION__));
- return -1;
- }
- dispatch = dispatchFunc;
-
- if (intervalMillis == 0) {
- intervalMillis = 4;
- }
- if ((dispatchInterval = msecs_to_jiffies(intervalMillis)) < 1) {
- dispatchInterval = 1;
- }
- if (maxCycles > DISPATCH_MAX_CYCLES) {
- dispatchMaxCycles = DISPATCH_MAX_CYCLES;
- } else if (maxCycles > 0) {
- dispatchMaxCycles = maxCycles;
- }
- CommOS_Debug(("%s: Interval millis %u (jif:%u).\n", __FUNCTION__,
- intervalMillis, dispatchInterval));
- CommOS_Debug(("%s: Max cycles %u.\n", __FUNCTION__, dispatchMaxCycles));
-
- numCpus = num_present_cpus();
- dispatchWQ = CreateWorkqueue(dispatchTaskName);
- if (!dispatchWQ) {
- CommOS_Log(("%s: Couldn't create %s task(s).\n", __FUNCTION__,
- dispatchTaskName));
- return -1;
- }
-
- if (aioTaskName) {
- aioWQ = CreateWorkqueue(aioTaskName);
- if (!aioWQ) {
- CommOS_Log(("%s: Couldn't create %s task(s).\n", __FUNCTION__,
- aioTaskName));
- DestroyWorkqueue(dispatchWQ);
- return -1;
- }
- } else {
- aioWQ = NULL;
- }
-
- running = 1;
- for (cpu = 0; cpu < numCpus; cpu++) {
- CommOS_InitWork(&dispatchWorksNow[cpu], DispatchWrapper);
- CommOS_InitWork(&dispatchWorks[cpu], DispatchWrapper);
- rc = QueueDelayedWorkOn(cpu, dispatchWQ,
- &dispatchWorks[cpu],
- dispatchInterval);
- if (rc != 0) {
- CommOS_StopIO();
- return -1;
- }
- }
- CommOS_Log(("%s: Created I/O task(s) successfully.\n", __FUNCTION__));
- return 0;
-}
-
-
-/**
- * @brief Stops the base IO system.
- * @sideeffects Dispatch threads, and if applicable, AIO threads are stopped.
- */
-
-void
-CommOS_StopIO(void)
-{
- int cpu;
-
- if (running) {
- running = 0;
- if (aioWQ) {
- FlushWorkqueue(aioWQ);
- DestroyWorkqueue(aioWQ);
- aioWQ = NULL;
- }
- FlushWorkqueue(dispatchWQ);
- for (cpu = 0; cpu < numCpus; cpu++) {
- WaitForDelayedWork(&dispatchWorksNow[cpu]);
- WaitForDelayedWork(&dispatchWorks[cpu]);
- }
- DestroyWorkqueue(dispatchWQ);
- dispatchWQ = NULL;
- CommOS_Log(("%s: I/O tasks stopped.\n", __FUNCTION__));
- }
-}
diff --git a/arch/arm/mvp/pvtcpkm/comm_os_linux.h b/arch/arm/mvp/pvtcpkm/comm_os_linux.h
deleted file mode 100644
index 81ee9d1..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_os_linux.h
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Contains linux-specific type definitions and function declarations
- */
-
-#ifndef _COMM_OS_LINUX_H_
-#define _COMM_OS_LINUX_H_
-
-#include <linux/types.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-#error "Kernel versions lower than 2.6.20 are not supported"
-#endif
-
-#include <linux/kernel.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-
-/*
- * Type definitions.
- */
-
-typedef atomic_t CommOSAtomic;
-typedef spinlock_t CommOSSpinlock;
-typedef struct mutex CommOSMutex;
-typedef wait_queue_head_t CommOSWaitQueue;
-typedef struct delayed_work CommOSWork;
-typedef void (*CommOSWorkFunc)(CommOSWork *work);
-typedef struct list_head CommOSList;
-typedef struct module *CommOSModule;
-
-
-/*
- * Initializers.
- */
-
-#define CommOSSpinlock_Define DEFINE_SPINLOCK
-
-
-#define COMM_OS_DOLOG(...) printk(KERN_INFO __VA_ARGS__)
-
-
-/**
- * @brief Logs given arguments in debug builds.
- */
-
-#if defined(COMM_OS_DEBUG)
- #define CommOS_Debug(args) COMM_OS_DOLOG args
-#else
- #define CommOS_Debug(args)
-#endif
-
-
-/**
- * @brief Logs given arguments.
- */
-
-#define CommOS_Log(args) COMM_OS_DOLOG args
-
-
-/**
- * @brief Logs function name and location.
- */
-
-#if defined(COMM_OS_TRACE)
-#define TRACE(ptr) \
- do { \
- CommOS_Debug(("%p:%s: at [%s:%d] with arg ptr [0x%p].\n", current, \
- __FUNCTION__, __FILE__, __LINE__, (ptr))); \
- } while (0)
-#else
-#define TRACE(ptr)
-#endif
-
-
-/**
- * @brief Write atomic variable
- * @param[in,out] atomic variable to write
- * @param val new value
- */
-
-static inline void
-CommOS_WriteAtomic(CommOSAtomic *atomic,
- int val)
-{
- atomic_set(atomic, val);
-}
-
-
-/**
- * @brief Reads atomic variable
- * @param atomic variable to read
- * @return value
- */
-
-static inline int
-CommOS_ReadAtomic(CommOSAtomic *atomic)
-{
- return atomic_read(atomic);
-}
-
-
-/**
- * @brief Atomically add value to atomic variable, return new value.
- * @param[in,out] atomic variable
- * @param val value to add
- * @return new value
- */
-
-static inline int
-CommOS_AddReturnAtomic(CommOSAtomic *atomic,
- int val)
-{
- return atomic_add_return(val, atomic);
-}
-
-
-/**
- * @brief Atomically substract value from atomic variable, return new value.
- * @param[in,out] atomic variable
- * @param val value to substract
- * @return new value
- */
-
-static inline int
-CommOS_SubReturnAtomic(CommOSAtomic *atomic,
- int val)
-{
- return atomic_sub_return(val, atomic);
-}
-
-
-/**
- * @brief Initializes a given lock.
- * @param[in,out] lock lock to initialize
- */
-
-static inline void
-CommOS_SpinlockInit(CommOSSpinlock *lock)
-{
- spin_lock_init(lock);
-}
-
-
-/**
- * @brief Locks given lock and disables bottom half processing.
- * @param[in,out] lock lock to lock
- */
-
-static inline void
-CommOS_SpinLockBH(CommOSSpinlock *lock)
-{
- spin_lock_bh(lock);
-}
-
-
-/**
- * @brief Attempts to lock the given lock and disable BH processing.
- * @param[in,out] lock lock to lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_SpinTrylockBH(CommOSSpinlock *lock)
-{
- return !spin_trylock_bh(lock);
-}
-
-
-/**
- * @brief Unlocks given lock and re-enables BH processing.
- * @param[in,out] lock lock to unlock
- */
-
-static inline void
-CommOS_SpinUnlockBH(CommOSSpinlock *lock)
-{
- spin_unlock_bh(lock);
-}
-
-
-/**
- * @brief Locks the given lock.
- * @param[in,out] lock lock to lock
- */
-
-static inline void
-CommOS_SpinLock(CommOSSpinlock *lock)
-{
- spin_lock(lock);
-}
-
-
-/**
- * @brief Attempts to lock the given lock.
- * @param[in,out] lock lock to try-lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_SpinTrylock(CommOSSpinlock *lock)
-{
- return !spin_trylock(lock);
-}
-
-
-/**
- * @brief Unlocks given lock.
- * @param[in,out] lock lock to unlock
- */
-
-static inline void
-CommOS_SpinUnlock(CommOSSpinlock *lock)
-{
- spin_unlock(lock);
-}
-
-
-/**
- * @brief Initializes given mutex.
- * @param[in,out] mutex mutex to initialize
- */
-
-static inline void
-CommOS_MutexInit(CommOSMutex *mutex)
-{
- mutex_init(mutex);
-}
-
-
-/**
- * @brief Acquires mutex.
- * @param[in,out] mutex mutex to lock
- * @return zero if successful, non-zero otherwise (interrupted)
- */
-
-static inline int
-CommOS_MutexLock(CommOSMutex *mutex)
-{
- return mutex_lock_interruptible(mutex);
-}
-
-
-/**
- * @brief Acquires mutex in uninterruptible mode.
- * @param[in,out] mutex mutex to lock
- */
-
-static inline void
-CommOS_MutexLockUninterruptible(CommOSMutex *mutex)
-{
- mutex_lock(mutex);
-}
-
-
-/**
- * @brief Attempts to acquire given mutex.
- * @param[in,out] mutex mutex to try-lock
- * @return zero if successful, non-zero otherwise
- */
-
-static inline int
-CommOS_MutexTrylock(CommOSMutex *mutex)
-{
- return !mutex_trylock(mutex);
-}
-
-
-/**
- * @brief Releases a given mutex.
- * @param[in,out] mutex mutex to unlock
- */
-
-static inline void
-CommOS_MutexUnlock(CommOSMutex *mutex)
-{
- mutex_unlock(mutex);
-}
-
-
-/**
- * @brief Initializes a wait queue.
- * @param[in,out] wq workqueue to initialize
- */
-
-static inline void
-CommOS_WaitQueueInit(CommOSWaitQueue *wq)
-{
- init_waitqueue_head(wq);
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * - a signal is pending
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @param interruptible enable/disable signal pending check
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, if a signal is pending or other error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_DoWait(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis,
- int interruptible)
-{
- int rc;
- DEFINE_WAIT(wait);
- long timeout;
-#if defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- long tmpTimeout;
- long retTimeout;
- const unsigned int interval = 50;
-#endif
-
- if (!timeoutMillis) {
- return -1;
- }
- if ((rc = cond(condArg1, condArg2)) != 0) {
- return rc;
- }
-
-#if defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- timeout = msecs_to_jiffies(interval < *timeoutMillis ?
- interval : (unsigned int)*timeoutMillis);
- retTimeout = msecs_to_jiffies((unsigned int)(*timeoutMillis));
-
- for (; retTimeout >= 0; ) {
- prepare_to_wait(wq, &wait,
- (interruptible?TASK_INTERRUPTIBLE:TASK_UNINTERRUPTIBLE));
- if ((rc = cond(condArg1, condArg2))) {
- break;
- }
- if (interruptible && signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if ((tmpTimeout = schedule_timeout(timeout))) {
- retTimeout -= (timeout - tmpTimeout);
- } else {
- retTimeout -= timeout;
- }
- if (retTimeout < 0) {
- retTimeout = 0;
- }
- }
- finish_wait(wq, &wait);
- if (rc == 0) {
- rc = cond(condArg1, condArg2);
- if (rc && (retTimeout == 0)) {
- retTimeout = 1;
- }
- }
- *timeoutMillis = (unsigned long long)jiffies_to_msecs(retTimeout);
-#else // !defined(COMM_OS_LINUX_WAIT_WORKAROUND)
- timeout = msecs_to_jiffies((unsigned int)(*timeoutMillis));
-
- for (;;) {
- prepare_to_wait(wq, &wait,
- (interruptible?TASK_INTERRUPTIBLE:TASK_UNINTERRUPTIBLE));
- if ((rc = cond(condArg1, condArg2)) != 0) {
- break;
- }
- if (interruptible && signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if ((timeout = schedule_timeout(timeout)) == 0) {
- rc = 0;
- break;
- }
- }
- finish_wait(wq, &wait);
- if (rc == 0) {
- rc = cond(condArg1, condArg2);
- if (rc && (timeout == 0)) {
- timeout = 1;
- }
- }
- *timeoutMillis = (unsigned long long)jiffies_to_msecs(timeout);
-#endif
-
- return rc;
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * - a signal is pending
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, if a signal is pending or other error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_Wait(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis)
-{
- return CommOS_DoWait(wq, cond, condArg1, condArg2, timeoutMillis, 1);
-}
-
-
-/**
- * @brief Puts the caller on a wait queue until either of the following occurs:
- * - the condition function (predicate) evaluates to TRUE
- * - the specified timeout interval elapsed
- * @param[in,out] wq wait queue to put item on
- * @param cond predicate to test
- * @param condArg1 argument 1 for cond
- * @param condArg2 argument 2 for cond
- * @param[in,out] timeoutMillis timeout interval in milliseconds
- * @return 1 if condition was met
- * 0 if the timeout interval elapsed
- * <0, error set by condition
- * @sideeffect timeoutMillis is updated to time remaining
- */
-
-static inline int
-CommOS_WaitUninterruptible(CommOSWaitQueue *wq,
- CommOSWaitConditionFunc cond,
- void *condArg1,
- void *condArg2,
- unsigned long long *timeoutMillis)
-{
- return CommOS_DoWait(wq, cond, condArg1, condArg2, timeoutMillis, 0);
-}
-
-
-/**
- * @brief Wakes up task(s) waiting on the given wait queue.
- * @param[in,out] wq wait queue.
- */
-
-static inline void
-CommOS_WakeUp(CommOSWaitQueue *wq)
-{
- wake_up(wq);
-}
-
-
-/**
- * @brief Allocates kernel memory of specified size; does not sleep.
- * @param size size to allocate.
- * @return Address of allocated memory or NULL if the allocation fails.
- */
-
-static inline void *
-CommOS_KmallocNoSleep(unsigned int size)
-{
- return kmalloc(size, GFP_ATOMIC);
-}
-
-
-/**
- * @brief Allocates kernel memory of specified size; may sleep.
- * @param size size to allocate.
- * @return Address of allocated memory or NULL if the allocation fails.
- */
-
-static inline void *
-CommOS_Kmalloc(unsigned int size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-
-/**
- * @brief Frees previously allocated kernel memory.
- * @param obj object to free.
- */
-
-static inline void
-CommOS_Kfree(void *obj)
-{
- if (obj) {
- kfree(obj);
- }
-}
-
-
-/**
- * @brief Yields the current cpu to other runnable tasks.
- */
-
-static inline void
-CommOS_Yield(void)
-{
- cond_resched();
-}
-
-
-/**
- * @brief Gets the current time in milliseconds.
- * @return Current time in milliseconds, with precision of at most one tick.
- */
-
-static inline unsigned long long
-CommOS_GetCurrentMillis(void)
-{
- return (unsigned long long)jiffies_to_msecs(jiffies);
-}
-
-
-/**
- * @brief Initializes given list.
- * @param list list to initialize.
- */
-
-static inline void
-CommOS_ListInit(CommOSList *list)
-{
- INIT_LIST_HEAD(list);
-}
-
-
-/**
- * @brief Tests if list is empty.
- * @param list list to test.
- * @return non-zero if empty, zero otherwise.
- */
-
-#define CommOS_ListEmpty(list) list_empty((list))
-
-
-/**
- * @brief Adds given element to beginning of list.
- * @param list list to add to.
- * @param elem element to add.
- */
-
-#define CommOS_ListAdd(list, elem) list_add((elem), (list))
-
-
-/**
- * @brief Adds given element to end of list.
- * @param list list to add to.
- * @param elem element to add.
- */
-
-#define CommOS_ListAddTail(list, elem) list_add_tail((elem), (list))
-
-
-/**
- * @brief Deletes given element from its list.
- * @param elem element to delete.
- */
-
-#define CommOS_ListDel(elem) \
- do { \
- list_del((elem)); \
- INIT_LIST_HEAD((elem)); \
- } while (0)
-
-
-/**
- * @brief Iterates over a list.
- * @param list list to iterate over.
- * @param[out] item stores next element.
- * @param itemListFieldName name in the item structure storing the list head.
- */
-
-#define CommOS_ListForEach(list, item, itemListFieldName) \
- list_for_each_entry((item), (list), itemListFieldName)
-
-
-/**
- * @brief Iterates safely over a list.
- * @param list list to iterate over.
- * @param[out] item stores next element. May be deleted in the loop.
- * @param[out] tmpItem saves iteration element.
- * @param itemListFieldName name in the item structure storing the list head.
- */
-
-#define CommOS_ListForEachSafe(list, item, tmpItem, itemListFieldName) \
- list_for_each_entry_safe((item), (tmpItem), (list), itemListFieldName)
-
-
-/**
- * @brief Combines two lists, adds second list to beginning of first one.
- * @param list list to add to.
- * @param list2 list to add.
- */
-
-#define CommOS_ListSplice(list, list2) list_splice((list2), (list))
-
-
-/**
- * @brief Combines two lists, adds second list to end of first one.
- * @param list list to add to.
- * @param list2 list to add.
- */
-
-#define CommOS_ListSpliceTail(list, list2) list_splice_tail((list2), (list))
-
-
-/**
- * @brief Gets current module handle.
- * @return module handle.
- */
-
-static inline CommOSModule
-CommOS_ModuleSelf(void)
-{
- return THIS_MODULE;
-}
-
-
-/**
- * @brief Retains module.
- * @param[in,out] module to retain.
- * @return zero if successful, non-zero otherwise.
- */
-
-static inline int
-CommOS_ModuleGet(CommOSModule module)
-{
- int rc = 0;
-
- if (!module) {
- goto out;
- }
- if (!try_module_get(module)) {
- rc = -1;
- }
-
-out:
- return rc;
-}
-
-
-/**
- * @brief Releases module.
- * @param[in,out] module to release.
- */
-
-static inline void
-CommOS_ModulePut(CommOSModule module)
-{
- if (module) {
- module_put(module);
- }
-}
-
-
-/**
- * @brief Inserts r/w memory barrier.
- */
-
-#define CommOS_MemBarrier smp_mb
-
-#endif /* _COMM_OS_LINUX_H_ */
diff --git a/arch/arm/mvp/pvtcpkm/comm_os_mod_linux.c b/arch/arm/mvp/pvtcpkm/comm_os_mod_linux.c
deleted file mode 100644
index e196108..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_os_mod_linux.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Linux-specific module loading, unloading functions.
- */
-
-#include "comm_os.h"
-#include "comm_os_mod_ver.h"
-
-#include <linux/moduleparam.h>
-
-
-/* Module parameters -- passed as one 'name=value'-list string. */
-
-static char modParams[256];
-module_param_string(COMM_OS_MOD_SHORT_NAME, modParams, sizeof modParams, 0644);
-
-
-/**
- * @brief Module initialization entry point. Calls the commOSModInit
- * function pointer to perform upper layer initialization.
- * @return zero if successful, non-zero otherwise.
- */
-
-static int __init
-ModInit(void)
-{
- int rc;
-
- if (!commOSModInit) {
- CommOS_Log(("%s: Can't find \'init\' function for module \'" \
- COMM_OS_MOD_SHORT_NAME_STRING "\'.\n", __FUNCTION__));
- return -1;
- }
-
- CommOS_Debug(("%s: Module parameters: [%s].\n", __FUNCTION__, modParams));
-
- rc = (*commOSModInit)(modParams);
- if (rc == 0) {
- CommOS_Log(("%s: Module \'" COMM_OS_MOD_SHORT_NAME_STRING \
- "\' has been successfully initialized.\n", __FUNCTION__));
- } else {
- CommOS_Log(("%s: Module \'" COMM_OS_MOD_SHORT_NAME_STRING \
- "\' could not be initialized [%d].\n", __FUNCTION__, rc));
- }
-
- return rc > 0 ? -rc : rc;
-}
-
-
-/**
- * @brief Module exit function. Calls the commOSModExit function pointer
- * to perform upper layer cleanup.
- */
-
-static void __exit
-ModExit(void)
-{
- if (!commOSModExit) {
- CommOS_Log(("%s: Can't find \'fini\' function for module \'" \
- COMM_OS_MOD_SHORT_NAME_STRING "\'.\n", __FUNCTION__));
- return;
- }
-
- (*commOSModExit)();
- CommOS_Log(("%s: Module \'" COMM_OS_MOD_SHORT_NAME_STRING \
- "\' has been stopped.\n", __FUNCTION__));
-}
-
-
-module_init(ModInit);
-module_exit(ModExit);
-
-/* Module information. */
-MODULE_AUTHOR("VMware, Inc.");
-MODULE_DESCRIPTION(COMM_OS_MOD_NAME_STRING);
-MODULE_VERSION(COMM_OS_MOD_VERSION_STRING);
-MODULE_LICENSE("GPL v2");
-/*
- * Starting with SLE10sp2, Novell requires that IHVs sign a support agreement
- * with them and mark their kernel modules as externally supported via a
- * change to the module header. If this isn't done, the module will not load
- * by default (i.e., neither mkinitrd nor modprobe will accept it).
- */
-MODULE_INFO(supported, "external");
diff --git a/arch/arm/mvp/pvtcpkm/comm_os_mod_ver.h b/arch/arm/mvp/pvtcpkm/comm_os_mod_ver.h
deleted file mode 100644
index 5e14c62..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_os_mod_ver.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Version definitions for the pvTCP module.
- */
-
-#ifndef _COMM_OS_MOD_VER_H_
-#define _COMM_OS_MOD_VER_H_
-
-#define COMM_OS_MOD_NAME_STRING "VMware paravirtualized tcp/ip module"
-#define COMM_OS_MOD_SHORT_NAME pvtcp
-#define COMM_OS_MOD_SHORT_NAME_STRING "pvtcp"
-
-#define COMM_OS_MOD_VERSION 1.0.0.0
-#define COMM_OS_MOD_VERSION_COMMAS 1,0,0,0
-#define COMM_OS_MOD_VERSION_STRING "1.0.0.0"
-
-#endif /* _COM_OS_MOD_VER_H_ */
diff --git a/arch/arm/mvp/pvtcpkm/comm_svc.h b/arch/arm/mvp/pvtcpkm/comm_svc.h
deleted file mode 100644
index 784ec76..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_svc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Communication functions exported by the comm_rt module.
- */
-
-#ifndef _COMM_SVC_H_
-#define _COMM_SVC_H_
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-#include "comm.h"
-
-int CommSvc_RegisterImpl(const CommImpl *impl);
-void CommSvc_UnregisterImpl(const CommImpl *impl);
-int CommSvc_Zombify(CommChannel channel, int inBH);
-int CommSvc_IsActive(CommChannel channel);
-CommTranspInitArgs CommSvc_GetTranspInitArgs(CommChannel channel);
-void *CommSvc_GetState(CommChannel channel);
-void CommSvc_Put(CommChannel channel);
-void CommSvc_DispatchUnlock(CommChannel channel);
-int CommSvc_Lock(CommChannel channel);
-void CommSvc_Unlock(CommChannel channel);
-int CommSvc_ScheduleAIOWork(CommOSWork *work);
-
-int
-CommSvc_Alloc(const CommTranspInitArgs *transpArgs,
- const CommImpl *impl,
- int inBH,
- CommChannel *newChannel);
-
-int
-CommSvc_Write(CommChannel channel,
- const CommPacket *packet,
- unsigned long long *timeoutMillis);
-
-int
-CommSvc_WriteVec(CommChannel channel,
- const CommPacket *packet,
- struct kvec **vec,
- unsigned int *vecLen,
- unsigned long long *timeoutMillis,
- unsigned int *iovOffset);
-
-unsigned int CommSvc_RequestInlineEvents(CommChannel channel);
-unsigned int CommSvc_ReleaseInlineEvents(CommChannel channel);
-
-#endif // _COMM_SVC_H_
diff --git a/arch/arm/mvp/pvtcpkm/comm_transp.h b/arch/arm/mvp/pvtcpkm/comm_transp.h
deleted file mode 100644
index c46f849..0000000
--- a/arch/arm/mvp/pvtcpkm/comm_transp.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Generic shared memory transport API.
- */
-
-#ifndef _COMM_TRANSP_H_
-#define _COMM_TRANSP_H_
-
-#define INCLUDE_ALLOW_PV
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_MONITOR
-#define INCLUDE_ALLOW_GPL
-#include "include_check.h"
-
-/*
- * Common shared memory identifier.
- * External handle that makes sense to both hypervisor and guest.
- */
-
-#define COMM_TRANSP_ID_8_ANY ((unsigned char)-1)
-#define COMM_TRANSP_ID_32_ANY ((unsigned int)-1)
-#define COMM_TRANSP_ID_64_ANY ((unsigned long long)-1)
-
-
-typedef struct CommTranspID {
- union {
- unsigned char d8[8];
- unsigned int d32[2];
- unsigned long long d64;
- };
-} CommTranspID;
-
-
-/* Basic initialization arguments. */
-
-typedef enum CommTranspInitMode {
- COMM_TRANSP_INIT_CREATE = 0x0,
- COMM_TRANSP_INIT_ATTACH = 0x1
-} CommTranspInitMode;
-
-typedef struct CommTranspInitArgs {
- unsigned int capacity; // Shared memory capacity.
- unsigned int type; // Type / implementation using this area.
- CommTranspID id; // ID (name) of shared memory area.
- CommTranspInitMode mode; // Init mode (above).
-} CommTranspInitArgs;
-
-
-/**
- * @brief Generate a type id from description (protocol) string. This function
- * uses djb2, a string hashing algorithm by Dan Bernstein.
- * (see http://www.cse.yorku.ca/~oz/hash.html)
- * @param str string to hash
- * @return 32-bit hash value
- */
-
-static inline unsigned int
-CommTransp_GetType(const char *str)
-{
- unsigned int hash = 5381;
- int c;
-
- while ((c = *str++)) {
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
- }
- return hash;
-}
-
-#endif // _COMM_TRANSP_H_
diff --git a/arch/arm/mvp/pvtcpkm/include_check.h b/arch/arm/mvp/pvtcpkm/include_check.h
deleted file mode 100644
index 2eeafe7..0000000
--- a/arch/arm/mvp/pvtcpkm/include_check.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for Empty File Placeholder
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp.c b/arch/arm/mvp/pvtcpkm/pvtcp.c
deleted file mode 100644
index fdfb0d2..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Pvtcp common code.
- */
-
-#include "pvtcp.h"
-
-
-/*
- * Operation table.
- */
-
-CommOperationFunc pvtcpOperations[] = {
- [PVTCP_OP_FLOW] = PvtcpFlowOp,
- [PVTCP_OP_IO] = PvtcpIoOp,
- [PVTCP_OP_CREATE] = PvtcpCreateOp,
- [PVTCP_OP_RELEASE] = PvtcpReleaseOp,
- [PVTCP_OP_BIND] = PvtcpBindOp,
- [PVTCP_OP_LISTEN] = PvtcpListenOp,
- [PVTCP_OP_ACCEPT] = PvtcpAcceptOp,
- [PVTCP_OP_CONNECT] = PvtcpConnectOp,
- [PVTCP_OP_SHUTDOWN] = PvtcpShutdownOp,
- [PVTCP_OP_SETSOCKOPT] = PvtcpSetSockOptOp,
- [PVTCP_OP_GETSOCKOPT] = PvtcpGetSockOptOp,
- [PVTCP_OP_IOCTL] = PvtcpIoctlOp,
- [PVTCP_OP_INVALID] = NULL
-};
-
-
-/*
- * Implementation block.
- */
-
-CommImpl pvtcpImpl = {
- .owner = NULL,
- .checkArgs = PvtcpCheckArgs,
- .stateCtor = PvtcpStateAlloc,
- .stateDtor = PvtcpStateFree,
- .dataAlloc = PvtcpBufAlloc,
- .dataFree = PvtcpBufFree,
- .operations = pvtcpOperations,
- .closeNtf = PvtcpCloseNtf,
- .closeNtfData = &pvtcpImpl,
- .ntfCenterID = {{
- .d32[0] = 2U /* x86 host context (vmci, only). */,
- .d32[1] = 10000 /* Default, not yet reserved, resource (vmci, only). */
- }}
-};
-
-
-/*
- * Version array.
- */
-
-const char *pvtcpVersions[] = {
- [PVTCP_VERS_1_1] = PVTCP_COMM_IMPL_VERS_1_1,
- [PVTCP_VERS_1_0] = PVTCP_COMM_IMPL_VERS_1_0
-};
-
-const unsigned int pvtcpVersionsSize =
- (sizeof pvtcpVersions / sizeof pvtcpVersions[0]);
-
-
-/*
- * Client (pv) channel to offload side. We choose to define it here, although
- * it's only applicable to the pv implementation. The reason is that we can
- * share a common close notification function which does the right thing
- * depending on the channel configuration.
- */
-
-CommChannel pvtcpClientChannel;
-
-
-/*
- * Built-in state interfaces.
- */
-
-static PvtcpIfConf ifUnbound = {
- .family = PVTCP_PF_UNBOUND
-};
-const PvtcpIfConf *pvtcpIfUnbound = &ifUnbound;
-
-static PvtcpIfConf ifDeathRow = {
- .family = PVTCP_PF_DEATH_ROW
-};
-const PvtcpIfConf *pvtcpIfDeathRow = &ifDeathRow;
-
-static PvtcpIfConf ifLoopbackInet4 = {
- .family = PVTCP_PF_LOOPBACK_INET4
-};
-const PvtcpIfConf *pvtcpIfLoopbackInet4 = &ifLoopbackInet4;
-
-
-/* Functions */
-
-/**
- * @brief Checks if the IF configuration has reasonable values.
- * @param conf configuration to check
- * @return zero if successful, -1 otherwise
- */
-
-static int
-IfCheck(const PvtcpIfConf *conf)
-{
- if (!conf ||
- ((conf->family != PF_INET) &&
- (conf->family != PF_INET6) &&
- (conf->family != PVTCP_PF_UNBOUND) &&
- (conf->family != PVTCP_PF_DEATH_ROW) &&
- (conf->family != PVTCP_PF_LOOPBACK_INET4))) {
- return -1;
- }
-
- /** @todo Need more checks for IP/netmask format validity. */
- return 0;
-}
-
-
-/**
- * @brief Checks if the IF has reasonable values, but restricts types to
- * AF_INET and AF_INET6
- * @param conf IF to check
- * @return zero if successful, -1 otherwise
- */
-
-static int
-IfRestrictedCheck(const PvtcpIfConf *conf)
-{
- if (IfCheck(conf) ||
- ((conf->family != PF_INET) &&
- (conf->family != PF_INET6))) {
- return -1;
- }
- return 0;
-}
-
-
-/**
- * @brief Finds a netif given a state and a configuration. The configuration
- * must have already been checked. This function doesn't lock, so it
- * should not be called when the state, or the netif for the passed
- * configuration may be deleted.
- * @param state state to look for.
- * @param conf configuration to look for.
- * @return netif matching configuration, or NULL.
- */
-
-PvtcpIf *
-PvtcpStateFindIf(PvtcpState *state,
- const PvtcpIfConf *conf)
-{
- PvtcpIf *netif;
-
- if (!state) {
- return NULL;
- }
-
- if (conf->family == PVTCP_PF_UNBOUND) {
- return &state->ifUnbound;
- }
-
- if (conf->family == PVTCP_PF_DEATH_ROW) {
- return &state->ifDeathRow;
- }
-
- if (conf->family == PVTCP_PF_LOOPBACK_INET4) {
- return &state->ifLoopbackInet4;
- }
-
- CommOS_ListForEach(&state->ifList, netif, stateLink) {
- if (netif->conf.family == conf->family) {
- if ((conf->family == PF_INET &&
- !memcmp(&netif->conf.addr.in, &conf->addr.in,
- sizeof conf->addr.in)) ||
- (conf->family == PF_INET6 &&
- !memcmp(&netif->conf.addr.in6, &conf->addr.in6,
- sizeof conf->addr.in6))) {
- return netif;
- }
- }
- }
- return NULL;
-}
-
-
-/**
- * @brief Creates and initializes a new netif for a given channel and with
- * the specified configuration. Death row and unbound netifs may not
- * be added using this function.
- * @param[in,out] channel channel to make a new netif in
- * @param conf configuration to set netif to
- * @return 0 if successful, -1 otherwise
- * @sideeffect May allocate memory
- */
-
-int
-PvtcpStateAddIf(CommChannel channel,
- const PvtcpIfConf *conf)
-{
- int rc = -1;
- PvtcpState *state;
- PvtcpIf *netif;
-
- if (!channel || IfRestrictedCheck(conf)) {
- return rc;
- }
-
- if (CommSvc_Lock(channel)) {
- return rc; /* channel isn't active. */
- }
-
- state = CommSvc_GetState(channel);
- if (!state) {
- goto out;
- }
-
- if (PvtcpStateFindIf(state, conf)) {
- goto out; /* Already configured. */
- }
-
- netif = CommOS_Kmalloc(sizeof *netif);
- if (!netif) {
- goto out;
- }
-
- INIT_LIST_HEAD(&netif->stateLink);
- INIT_LIST_HEAD(&netif->sockList);
- netif->state = state;
- netif->conf = *conf;
- CommOS_ListAddTail(&state->ifList, &netif->stateLink);
- rc = 0;
-
-out:
- CommSvc_Unlock(channel);
- return rc;
-}
-
-
-/**
- * @brief Removes and potentially deallocates all sockets associated with the
- * given netif and deallocates the latter.
- * @param[in,out] netif netif to deallocate
- * @sideeffect Closes sockets, deallocates memory
- */
-
-static void
-IfFree(PvtcpIf *netif)
-{
- PvtcpSock *pvsk;
- PvtcpSock *tmp;
-
- if (netif) {
- CommOS_ListForEachSafe(&netif->sockList, pvsk, tmp, ifLink) {
- CommOS_ListDel(&pvsk->ifLink);
- PvtcpReleaseSocket(pvsk);
- }
- if ((netif->conf.family != PVTCP_PF_UNBOUND) &&
- (netif->conf.family != PVTCP_PF_DEATH_ROW) &&
- (netif->conf.family != PVTCP_PF_LOOPBACK_INET4)) {
- CommOS_ListDel(&netif->stateLink);
- CommOS_Kfree(netif);
- }
- }
-}
-
-
-/**
- * @brief Closes all sockets associated with, and deallocates the netif
- * in the given channel and with the specified configuration.
- * Death row and unbound netifs may not be removed using this function.
- * @param[in,out] channel channel to remove from
- * @param conf configuration specified
- * @return zero if successful, error code otherwise
- * @sideeffect Closes sockets, deallocates memory
- */
-
-void
-PvtcpStateRemoveIf(CommChannel channel,
- const PvtcpIfConf *conf)
-{
- PvtcpState *state;
- PvtcpIf *netif;
-
- if (!channel || IfRestrictedCheck(conf)) {
- return;
- }
-
- if (CommSvc_Lock(channel)) {
- return; /* channel isn't active. */
- }
-
- state = CommSvc_GetState(channel);
- if (state && (netif = PvtcpStateFindIf(state, conf))) {
- if (netif->state == state) {
- IfFree(netif);
- }
- }
-
- CommSvc_Unlock(channel);
-}
-
-
-/**
- * @brief Adds a socket to an existing netif. If the socket is already on a
- * different netif, it is removed from that netif.
- * It locks the must-be-active channel. We use that lock to guard
- * against concurrent removal of the netif.
- * @param[in,out] channel channel to add to
- * @param conf specified configuration
- * @param[in,out] sock socket to add
- * @return zero if successful, -1 otherwise
- */
-
-int
-PvtcpStateAddSocket(CommChannel channel,
- const PvtcpIfConf *conf,
- PvtcpSock *sock)
-{
- int rc = -1;
- PvtcpState *state;
- PvtcpIf *netif;
-
- if (!channel || !sock || (sock->channel != channel) || IfCheck(conf)) {
- return rc;
- }
-
- if (CommSvc_Lock(channel)) {
- return rc; /* channel isn't active. */
- }
-
- state = CommSvc_GetState(channel);
- if (!state) {
- goto out;
- }
-
- netif = PvtcpStateFindIf(state, conf);
- if (!netif) {
- goto out;
- }
-
- CommOS_ListDel(&sock->ifLink);
- sock->netif = netif;
- CommOS_ListAddTail(&netif->sockList, &sock->ifLink);
- rc = 0;
-
-out:
- CommSvc_Unlock(channel);
- return rc;
-}
-
-
-/**
- * @brief Removes a socket from its netif.
- * It locks the must-be-active channel. We use that lock to guard
- * against concurrent removal of the netif.
- * @param[in,out] channel channel to remove from
- * @param[in,out] sock socket to remove
- * @return zero if successful, -1 otherwise
- */
-
-int
-PvtcpStateRemoveSocket(CommChannel channel,
- PvtcpSock *sock)
-{
- if (!channel || !sock ||
- (sock->channel && (sock->channel != channel))) {
- return -1;
- }
-
- if (CommSvc_Lock(channel)) {
- return -1; /* channel isn't active. */
- }
-
- CommOS_ListDel(&sock->ifLink);
- sock->channel = NULL;
- sock->state = NULL;
- sock->netif = NULL;
-
- CommSvc_Unlock(channel);
- return 0;
-}
-
-
-/**
- * @brief State constructor called when a channel is created. The netifs
- * 'death row' and 'unbound' are always initialized.
- * @param[in,out] channel channel to initialize
- * @return pointer to a new state structure or NULL
- * @sideeffect Allocates memory
- */
-
-void *
-PvtcpStateAlloc(CommChannel channel)
-{
- PvtcpState *state;
-
- state = CommOS_Kmalloc(sizeof *state);
- if (state) {
- state->channel = channel;
- INIT_LIST_HEAD(&state->ifList);
-
- /* Initialize always-present netifs. */
- INIT_LIST_HEAD(&state->ifDeathRow.stateLink); /* Irrelevant */
- INIT_LIST_HEAD(&state->ifDeathRow.sockList);
- state->ifDeathRow.state = state;
- state->ifDeathRow.conf.family = PVTCP_PF_DEATH_ROW;
-
- INIT_LIST_HEAD(&state->ifUnbound.stateLink); /* Irrelevant */
- INIT_LIST_HEAD(&state->ifUnbound.sockList);
- state->ifUnbound.state = state;
- state->ifUnbound.conf.family = PVTCP_PF_UNBOUND;
-
- INIT_LIST_HEAD(&state->ifLoopbackInet4.stateLink); /* Irrelevant */
- INIT_LIST_HEAD(&state->ifLoopbackInet4.sockList);
- state->ifLoopbackInet4.state = state;
- state->ifLoopbackInet4.conf.family = PVTCP_PF_LOOPBACK_INET4;
-
- state->namespace = NULL;
- state->mask = ((unsigned int)channel << 4) ^ (unsigned int)state;
-#if defined(__linux__)
- state->id = ((unsigned long long)random32() << 32) |
- (unsigned long long)random32();
-#else
- state->id = (unsigned long long)state;
-#endif
- }
- return state;
-}
-
-
-/**
- * @brief State destructor called when a channel is closed.
- * The caller (Comm) guarantees proper locking.
- * @param arg pointer to state structure
- * @sideeffect Destroys all netifs and their sockets, deallocates memory
- */
-
-void
-PvtcpStateFree(void *arg)
-{
- PvtcpState *state = arg;
- PvtcpIf *netif;
- PvtcpIf *tmp;
-
- if (state) {
- CommOS_ListForEachSafe(&state->ifList, netif, tmp, stateLink) {
- IfFree(netif);
- }
- /* coverity[address_free] */
- IfFree(&state->ifLoopbackInet4);
- /* coverity[address_free] */
- IfFree(&state->ifUnbound);
- /* coverity[address_free] */
- IfFree(&state->ifDeathRow);
- CommOS_Kfree(state);
- }
-}
-
-
-/**
- * @brief Checks transport arguments.
- * @param transpArgs transport arguments.
- * @return zero if successful, < 0 otherwise.
- */
-
-int
-PvtcpCheckArgs(CommTranspInitArgs *transpArgs)
-{
- int rc = -1;
- const unsigned int minCapacity =
- (PVTCP_SOCK_BUF_SIZE + sizeof(CommPacket)) * 2;
- unsigned int versionIndex = pvtcpVersionsSize;
-
- if (transpArgs->capacity < minCapacity) {
- return rc;
- }
-
- while (versionIndex--) {
- if (transpArgs->type == CommTransp_GetType(pvtcpVersions[versionIndex])) {
- /* If a match, overwrite the hash with the actual version (index). */
-
- transpArgs->type = versionIndex;
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
-
-
-/**
- * @brief Called after a channel is freed.
- * @param ntfData callback data from implementation block.
- * @param transpArgs transport arguments of closed channel.
- * @param inBH whether called in bottom half.
- */
-
-void
-PvtcpCloseNtf(void *ntfData,
- const CommTranspInitArgs *transpArgs,
- int inBH)
-{
- CommImpl *impl = (CommImpl *)ntfData;
-
- pvtcpClientChannel = NULL;
- CommOS_Log(("%s: Channel was reset!\n", __FUNCTION__));
-
- /*
- * If the impl. block owner is NULL, we're pv client: we attempt to
- * reopen the channel in a few seconds.
- */
-
- if (impl && !impl->owner && !inBH) {
- CommOS_Log(("%s: Attempting to re-initialize channel.\n", __FUNCTION__));
- impl->openAtMillis = CommOS_GetCurrentMillis();
- impl->openTimeoutAtMillis =
- CommOS_GetCurrentMillis() + PVTCP_CHANNEL_OPEN_TIMEOUT;
- if (CommSvc_Alloc(transpArgs, impl, inBH, &pvtcpClientChannel)) {
- CommOS_Log(("%s: Failed to initialize channel!\n", __FUNCTION__));
- }
- }
-}
-
-
-/**
- * @brief Initializes the Pvtcp socket common fields.
- * @param pvsk pvtcp socket.
- * @param channel Comm channel this socket is associated with.
- * @return 0 if successful, -1 otherwise.
- */
-
-int
-PvtcpSockInit(PvtcpSock *pvsk,
- CommChannel channel)
-{
- PvtcpState *state;
- int rc = -1;
-
- if (pvsk && channel && (state = CommSvc_GetState(channel))) {
- /* Must _not_ zero out pvsk! */
-
- CommOS_MutexInit(&pvsk->inLock);
- CommOS_MutexInit(&pvsk->outLock);
- CommOS_SpinlockInit(&pvsk->stateLock);
- CommOS_ListInit(&pvsk->ifLink);
- CommOS_InitWork(&pvsk->work, PvtcpProcessAIO);
- pvsk->netif = NULL;
- pvsk->state = state;
- pvsk->stateID = state->id;
- pvsk->channel = channel;
- pvsk->peerSock = PVTCP_PEER_SOCK_NULL;
- pvsk->peerSockSet = 0;
- CommOS_WriteAtomic(&pvsk->deltaAckSize,
- (1 << PVTCP_SOCK_SMALL_ACK_ORDER));
- CommOS_WriteAtomic(&pvsk->rcvdSize, 0);
- CommOS_WriteAtomic(&pvsk->sentSize, 0);
- CommOS_WriteAtomic(&pvsk->queueSize, 0);
- CommOS_ListInit(&pvsk->queue);
- pvsk->rpcReply = NULL;
- pvsk->rpcStatus = 0;
- pvsk->err = 0;
- rc = 0;
- }
- return rc;
-}
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp.h b/arch/arm/mvp/pvtcpkm/pvtcp.h
deleted file mode 100644
index 7f4f2f5..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp.h
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Pvtcp common APIs.
- */
-
-#ifndef _PVTCP_H_
-#define _PVTCP_H_
-
-/*
- * Pvtcp state store ipv4 and ipv6 address structures.
- * Platform-specific headers where these are defined, must be included here.
- * Implementation-related header files should not be included in this file.
- *
- * NOTE: Pvtcp is not an API and none of its functions are exported.
- */
-
-#if defined(__linux__)
-#include <linux/in.h>
-#include <linux/in6.h>
-#else
-#error "Unsupported OS."
-#endif
-
-#include "comm_svc.h"
-
-/* Max time to wait for a channel to be created. */
-#define PVTCP_CHANNEL_OPEN_TIMEOUT 2000
-
-/* Max payload size. Used to allocate offload per-cpu bounce buffers. */
-#define PVTCP_SOCK_BUF_SIZE (8 << 10) /* 8K */
-
-#define PVTCP_SOCK_DGRAM_BUF_SIZE PVTCP_SOCK_BUF_SIZE
-#define PVTCP_SOCK_STREAM_BUF_SIZE PVTCP_SOCK_BUF_SIZE
-
-/* Dgram payloads include a pseudo (udp/ip) header. */
-typedef struct PvtcpDgramPseudoHeader {
- unsigned long long d0;
- unsigned long long d1;
- unsigned long long d2;
- unsigned long long d3;
-} PvtcpDgramPseudoHeader;
-
-
-/*
- * Flow control constants for pv/offload sockets.
- * We are defining a receive size model: 1) small, 2) medium, 3)large.
- * This seems sufficient in addressing most target environments, but more
- * models may be defined. A smaller minimum model (1) cannot be defined.
- *
- * Short description of socket-level flow control. This applies to both
- * dgram and stream sockets, in both directions. It follows that, with regard
- * to 'comm' writes, dgram and stream writes are: a) lossless and b) ordered.
- *
- * 0. Both sides (offload, pv) of a socket maintain (almost) mirror values
- * of input/output queue sizes. We say 'almost', because they're allowed
- * to conservatively converge in time.
- * 1. Senders never write out to the shmem channel, and destined to a socket
- * (be it offload or pv), more bytes than that socket can hold/enqueue.
- * This is based on socket fields storing information mentioned above.
- * The upper limit is PVTCP_SOCK_RCVSIZE and cannot be exceeded under
- * any circumstances.
- * 2. There is a 'safe' limit value (per socket) which can be tested prior
- * to writing one more max-sized packet to that socket.
- * This value is PVTCP_SOCK_SAFE_RCVSIZE.
- * 3. There is also a notion of 'large' acks, which controls the frequency of
- * reporting socket queue size changes when bytes are consumed from it.
- * When a sender is about to write out (to the channel, for a given socket)
- * in excess of PVTCP_SOCK_LARGE_ACK_WM bytes, it sets, in the packet
- * header flag field, the PVTCP_SOCK_LARGE_ACK_ORDER value. The other end
- * updates its 'delta ack' value accordingly (1 << flag value).
- * 4. As bytes are consumed (again, at either end), the operation or function,
- * will send a size ack packet with the consumed size since the last ack,
- * _iff_ that size is larger than, or equal to the 'delta ack' value.
- * If an ack was sent, the 'delta ack' is decreased by half, to a minimum
- * indicated by PVTCP_SOCK_SMALL_ACK_ORDER.
- * Note that concurrently setting the 'delta ack' to its high value
- * because of condition 3) above, is fine since the sender already has,
- * or is about to put pressure on the socket.
- */
-
-#if !defined(PVTCP_SOCK_RCVSIZE_MODEL)
- #define PVTCP_SOCK_RCVSIZE_MODEL 1
-#endif
-
-#if PVTCP_SOCK_RCVSIZE_MODEL == 1
- #define PVTCP_SOCK_LARGE_ACK_WM (64 << 10) /* 64K */
- #define PVTCP_SOCK_LARGE_ACK_ORDER 15
- #define PVTCP_SOCK_SMALL_ACK_ORDER 11
- #define PVTCP_SOCK_SAFE_RCVSIZE (128 << 10) /* 128K */
-#elif PVTCP_SOCK_RCVSIZE_MODEL == 2
- #define PVTCP_SOCK_LARGE_ACK_WM (128 << 10) /* 128K */
- #define PVTCP_SOCK_LARGE_ACK_ORDER 16
- #define PVTCP_SOCK_SMALL_ACK_ORDER 12
- #define PVTCP_SOCK_SAFE_RCVSIZE (256 << 10) /* 256K */
-#elif PVTCP_SOCK_RCVSIZE_MODEL == 3
- #define PVTCP_SOCK_LARGE_ACK_WM (128 << 10) /* 128K */
- #define PVTCP_SOCK_LARGE_ACK_ORDER 16
- #define PVTCP_SOCK_SMALL_ACK_ORDER 12
- #define PVTCP_SOCK_SAFE_RCVSIZE (512 << 10) /* 512K */
-#else
- #error "Invalid PVTCP_SOCK_RCVSIZE_MODEL (one of 1, 2, 3)"
-#endif
-
-#define PVTCP_SOCK_RCVSIZE \
- (PVTCP_SOCK_SAFE_RCVSIZE + \
- PVTCP_SOCK_BUF_SIZE + sizeof (PvtcpDgramPseudoHeader))
-
-
-/*
- * Operation codes
- */
-
-enum PvtcpOpCodes {
- PVTCP_OP_FLOW = 0,
- PVTCP_OP_IO,
- PVTCP_OP_CREATE,
- PVTCP_OP_RELEASE,
- PVTCP_OP_BIND,
- PVTCP_OP_LISTEN,
- PVTCP_OP_ACCEPT,
- PVTCP_OP_CONNECT,
- PVTCP_OP_SHUTDOWN,
- PVTCP_OP_SETSOCKOPT,
- PVTCP_OP_GETSOCKOPT,
- PVTCP_OP_IOCTL,
- PVTCP_OP_INVALID
-};
-
-#define PVTCP_FLOW_OP_INVALID_SIZE 0xffffffff
-
-
-/*
- * Operation functions
- */
-
-COMM_DEFINE_OP(PvtcpFlowOp);
-COMM_DEFINE_OP(PvtcpIoOp);
-COMM_DEFINE_OP(PvtcpCreateOp);
-COMM_DEFINE_OP(PvtcpReleaseOp);
-COMM_DEFINE_OP(PvtcpBindOp);
-COMM_DEFINE_OP(PvtcpListenOp);
-COMM_DEFINE_OP(PvtcpAcceptOp);
-COMM_DEFINE_OP(PvtcpConnectOp);
-COMM_DEFINE_OP(PvtcpShutdownOp);
-COMM_DEFINE_OP(PvtcpSetSockOptOp);
-COMM_DEFINE_OP(PvtcpGetSockOptOp);
-COMM_DEFINE_OP(PvtcpIoctlOp);
-
-
-/*
- * Pvtcp/Comm type and supported versions.
- */
-
-#define PVTCP_COMM_IMPL_TYPE "com.vmware.comm.protocol.pvTCP@"
-
-#define PVTCP_COMM_IMPL_VERS_1_0 (PVTCP_COMM_IMPL_TYPE "1.0")
-#define PVTCP_COMM_IMPL_VERS_1_1 (PVTCP_COMM_IMPL_TYPE "1.1")
-
-typedef enum {
- PVTCP_VERS_1_0 = 0,
- PVTCP_VERS_1_1
-} PvtcpVersion;
-
-extern const char *pvtcpVersions[];
-extern const unsigned int pvtcpVersionsSize;
-
-
-/*
- * State interface markers
- */
-
-#define PVTCP_PF_UNBOUND 0x0
-#define PVTCP_PF_DEATH_ROW 0xffffffff
-#define PVTCP_PF_LOOPBACK_INET4 (PVTCP_PF_DEATH_ROW - 1)
-
-
-/*
- * Interface and interface configuration structures.
- */
-
-typedef struct PvtcpIfConf {
- int family; // Values:
- // unbound (PVTCP_PF_UNBOUND)
- // deathRow (PVTCP_PF_DEATH_ROW)
- // loopback (PVTCP_PF_LOOPBACK_INET4)
- // inet4 (PF_INET)
- // inet6 (PF_INET6)
- union {
- struct in_addr in;
- struct in6_addr in6;
- } addr; // inet4 or inet6 address.
- union {
- struct in_addr in;
- struct in6_addr in6;
- } mask; // inet4 or inet6 netmask.
-} PvtcpIfConf;
-
-
-struct PvtcpState;
-
-typedef struct PvtcpIf {
- CommOSList sockList; // List of sockets.
- CommOSList stateLink; // Link in PvtcpState.ifList.
- struct PvtcpState *state; // Back reference to state.
- PvtcpIfConf conf; // Interface configuration.
-} PvtcpIf;
-
-
-/*
- * General pvtcp state associated with a channel.
- */
-
-typedef struct PvtcpState {
- unsigned long long id; // Randomly generated state ID.
- CommOSList ifList; // List of active interfaces.
- CommChannel channel; // Comm channel back reference.
- PvtcpIf ifDeathRow; // Always-present netif.
- PvtcpIf ifUnbound; // Ditto.
- PvtcpIf ifLoopbackInet4; // Ditto.
- void *namespace; // Name space, where supported.
- void *extra; // Used by upper layer to extend state as needed.
- unsigned int mask; // Mask used to obfuscate socket pointers.
-} PvtcpState;
-
-
-/*
- * Define pvtcp socket common fields and include the pv or offload header
- * to get the right PvtcpSock definition.
- */
-
-#define PVTCP_SOCK_COMMON_FIELDS \
- CommOSMutex inLock; /* Input lock. */ \
- CommOSMutex outLock; /* Output lock. */ \
- CommOSSpinlock stateLock; /* State update lock. */ \
- CommOSList ifLink; /* Link in PvtcpIf.sockList. */ \
- CommOSWork work; /* Work item for AIO processing. */ \
- PvtcpIf *netif; /* Netif reference. */ \
- PvtcpState *state; /* State reference. */ \
- unsigned long long stateID; /* State ID. */ \
- CommChannel channel; /* Comm channel reference. */ \
- unsigned long long peerSock; /* Peer socket, opaque. */ \
- volatile int peerSockSet; /* Peer socket valid. */ \
- CommOSAtomic deltaAckSize; /* Recv size updates required by peer. */ \
- CommOSAtomic rcvdSize; /* Bytes received since last ack. */ \
- CommOSAtomic sentSize; /* Bytes sent; also updated by peer. */ \
- CommOSAtomic queueSize; /* Queue size. */ \
- CommOSList queue; /* Send queue (off) or recv queue (pv). */ \
- void *rpcReply; /* RPC reply. */ \
- int rpcStatus; /* RPC completion status. */ \
- int err /* Socket error. */
-
-#define PVTCP_PEER_SOCK_NULL ((unsigned long long)0)
-
-
-/*
- * Helper macros
- */
-
-#define SOCK_STATE_LOCK(pvsk) CommOS_SpinLock(&(pvsk)->stateLock)
-#define SOCK_STATE_UNLOCK(pvsk) CommOS_SpinUnlock(&(pvsk)->stateLock)
-
-#define SOCK_IN_TRYLOCK(pvsk) CommOS_MutexTrylock(&(pvsk)->inLock)
-#define SOCK_IN_LOCK(pvsk) CommOS_MutexLock(&(pvsk)->inLock)
-#define SOCK_IN_UNLOCK(pvsk) CommOS_MutexUnlock(&(pvsk)->inLock)
-
-#define SOCK_OUT_TRYLOCK(pvsk) CommOS_MutexTrylock(&(pvsk)->outLock)
-#define SOCK_OUT_LOCK(pvsk) CommOS_MutexLock(&(pvsk)->outLock)
-#define SOCK_OUT_LOCK_UNINT(pvsk) \
- CommOS_MutexLockUninterruptible(&(pvsk)->outLock)
-#define SOCK_OUT_UNLOCK(pvsk) CommOS_MutexUnlock(&(pvsk)->outLock)
-
-#define PVTCP_UNLOCK_DISP_DISCARD_VEC() \
- CommSvc_DispatchUnlock(channel); \
- while (vecLen) { \
- PvtcpBufFree(vec[--vecLen].iov_base); \
- }
-
-
-#if defined(PVTCP_BUILDING_SERVER)
-#include "pvtcp_off.h"
-#else
-#include "pvtcp_pv.h"
-#endif // defined(PVTCP_BUILDING_SERVER)
-
-
-/*
- * Data declarations
- */
-
-extern const PvtcpIfConf *pvtcpIfUnbound;
-extern const PvtcpIfConf *pvtcpIfDeathRow;
-extern const PvtcpIfConf *pvtcpIfLoopbackInet4;
-
-extern CommImpl pvtcpImpl;
-extern CommOperationFunc pvtcpOperations[];
-
-extern CommChannel pvtcpClientChannel;
-
-
-/*
- * Common state manipulation functions.
- */
-
-void *PvtcpStateAlloc(CommChannel channel);
-void PvtcpStateFree(void *arg);
-
-int PvtcpStateAddIf(CommChannel channel, const PvtcpIfConf *conf);
-void PvtcpStateRemoveIf(CommChannel channel, const PvtcpIfConf *conf);
-PvtcpIf *PvtcpStateFindIf(PvtcpState *state, const PvtcpIfConf *conf);
-
-int
-PvtcpStateAddSocket(CommChannel channel,
- const PvtcpIfConf *conf,
- PvtcpSock *sock);
-int PvtcpStateRemoveSocket(CommChannel channel, PvtcpSock *sock);
-
-
-/*
- * Common Pvtcp functions.
- */
-
-int PvtcpCheckArgs(CommTranspInitArgs *transpArgs);
-
-void
-PvtcpCloseNtf(void *ntfData,
- const CommTranspInitArgs *transpArgs,
- int inBH);
-
-void *PvtcpBufAlloc(unsigned int size);
-void PvtcpBufFree(void *buf);
-
-void PvtcpReleaseSocket(PvtcpSock *pvsk);
-int PvtcpSockInit(PvtcpSock *pvsk, CommChannel channel);
-
-void PvtcpProcessAIO(CommOSWork *work);
-
-
-/**
- * @brief Packs an IPV6 address stored in an array of four 32-bit elements,
- * into two 64-bit variables.
- * @param addr IPV6 address as an array of 32-bit elements.
- * @param[out] d64_0 pointer to 64-bit variable.
- * @param[out] d64_1 pointer to 64-bit variable.
- */
-
-static inline void
-PvtcpI6AddrPack(const unsigned int addr[4],
- unsigned long long *d64_0,
- unsigned long long *d64_1)
-{
- *d64_0 = *(unsigned long long *)&addr[0];
- *d64_1 = *(unsigned long long *)&addr[2];
-}
-
-
-/**
- * @brief Unpacks two 64-bit values into an IPV6 address-storing array of
- * four 32-bit elements,
- * @param[out] addr IPV6 address as an array of 32-bit elements.
- * @param d64_0 64-bit value.
- * @param d64_1 64-bit value.
- */
-
-static inline void
-PvtcpI6AddrUnpack(unsigned int addr[4],
- unsigned long long d64_0,
- unsigned long long d64_1)
-{
- *(unsigned long long *)&addr[0] = d64_0;
- *(unsigned long long *)&addr[2] = d64_1;
-}
-
-
-/**
- * @brief Verifies whether the argument is a valid socket. If yes, it returns
- * the actual pointer. Otherwise, it returns from the calling function.
- * WARNING: This macro must ONLY be used in operation functions, as its
- * implementation assumes.
- * @param handle socket handle to verify.
- * @param container state supposed to contain the socket handle.
- * @return 32-bit or 64-bit PvtcpSock*, depending on __LP64__ or __LLP64__.
- */
-
-#if defined(__LP64__) || defined(__LLP64__)
-
-#define PvtcpGetPvskOrReturn(handle, container) \
- ({ \
- PvtcpState *__state = (PvtcpState *)(container); \
- PvtcpSock *__pvsk = \
- (PvtcpSock *)((handle) ^ (unsigned long long)__state->mask); \
- \
- if (__pvsk->stateID != __state->id) { \
- PVTCP_UNLOCK_DISP_DISCARD_VEC(); \
- CommSvc_Zombify(__state->channel, 0); \
- return; \
- } \
- (__pvsk); \
- })
-
-#else // __LP64__ || __LLP64__
-
-#define PvtcpGetPvskOrReturn(handle, container) \
- ({ \
- PvtcpState *__state = (PvtcpState *)(container); \
- PvtcpSock *__pvsk = \
- (PvtcpSock *)((unsigned int)(handle) ^ __state->mask); \
- \
- if (__pvsk->stateID != __state->id) { \
- PVTCP_UNLOCK_DISP_DISCARD_VEC(); \
- CommSvc_Zombify(__state->channel, 0); \
- return; \
- } \
- (__pvsk); \
- })
-
-#endif // __LP64__ || __LLP64__
-
-
-/**
- * @brief Masks a socket pointer to be passed to the peer module.
- * @param pvsk socket pointer to mask.
- * @return 64-bit pvtcp socket handle.
- */
-
-#if defined(__LP64__) || defined(__LLP64__)
-
-#define PvtcpGetHandle(pvsk) \
- ((unsigned long long)(pvsk) ^ (unsigned long long)(pvsk)->state->mask)
-
-#else // __LP64__ || __LLP64__
-
-#define PvtcpGetHandle(pvsk) \
- ((unsigned int)(pvsk) ^ (pvsk)->state->mask)
-
-#endif // __LP64__ || __LLP64__
-
-#endif // _PVTCP_H_
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp_off.c b/arch/arm/mvp/pvtcpkm/pvtcp_off.c
deleted file mode 100644
index 053d9c2..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp_off.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Server (offload) side code.
- */
-
-#include "pvtcp.h"
-
-/**
- * @brief Allocates the net buffer.
- * @param size buffer size
- * @return address of buffer or NULL
- */
-void *
-PvtcpBufAlloc(unsigned int size)
-{
- PvtcpOffBuf *buf;
-
- /* coverity[alloc_fn] */
- /* coverity[var_assign] */
- buf = CommOS_Kmalloc(size + sizeof *buf - sizeof buf->data);
- if (buf) {
- CommOS_ListInit(&buf->link);
- buf->len = (unsigned short)size;
- buf->off = 0;
- return PvtcpOffBufFromInternal(buf);
- }
- return NULL;
-}
-
-
-/**
- * @brief Deallocates given net buffer.
- * @param buf buffer to deallocate
- * @sideeffect Frees memory
- */
-
-void
-PvtcpBufFree(void *buf)
-{
- CommOS_Kfree(PvtcpOffInternalFromBuf(buf));
-}
-
-
-/**
- * @brief Initializes the Pvtcp socket offload common fields.
- * @param pvsk pvtcp socket.
- * @param channel Comm channel this socket is associated with.
- * @return 0 if successful, -1 otherwise.
- */
-
-int
-PvtcpOffSockInit(PvtcpSock *pvsk,
- CommChannel channel)
-{
- int rc = PvtcpSockInit(pvsk, channel);
-
- pvsk->opFlags = 0;
- pvsk->flags = 0;
- return rc;
-}
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp_off.h b/arch/arm/mvp/pvtcpkm/pvtcp_off.h
deleted file mode 100644
index f183968..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp_off.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Offload common definitions.
- * This file is meant to only be included via pvtcp.h.
- */
-
-#ifndef _PVTCP_OFF_H_
-#define _PVTCP_OFF_H_
-
-
-#define PVTCP_OFF_SOCK_COMMON_FIELDS \
- volatile unsigned int opFlags; /* Saves op codes as bit mask. */ \
- volatile unsigned int flags /* General purpose flags. */
-
-
-/* General purpose socket flags */
-
-enum PvtcpOffPvskFlags {
- PVTCP_OFF_PVSKF_IPV6_LOOP = 0, /* Used for IPV6 loopback morphing/reset. */
- PVTCP_OFF_PVSKF_SHUT_RD, /* Set to initiate socket recv shutdown. */
- PVTCP_OFF_PVSKF_SHUT_WR, /* Set to initiate socket send shutdown. */
- PVTCP_OFF_PVSKF_TCP_NODELAY, /* Caches the TCP_NODELAY socket option. */
- PVTCP_OFF_PVSKF_TCP_CORK, /* Caches the TCP_CORK socket option. */
- PVTCP_OFF_PVSKF_DISCONNECT, /* Set do indicate connect()/AF_UNSPEC. */
- PVTCP_OFF_PVSKF_INVALID = 32
-};
-
-
-/*
- * Include OS-dependent PvtcpSock structure and functions.
- */
-
-#if defined(__linux__)
-#include "pvtcp_off_linux.h"
-#else
-#error "Unsupported OS."
-#endif
-
-
-/*
- * Offload packet payload data structure.
- */
-
-typedef struct PvtcpOffBuf {
- CommOSList link; // Link in socket queue.
- unsigned short len;
- unsigned short off;
- char data[1];
-} PvtcpOffBuf;
-
-
-/**
- * @brief Returns net buffer given private data structure pointer and based
- * on the internal offset pointer
- * @param arg pointer to PvtcpOffBuf wrapper structure
- * @return address of buffer or NULL
- */
-
-static inline void *
-PvtcpOffBufFromInternalOff(PvtcpOffBuf *arg)
-{
- return arg ?
- &arg->data[arg->off] :
- NULL;
-}
-
-
-/**
- * @brief Returns net buffer given private data structure pointer
- * @param arg pointer to PvtcpOffBuf wrapper structure
- * @return address of buffer or NULL
- */
-
-static inline void *
-PvtcpOffBufFromInternal(PvtcpOffBuf *arg)
-{
- return arg ?
- &arg->data[0] :
- NULL;
-}
-
-
-/**
- * @brief Returns internal data structure given net buffer pointer
- * @param arg pointer to PvtcpOffBuf wrapper structure
- * @return address of internal data structure or NULL
- */
-
-static inline PvtcpOffBuf *
-PvtcpOffInternalFromBuf(void *arg)
-{
- return arg ?
- (PvtcpOffBuf *)((char *)arg - offsetof(PvtcpOffBuf, data)) :
- NULL;
-}
-
-
-/**
- * @brief Tests operation flag for AIO processing.
- * @param pvsk socket to test operation on.
- * @param op operation to test if set.
- * @return non-zero if operation set, zero otherwise.
- * @sideeffect socket processing by AIO threads affected according to operation.
- */
-
-static inline int
-PvskTestOpFlag(struct PvtcpSock *pvsk,
- int op)
-{
- return pvsk->opFlags & (1 << op);
-}
-
-
-/**
- * @brief Sets operation flag for AIO processing; acquires the state lock.
- * @param[in,out] pvsk socket to set operation on.
- * @param op operation to set.
- * @sideeffect socket processing by AIO threads affected according to operation.
- */
-
-static inline void
-PvskSetOpFlag(struct PvtcpSock *pvsk,
- int op)
-{
- unsigned int ops;
-
- SOCK_STATE_LOCK(pvsk);
- ops = pvsk->opFlags | (1 << op);
- pvsk->opFlags = ops;
- SOCK_STATE_UNLOCK(pvsk);
-}
-
-
-/**
- * @brief Resets operation flag for AIO processing; acquires the state lock.
- * @param[in,out] pvsk socket to reset operation on.
- * @param op operation to reset.
- * @sideeffect socket processing by AIO threads affected according to operation.
- */
-
-static inline void
-PvskResetOpFlag(struct PvtcpSock *pvsk,
- int op)
-{
- unsigned int ops;
-
- SOCK_STATE_LOCK(pvsk);
- ops = pvsk->opFlags & ~(1 << op);
- pvsk->opFlags = ops;
- SOCK_STATE_UNLOCK(pvsk);
-}
-
-
-/**
- * @brief Tests general purpose socket flags.
- * @param pvsk socket.
- * @param flag flag to test.
- * @return non-zero if flag set, zero otherwise.
- */
-
-static inline int
-PvskTestFlag(struct PvtcpSock *pvsk,
- int flag)
-{
- return (flag < PVTCP_OFF_PVSKF_INVALID) && (pvsk->flags & (1 << flag));
-}
-
-
-/**
- * @brief Sets general purpose socket flags; acquires the state lock.
- * @param[in,out] pvsk socket.
- * @param flag flag to set or clear.
- * @param onOff whether to set or clear the flag.
- */
-
-static inline void
-PvskSetFlag(struct PvtcpSock *pvsk,
- int flag,
- int onOff)
-{
- unsigned int flags;
-
- SOCK_STATE_LOCK(pvsk);
- if (flag < PVTCP_OFF_PVSKF_INVALID) {
- if (onOff) {
- flags = pvsk->flags | (1 << flag);
- } else {
- flags = pvsk->flags & ~(1 << flag);
- }
- pvsk->flags = flags;
- }
- SOCK_STATE_UNLOCK(pvsk);
-}
-
-
-int PvtcpOffSockInit(PvtcpSock *pvsk, CommChannel channel);
-
-#endif // _PVTCP_OFF_H_
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp_off_io_linux.c b/arch/arm/mvp/pvtcpkm/pvtcp_off_io_linux.c
deleted file mode 100644
index 9958c39..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp_off_io_linux.c
+++ /dev/null
@@ -1,831 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Server (offload) side Linux-specific socket I/O functions.
- */
-
-#include "pvtcp.h"
-
-/*
- * Data.
- */
-
-/* Used to check if OutputAIO()-ing is likely in progress. */
-
-CommOSAtomic PvtcpOutputAIOSection;
-
-
-/*
- * Large datagram bounce buffer (PVTCP_SOCK_BUF_SIZE < size <= 64K).
- * Only one such buffer is available, shared across cpus via get/put.
- * A preallocated, smaller buffer is used for most over-size 'allocs'.
- * A larger, 64K-buffer may need to be __vmalloc()-ed.
- */
-
-typedef struct LargeDgramBuf {
- unsigned char buf[PVTCP_SOCK_BUF_SIZE << 1]; /* Fast buffer. */
- void *spareBuf; /* Dynamically allocated. */
- CommOSMutex lock;
-} LargeDgramBuf;
-
-static LargeDgramBuf largeDgramBuf;
-
-
-/**
- * @brief One time initialization of large datagram buffer.
- */
-
-void
-PvtcpOffLargeDgramBufInit(void)
-{
- largeDgramBuf.spareBuf = NULL;
- CommOS_MutexInit(&largeDgramBuf.lock);
-}
-
-
-/**
- * @brief Reserves/holds the large datagram buffer.
- * @param size size of buffer.
- * @sizeeffect may sleep until the buffer is available.
- * @return address of buffer, or NULL if size too large or allocation failed.
- */
-
-static inline void *
-LargeDgramBufGet(int size)
-{
- static const unsigned int maxSize = 64 * 1024;
-
- /* coverity[alloc_fn] */
- /* coverity[var_assign] */
-
- CommOS_MutexLockUninterruptible(&largeDgramBuf.lock);
-
- if (size <= sizeof largeDgramBuf.buf) {
- return largeDgramBuf.buf;
- }
-
- if (size <= maxSize) {
- if (!largeDgramBuf.spareBuf) {
- largeDgramBuf.spareBuf = __vmalloc(maxSize,
- (GFP_ATOMIC | __GFP_HIGHMEM),
- PAGE_KERNEL);
- }
- if (largeDgramBuf.spareBuf) {
- return largeDgramBuf.spareBuf;
- }
- }
-
- CommOS_MutexUnlock(&largeDgramBuf.lock);
- return NULL;
-}
-
-
-/**
- * @brief Releases hold on the large datagram buffer.
- * @param buf buffer to put back.
- */
-
-static inline void
-LargeDgramBufPut(void *buf)
-{
- static unsigned int spareBufPuts = 0;
-
- BUG_ON((buf != largeDgramBuf.buf) && (buf != largeDgramBuf.spareBuf));
-
- if (largeDgramBuf.spareBuf && (++spareBufPuts % 2) == 0) {
- /* Deallocate the spare buffer every now and then. */
-
- vfree(largeDgramBuf.spareBuf);
- largeDgramBuf.spareBuf = NULL;
- }
-
- CommOS_MutexUnlock(&largeDgramBuf.lock);
-}
-
-
-/*
- * I/O offload operations.
- */
-
-/**
- * @brief Flow control notification received when more (enough) data was
- * consumed from a PV socket.
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled
- */
-
-void
-PvtcpFlowOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
-
- PvtcpHoldSock(pvsk);
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
- CommOS_SubReturnAtomic(&pvsk->rcvdSize, (int)packet->data32);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Outputs bytes to socket.
- * @param channel communication channel with offloader.
- * @param upperLayerState state associated with this channel.
- * @param packet received packet header.
- * @param vec payload buffer descriptors.
- * @param vecLen payload buffer descriptor count.
- * @sideeffect Changes send size/capacity ratio. May schedule AIO processing
- * for enqueued bytes, if applicable.
- */
-
-void
-PvtcpIoOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- int rc;
- unsigned int vecOff;
- PvtcpOffBuf *internalBuf;
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- unsigned int dataLen = packet->len - sizeof *packet;
- struct msghdr msg = {
- .msg_controllen = 0,
- .msg_control = NULL
- };
- int tmpSize;
- int needSched = 0;
-
- PvtcpHoldSock(pvsk);
- rc = 0;
-
- if (!pvsk->peerSockSet || PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_WR)) {
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
- goto out;
- }
-
- tmpSize = (int)COMM_OPF_GET_VAL(packet->flags);
- if (tmpSize) {
- /* It was requested that we update deltaAckSize. */
-
- tmpSize = 1 << tmpSize;
- CommOS_WriteAtomic(&pvsk->deltaAckSize, tmpSize);
- }
-
- if (sk->sk_type == SOCK_STREAM) {
- unsigned int queueSize = 0;
-
- if (!SOCK_OUT_TRYLOCK(pvsk)) {
- if (pvsk->peerSockSet &&
- (sk->sk_state == TCP_ESTABLISHED) &&
- (CommOS_ReadAtomic(&pvsk->queueSize) == 0)) {
- /* Attempt to write directly as many bytes as we can. */
-
- msg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
- rc = kernel_sendmsg(sock, &msg, vec, vecLen, dataLen);
-
- if (rc == -EAGAIN) {
- rc = 0;
- }
- if (rc >= 0) {
- dataLen = rc;
- for (vecOff = 0; vecOff < vecLen; vecOff++) {
- if (rc >= vec[vecOff].iov_len) {
- /* Dispose of all fully consumed buffers. */
-
- PvtcpBufFree(vec[vecOff].iov_base);
- rc -= vec[vecOff].iov_len;
- } else {
- /* Place partly consumed / unconsumed buffers in queue. */
-
- internalBuf =
- PvtcpOffInternalFromBuf(vec[vecOff].iov_base);
- BUG_ON(internalBuf == NULL);
- if (rc > 0) {
- internalBuf->len -= rc;
- internalBuf->off += rc;
- rc = 0;
- }
- CommOS_ListAddTail(&pvsk->queue, &internalBuf->link);
- queueSize += internalBuf->len;
- }
- }
- if (queueSize > 0) {
- CommOS_AddReturnAtomic(&pvsk->queueSize, queueSize);
- needSched = 1;
- }
- } else {
- /*
- * We never close offload sockets unless told by the PV side,
- * or when the comm goes down. Getting out of sync with PV
- * sockets is a dangerously bad idea.
- * This is very likely an EPIPE/ECONNRESET.
- */
-
- dataLen = 0;
- for ( vecOff = 0; vecOff < vecLen; vecOff++) {
- PvtcpBufFree(vec[vecOff].iov_base);
- }
- }
- SOCK_OUT_UNLOCK(pvsk);
- } else {
- SOCK_OUT_UNLOCK(pvsk);
- goto enqueueBytes;
- }
- } else {
- /*
- * We enqueue the bytes for aio processing. Note that request
- * level ordering is preserved since we're still under the dispatch
- * lock. However, accessing 'queue' must be protected via
- * the state lock to serialize with aio changes.
- * Note that the struct socket *sock may have been released, but here
- * we only access sk which is held (albeit potentially orphaned).
- */
-
- CommOSList bufList;
-
-enqueueBytes:
- dataLen = 0;
- if (pvsk->peerSockSet && (sk->sk_state == TCP_ESTABLISHED)) {
- queueSize = 0;
- CommOS_ListInit(&bufList);
- for (vecOff = 0; vecOff < vecLen; vecOff++) {
- internalBuf = PvtcpOffInternalFromBuf(vec[vecOff].iov_base);
- BUG_ON(internalBuf == NULL);
- CommOS_ListAddTail(&bufList, &internalBuf->link);
- queueSize += internalBuf->len;
- }
-
- if (queueSize > 0) {
- SOCK_STATE_LOCK(pvsk);
- CommOS_ListSpliceTail(&pvsk->queue, &bufList);
- SOCK_STATE_UNLOCK(pvsk);
- CommOS_AddReturnAtomic(&pvsk->queueSize, queueSize);
- needSched = 1;
- }
- } else {
- for ( vecOff = 0; vecOff < vecLen; vecOff++) {
- PvtcpBufFree(vec[vecOff].iov_base);
- }
- }
- }
- } else { /* SOCK_DGRAM || SOCK_RAW */
- struct sockaddr *addr;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- int addrLen;
-
- /*
- * Non-stream sockets don't use the send queue, packets are sent
- * directly and they must _not_ be merged.
- */
-
- if (sk->sk_family == AF_INET) {
- sin.sin_family = AF_INET;
- sin.sin_port = packet->data16;
- addr = (struct sockaddr *)&sin;
- addrLen = sizeof sin;
- sin.sin_addr.s_addr = (unsigned int)packet->data64ex;
- PvtcpTestAndBindLoopbackInet4(pvsk, &sin.sin_addr.s_addr, 0);
- } else { /* AF_INET6 */
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = packet->data16;
- addr = (struct sockaddr *)&sin6;
- addrLen = sizeof sin6;
- PvtcpTestAndBindLoopbackInet6(pvsk, &packet->data64ex,
- &packet->data64ex2, 0);
- PvtcpI6AddrUnpack(&sin6.sin6_addr.s6_addr32[0],
- packet->data64ex, packet->data64ex2);
- }
- msg.msg_flags = packet->data32 | MSG_DONTWAIT | MSG_NOSIGNAL;
- msg.msg_name = addr;
- msg.msg_namelen = addrLen;
-
- if (pvsk->peerSockSet) {
- /*
- * Flow-control already done, based on PVTCP_SOCK_SAFE_RCVSIZE, just
- * as with stream sockets. Meaning that we block the senders in the
- * guest (if applicable).
- *
- * The send buffer size was set high enough, at socket creation time,
- * to avoid dropping datagrams during the (non-blocking) write.
- */
-
- if (vecLen == 0) {
- /*
- * Allow zero-sized datagram sending.
- */
-
- struct kvec dummy = { .iov_base = NULL, .iov_len = 0 };
-
- rc = kernel_sendmsg(sock, &msg, &dummy, 0, 0);
- if (rc != dummy.iov_len) {
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Dgram [0x%p] sent [%d], expected [%d]\n",
- __FUNCTION__, sk, rc, dummy.iov_len));
-#endif
- if (rc == -EAGAIN) { /* As if lost on the wire. */
- rc = 0;
- }
- }
- }
-
- for (vecOff = 0; vecOff < vecLen; vecOff++) {
- rc = kernel_sendmsg(sock, &msg, &vec[vecOff], 1,
- vec[vecOff].iov_len);
- PvtcpBufFree(vec[vecOff].iov_base);
- if (rc != vec[vecOff].iov_len) {
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Dgram [0x%p] sent [%d], expected [%d]\n",
- __FUNCTION__, sk, rc, vec[vecOff].iov_len));
-#endif
- if (rc == -EAGAIN) { /* As if lost on the wire. */
- rc = 0;
- }
- }
- }
-
- if (COMM_OPF_TEST_ERR(packet->flags)) {
- /* PV client wants an automatic bind. */
-
- PvskSetOpFlag(pvsk, PVTCP_OP_BIND);
- PvtcpSchedSock(pvsk);
- }
- } else {
- for ( vecOff = 0; vecOff < vecLen; vecOff++) {
- PvtcpBufFree(vec[vecOff].iov_base);
- }
- }
- }
- CommSvc_DispatchUnlock(channel);
-
-out:
- if (rc < 0) {
- pvsk->err = -rc;
- }
- tmpSize = CommOS_AddReturnAtomic(&pvsk->sentSize, dataLen);
- if ((tmpSize >= CommOS_ReadAtomic(&pvsk->deltaAckSize)) ||
- pvsk->err || needSched) {
- if (CommOS_AddReturnAtomic(&PvtcpOutputAIOSection, 1) == 1) {
- /* OutputAIO() (likely) not running. */
-
- PvtcpSchedSock(pvsk);
- }
- CommOS_SubReturnAtomic(&PvtcpOutputAIOSection, 1);
- }
-
- PvtcpPutSock(pvsk);
-}
-
-
-/*
- * AI/O functions called from the main AIO processing function.
- */
-
-/**
- * @brief Processes socket flow control acks and error notifications in an
- * AIO thread. This function is called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket to process.
- * @param err non-zero if offload was closed, zero otherwise.
- * @sideeffect May resume PV socket sending or raise errors.
- */
-
-void
-PvtcpFlowAIO(PvtcpSock *pvsk,
- int err)
-{
- CommPacket packet = { .flags = 0 };
- unsigned long long timeout;
- int tmpSize;
-
- COMM_OPF_CLEAR_ERR(packet.flags);
- packet.data32 = PVTCP_FLOW_OP_INVALID_SIZE;
- if (pvsk->err || err) {
- COMM_OPF_SET_ERR(packet.flags);
- packet.data32ex = !pvsk->err ? 0 : xchg(&pvsk->err, 0);
- if (!packet.data32ex) {
- packet.data32ex = -err;
- }
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sending socket error [%u] on [0x%p -> 0x%0x].\n",
- __FUNCTION__, packet.data32ex, pvsk,
- (unsigned)(pvsk->peerSock)));
-#endif
- } else {
- SOCK_STATE_LOCK(pvsk);
- tmpSize = CommOS_ReadAtomic(&pvsk->deltaAckSize);
- if (CommOS_ReadAtomic(&pvsk->sentSize) >= tmpSize) {
- if ((SkFromPvsk(pvsk)->sk_type != SOCK_STREAM) &&
- !sock_writeable(SkFromPvsk(pvsk))) {
- /* Don't send dgram flow op until WriteSpaceCB tells us to do so. */
-
- packet.data32 = PVTCP_FLOW_OP_INVALID_SIZE;
- } else {
- packet.data32 = CommOS_ReadAtomic(&pvsk->sentSize);
- CommOS_WriteAtomic(&pvsk->sentSize, 0);
- if (tmpSize > (1 << (PVTCP_SOCK_SMALL_ACK_ORDER + 1))) {
- tmpSize >>= 1;
- CommOS_WriteAtomic(&pvsk->deltaAckSize, tmpSize);
- }
- }
- }
- SOCK_STATE_UNLOCK(pvsk);
- packet.data32ex = 0;
- }
-
- if (((packet.data32 != PVTCP_FLOW_OP_INVALID_SIZE) ||
- COMM_OPF_TEST_ERR(packet.flags)) &&
- pvsk->peerSockSet) {
- packet.len = sizeof packet;
- packet.opCode = PVTCP_OP_FLOW;
- packet.data64 = pvsk->peerSock;
- timeout = COMM_MAX_TO;
- CommSvc_Write(pvsk->channel, &packet, &timeout);
- }
-}
-
-
-/**
- * @brief Processes queued socket output in an AIO thread. This function is
- * called with the socket 'out' lock taken.
- * @param[in,out] pvsk socket to process.
- * @sideeffect Changes send size/capacity ratio.
- */
-
-void
-PvtcpOutputAIO(PvtcpSock *pvsk)
-{
- struct sock *sk;
- struct socket *sock;
- PvtcpOffBuf *internalBuf;
- PvtcpOffBuf *tmp;
- CommOSList queue;
-#define VEC_SIZE 32
- struct kvec vec[VEC_SIZE];
- unsigned int vecLen;
- unsigned int dataLen;
- struct msghdr msg = {
- .msg_controllen = 0,
- .msg_control = NULL,
- .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL
- };
- int queueDelta = 0;
- int done = 0;
- int rc;
-
- sk = SkFromPvsk(pvsk);
- if (!sk) {
- /* This is an error socket, we don't process it. */
-
- return;
- }
-
- sock = sk->sk_socket;
-
-again:
- CommOS_AddReturnAtomic(&PvtcpOutputAIOSection, 1);
- while (!done && CommOS_ReadAtomic(&pvsk->queueSize) > 0) {
- /* Note: only stream sockets can have a positive send queue size.
- * Similar to PvtcpIoOp: we must check if sock (struct socket *) is
- * still valid.
- */
-
- /* Take the current queue private. */
-
- SOCK_STATE_LOCK(pvsk);
- queue = pvsk->queue;
- if (CommOS_ListEmpty(&queue)) {
- SOCK_STATE_UNLOCK(pvsk);
- return;
- }
- queue.next->prev = &queue;
- queue.prev->next = &queue;
- CommOS_ListInit(&pvsk->queue);
- SOCK_STATE_UNLOCK(pvsk);
-
- vecLen = 0;
- dataLen = 0;
-
- if (sk->sk_state == TCP_ESTABLISHED) {
- CommOS_ListForEach(&queue, internalBuf, link) {
- if (vecLen == VEC_SIZE) {
- break;
- }
- vec[vecLen].iov_base = PvtcpOffBufFromInternalOff(internalBuf);
- vec[vecLen].iov_len = internalBuf->len;
- dataLen += internalBuf->len;
- vecLen++;
- }
-
- rc = kernel_sendmsg(sock, &msg, vec, vecLen, dataLen);
-
- if (rc == -EAGAIN) {
- rc = 0;
- }
- if (rc >= 0) {
- /* If we wrote anything, dispose of the buffers in question. */
-
- queueDelta = rc;
- if (queueDelta > 0) {
- CommOS_ListForEachSafe(&queue, internalBuf, tmp, link) {
- if (rc >= internalBuf->len) {
- rc -= internalBuf->len;
- CommOS_ListDel(&internalBuf->link);
- PvtcpBufFree(PvtcpOffBufFromInternal(internalBuf));
- } else {
- internalBuf->len -= rc;
- internalBuf->off += rc;
- break;
- }
- }
- }
- if (!CommOS_ListEmpty(&queue)) {
- /* Add the remaining bytes to the beginning of the queue. */
-
- SOCK_STATE_LOCK(pvsk);
- CommOS_ListSplice(&pvsk->queue, &queue);
- SOCK_STATE_UNLOCK(pvsk);
- }
- if (queueDelta == 0) {
- /* Bail out if no bytes written, WriteSpaceCB() will resched. */
-
- done = 1;
- break;
- }
- CommOS_AddReturnAtomic(&pvsk->sentSize, queueDelta);
- CommOS_SubReturnAtomic(&pvsk->queueSize, queueDelta);
- } else {
- /*
- * Very likely, this is due to the socket being closed, so fine.
- */
-
- goto discardOutput;
- }
- } else {
- /* Dispose of all buffers in the queue and mark it empty. */
-
-discardOutput:
- if (!CommOS_ListEmpty(&queue)) {
- CommOS_ListForEachSafe(&queue, internalBuf, tmp, link) {
- CommOS_ListDel(&internalBuf->link);
- PvtcpBufFree(PvtcpOffBufFromInternal(internalBuf));
- }
- }
- CommOS_WriteAtomic(&pvsk->queueSize, 0);
- break;
- }
- }
- if (CommOS_SubReturnAtomic(&PvtcpOutputAIOSection, 1) > 0) {
- if (!done) {
- goto again;
- }
- }
-
- if (PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_WR)) {
- kernel_sock_shutdown(sock, SHUT_WR);
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_WR, 0);
- }
-#undef VEC_SIZE
-}
-
-
-/**
- * @brief Processes socket input in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket to process.
- * @param[in,out] perCpuBuf per-cpu socket read buffer.
- * @return zero if eof was not detected, non-zero otherwise.
- * @sideeffect Changes receive size/capacity ratio.
- */
-
-int
-PvtcpInputAIO(PvtcpSock *pvsk,
- void *perCpuBuf)
-{
- struct sock *sk;
- struct socket *sock;
- int err = 0;
- CommPacket packet = {
- .opCode = PVTCP_OP_IO
- };
- unsigned long long timeout;
-
- sk = SkFromPvsk(pvsk);
- if (!sk) {
- /* IO processing is skipped on socket create-error sockets. */
-
- return -1;
- }
- if (!perCpuBuf) {
- /* No read buffer. */
-
- return -1;
- }
-
- sock = sk->sk_socket;
- packet.data64 = pvsk->peerSock;
- COMM_OPF_CLEAR_ERR(packet.flags);
-
- if (sk->sk_state == TCP_LISTEN) {
- /* Process stream listen 'input'. */
-
- packet.len = sizeof packet;
- packet.data16 = sk->sk_ack_backlog;
- timeout = COMM_MAX_TO;
- if (pvsk->peerSockSet) {
- CommSvc_Write(pvsk->channel, &packet, &timeout);
- CommOS_Debug(("%s: Listen sock [0x%p] 'ack_backlog' [%hu].\n",
- __FUNCTION__, sk, packet.data16));
- }
- } else {
- /* Common path for both stream and datagram sockets. */
-
- int rc;
- int tmpSize;
- struct kvec vec[2];
- void *ioBuf = perCpuBuf;
- struct kvec *inVec;
- unsigned int inVecLen;
- unsigned int iovOffset = 0;
- unsigned int inputSize = 0;
- unsigned int coalescingSize = PVTCP_SOCK_RCVSIZE >> 2;
- struct sockaddr_in sin = { .sin_family = AF_INET };
- struct sockaddr_in6 sin6 = { .sin6_family = AF_INET6 };
- struct msghdr msg = {
- .msg_controllen = 0,
- .msg_control = NULL,
- .msg_flags = MSG_DONTWAIT
- };
- int tmpFlags = msg.msg_flags;
- PvtcpDgramPseudoHeader dgramHeader;
-
- tmpSize = CommOS_ReadAtomic(&pvsk->rcvdSize);
- while ((tmpSize < PVTCP_SOCK_SAFE_RCVSIZE) && pvsk->peerSockSet) {
- if (ioBuf != perCpuBuf) {
- LargeDgramBufPut(ioBuf);
- ioBuf = perCpuBuf;
- }
- vec[0].iov_base = (char *)ioBuf;
-
- if (sk->sk_type == SOCK_STREAM) {
- if (PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_RD)) {
- break;
- }
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- vec[0].iov_len = PVTCP_SOCK_STREAM_BUF_SIZE;
- } else { /* SOCK_DGRAM || SOCK_RAW */
- if (sk->sk_family == AF_INET) {
- msg.msg_name = &sin;
- msg.msg_namelen = sizeof sin;
- } else {
- msg.msg_name = &sin6;
- msg.msg_namelen = sizeof sin6;
- }
-
- /*
- * Check if datagram larger than the per cpu buffer; if so,
- * allocate a large enough buffer. This should happen quite
- * rarely, as well-behaved applications don't rely on IP
- * fragmentation to accommodate large sizes.
- */
-
- vec[0].iov_len = 1;
- msg.msg_flags |= (MSG_PEEK | MSG_TRUNC);
- rc = kernel_recvmsg(sock, &msg, vec, 1, 1, msg.msg_flags);
- if (rc < 0) {
- break;
- }
- msg.msg_flags = tmpFlags;
- if (rc > PVTCP_SOCK_DGRAM_BUF_SIZE) {
- /*
- * Track large datagram allocations, whether allocation succeeds
- * or not. No need for atomic overhead, approximating is OK.
- */
-
- pvtcpOffDgramAllocations++;
- ioBuf = LargeDgramBufGet(rc);
- if (!ioBuf) {
- /*
- * We reset it to the per-cpu buffer such that we can still
- * consume the datagram in the next recvmsg, which will set
- * MSG_TRUNC so we won't put it on the channel.
- */
-
- CommOS_Debug(("%s: Dropping datagram (alloc failure)!\n",
- __FUNCTION__));
- ioBuf = perCpuBuf;
- vec[0].iov_len = PVTCP_SOCK_DGRAM_BUF_SIZE;
- } else {
- vec[0].iov_len = rc;
- }
- } else {
- vec[0].iov_len = PVTCP_SOCK_DGRAM_BUF_SIZE;
- }
- vec[0].iov_base = (char *)ioBuf;
- }
-
- rc = kernel_recvmsg(sock, &msg, vec, 1, vec[0].iov_len, msg.msg_flags);
- if (rc < 0) {
- break;
- }
-
- if ((rc == 0) && (sk->sk_type == SOCK_STREAM)) {
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_RD, 1);
- err = -ECONNRESET;
- break;
- }
-
- if (msg.msg_flags & MSG_TRUNC) {
- continue;
- }
-
- inputSize += rc;
- tmpSize = CommOS_AddReturnAtomic(&pvsk->rcvdSize, rc);
- if (tmpSize >= PVTCP_SOCK_LARGE_ACK_WM) {
- COMM_OPF_SET_VAL(packet.flags, PVTCP_SOCK_LARGE_ACK_ORDER);
- } else {
- COMM_OPF_SET_VAL(packet.flags, 0);
- }
-
- if (sk->sk_type == SOCK_STREAM) {
- vec[0].iov_base = ioBuf;
- vec[0].iov_len = rc;
- inVecLen = 1;
- packet.len = sizeof packet + rc;
- } else { /* SOCK_DGRAM || SOCK_RAW */
- if (sk->sk_family == AF_INET) {
- dgramHeader.d0 = (unsigned long long)sin.sin_port;
- PvtcpResetLoopbackInet4(pvsk, &sin.sin_addr.s_addr);
- dgramHeader.d1 = (unsigned long long)sin.sin_addr.s_addr;
- } else { /* AF_INET6 */
- dgramHeader.d0 = (unsigned long long)sin6.sin6_port;
- PvtcpResetLoopbackInet6(pvsk, &sin6.sin6_addr);
- PvtcpI6AddrPack(&sin6.sin6_addr.s6_addr32[0],
- &dgramHeader.d1, &dgramHeader.d2);
- }
- vec[0].iov_base = &dgramHeader;
- vec[0].iov_len = sizeof dgramHeader;
- vec[1].iov_base = ioBuf;
- vec[1].iov_len = rc;
- inVecLen = 2;
- packet.len = sizeof packet + sizeof dgramHeader + rc;
- }
-
- inVec = vec;
- timeout = COMM_MAX_TO;
- rc = CommSvc_WriteVec(pvsk->channel, &packet,
- &inVec, &inVecLen, &timeout, &iovOffset);
- if (rc != packet.len) {
- CommOS_Log(("%s: BOOG -- WROTE INCOMPLETE PACKET [%u->%d]!\n",
- __FUNCTION__, packet.len, rc));
- break;
- }
-
- /*
- * If the write failed, we could print a warning. But if this
- * happened, the comm channel went down.
- */
- if (inputSize >= coalescingSize) {
- PvtcpSchedSock(pvsk); /* We must schedule ourselves back in. */
- break;
- }
- }
- if (ioBuf != perCpuBuf) {
- LargeDgramBufPut(ioBuf);
- }
- }
- return err;
-}
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp_off_linux.c b/arch/arm/mvp/pvtcpkm/pvtcp_off_linux.c
deleted file mode 100644
index 047547f..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp_off_linux.c
+++ /dev/null
@@ -1,2858 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Server (offload) side Linux-specific functions and callbacks.
- */
-
-
-#include "pvtcp.h"
-
-#if defined(CONFIG_NET_NS)
-#include <linux/nsproxy.h>
-#include <linux/un.h>
-#endif
-
-#include <net/ipv6.h>
-#include <linux/kobject.h>
-#include <linux/netfilter_ipv4.h>
-#include <linux/netfilter_ipv6.h>
-#include <linux/cred.h>
-
-
-/* The PVSock address (127.238.0.1) in binary form, host byte order. */
-#define PVTCP_PVSOCK_ADDR 0x7fee0001
-#define PVTCP_PVSOCK_NET 0x7fee0000
-#define PVTCP_PVSOCK_MASK 0x000000ff
-
-/* From mvpkm */
-extern uid_t Mvpkm_vmwareUid;
-
-/*
- * Credentials to back socket file pointer. Used in Android ICS network
- * data usage accounting to bill guest data to MVP.
- */
-static struct cred _cred;
-static struct file _file = {
- .f_cred = &_cred,
-};
-
-/* From pvtcp_off_io_linux.c */
-extern CommOSAtomic PvtcpOutputAIOSection;
-extern void PvtcpOffLargeDgramBufInit(void);
-
-static const unsigned short portRangeBase = 7000;
-static const unsigned int portRangeSize = 31;
-static int hooksRegistered = 0;
-
-static inline int PvtcpTestPortIndexBit(unsigned int addr,
- unsigned int portIdx);
-/**
- * @note
- * Netfilter hooks:
- *
- * We decide to drop each packet based on the following criteria:
- * 1) Destination address is to a pvsock address AND
- * 3) (NOT(uid == 0 OR uid == vmwareUid)) OR
- * 4) (type == UDP AND NOT(port-in-pvsock-range)))
- */
-
-/**
- * @brief Netfilter hook. Restricts LOCAL_OUT packets.
- * See note above to filter policy.
- * @param skb skbuff
- * @param inet6 is this socket ipv4 or ipv6?
- * @return NF_ACCEPT if the packet is allowed through, NF_DROP otherwise
- */
-static inline unsigned int
-PvsockNfHook(struct sk_buff *skb, int inet6)
-{
- uid_t uid;
- unsigned int port;
- struct socket *sock;
- unsigned int addr = inet6 ?
- ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]) :
- ntohl(ip_hdr(skb)->daddr);
-
- if (likely((addr ^ PVTCP_PVSOCK_NET) & ~PVTCP_PVSOCK_MASK)) {
- /* Not a pvsock address. */
- return NF_ACCEPT;
- }
-
- sock = skb->sk->sk_socket;
- if (unlikely(!sock)) {
- return NF_ACCEPT;
- }
-
- /*
- * Guest (kernel) sockets can send to other guest sockets,
- * Root can send to whoever it wants, no checks.
- */
- uid = (sock->file ? sock->file->f_cred->uid : 0);
- if (uid == 0 || (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM)) {
- return NF_ACCEPT;
- }
-
- /*
- * Only vmware can send to guest.
- */
- if (likely(uid == Mvpkm_vmwareUid)) {
- if (sock->type == SOCK_DGRAM) {
- /*
- * Deny sending to UDP port in pvsock range, if receiving socket was
- * not created by the guest with this pvsock address. Drop all other
- * UDP packets.
- */
- port = ntohs(udp_hdr(skb)->dest) - portRangeBase;
- if ((port < portRangeSize) &&
- PvtcpTestPortIndexBit(htonl(addr), port)) {
- return NF_ACCEPT;
- }
- return NF_DROP;
- }
- /*
- * TCP is all-good.
- */
- return NF_ACCEPT;
- }
-
- return NF_DROP;
-}
-
-
-/**
- * @brief AF_INET4 Netfilter hook. Restricts LOCAL_OUT packets.
- * See note above to filter policy.
- * @param hooknum netfilter hook number
- * @param skb skbuff
- * @param in rx net_device
- * @param out out net_device
- * @param okfn ignored
- * @return NF_ACCEPT if the packet is allowed through, NF_DROP otherwise
- */
-static unsigned int
-Inet4NfHook(unsigned int hooknum,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- return PvsockNfHook(skb, 0);
-}
-
-/**
- * @brief AF_INET6 Netfilter hook. Restricts LOCAL_OUT packets.
- * See note above to filter policy.
- * @param hooknum netfilter hook number
- * @param skb skbuff
- * @param in rx net_device
- * @param out out net_device
- * @param okfn ignored
- * @return NF_ACCEPT if the packet is allowed through, NF_DROP otherwise
- */
-static unsigned int
-Inet6NfHook(unsigned int hooknum,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- if (!ipv6_addr_v4mapped(&ipv6_hdr(skb)->daddr)) {
- /* Not ipv4-mapped, so not a pvsock address. */
- return NF_ACCEPT;
- }
-
- return PvsockNfHook(skb, 1);
-}
-
-
-static struct nf_hook_ops netfilterHooks[] = {
- {
- .hook = Inet4NfHook,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_LOCAL_OUT,
- .priority = NF_IP_PRI_SECURITY
- },
- {
- .hook = Inet6NfHook,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_INET_LOCAL_OUT,
- .priority = NF_IP6_PRI_SECURITY
- }
-};
-
-
-#if !defined(CONFIG_SYSFS)
-#error "The pvTCP offload module requires sysfs!"
-#endif
-
-/*
- * State kobject, attributes and type.
- */
-
-typedef struct PvtcpStateKObj {
- struct kobject kobj;
- CommTranspInitArgs transpArgs;
- unsigned int pvsockAddr;
- int useNS;
- int haveNS;
-} PvtcpStateKObj;
-
-
-typedef struct PvtcpStateKObjAttr {
- struct attribute attr;
- ssize_t (*show)(PvtcpStateKObj *stateKObj, char *buf);
- ssize_t (*store)(PvtcpStateKObj *stateKObj, const char *buf, size_t count);
-} PvtcpStateKObjAttr;
-
-
-/**
- * @brief Releases state a kobject.
- * @param kobj (embedded) state kobject.
- */
-
-static void
-StateKObjRelease(struct kobject *kobj)
-{
- kfree(container_of(kobj, PvtcpStateKObj, kobj));
-}
-
-
-/**
- * @brief Sysfs show function for all pvtcp attributes.
- * @param kobj (embedded) state kobject.
- * @param attr pvtcp attribute to show.
- * @param buf output buffer.
- * @return number of bytes written or negative error code.
- */
-
-static ssize_t
-StateKObjShow(struct kobject *kobj,
- struct attribute *attr,
- char *buf)
-{
- PvtcpStateKObjAttr *stateAttr = container_of(attr, PvtcpStateKObjAttr, attr);
- PvtcpStateKObj *stateKObj = container_of(kobj, PvtcpStateKObj, kobj);
-
- if (stateAttr->show) {
- return stateAttr->show(stateKObj, buf);
- }
-
- return -EIO;
-}
-
-
-/**
- * @brief Sysfs store function for all pvtcp attributes.
- * @param kobj (embedded) state kobject.
- * @param attr pvtcp attribute to show.
- * @param buf input buffer.
- * @param count input buffer length.
- * @return number of bytes consumed or negative error code.
- */
-
-static ssize_t
-StateKObjStore(struct kobject *kobj,
- struct attribute *attr,
- const char *buf,
- size_t count)
-{
- PvtcpStateKObjAttr *stateAttr = container_of(attr, PvtcpStateKObjAttr, attr);
- PvtcpStateKObj *stateKObj = container_of(kobj, PvtcpStateKObj, kobj);
-
- if (stateAttr->store) {
- return stateAttr->store(stateKObj, buf, count);
- }
-
- return -EIO;
-}
-
-
-static struct sysfs_ops StateKObjSysfsOps = {
- .show = StateKObjShow,
- .store = StateKObjStore
-};
-
-
-/**
- * @brief Show function for the comm_info pvtcp attribute.
- * @param stateKObj state kobject.
- * @param buf output buffer.
- * @return number of bytes written or negative error code.
- */
-
-static ssize_t
-StateKObjCommInfoShow(PvtcpStateKObj *stateKObj,
- char *buf)
-{
- unsigned int typeHash;
-
- /*
- * In the offload module, the transport arguments' type field has been
- * assigned the matching index in the versions array at probe time.
- * Recover and print out the type hash.
- */
-
- typeHash = CommTransp_GetType(pvtcpVersions[stateKObj->transpArgs.type]);
-
- return snprintf(buf, PAGE_SIZE, "ID=%u,%u\nCAPACITY=%u\nTYPE=0x%0x\n",
- stateKObj->transpArgs.id.d32[0],
- stateKObj->transpArgs.id.d32[1],
- stateKObj->transpArgs.capacity,
- typeHash);
-}
-
-
-/**
- * @brief Show function for the pvsock_addr pvtcp attribute.
- * @param stateKObj state kobject.
- * @param buf output buffer.
- * @return number of bytes written or negative error code.
- */
-
-static ssize_t
-StateKObjPvsockAddrShow(PvtcpStateKObj *stateKObj,
- char *buf)
-{
- union {
- unsigned int raw;
- unsigned char bytes[4];
- } addr;
-
- addr.raw = stateKObj->pvsockAddr;
- return snprintf(buf, PAGE_SIZE, "%u.%u.%u.%u\n",
- (unsigned int)addr.bytes[0], (unsigned int)addr.bytes[1],
- (unsigned int)addr.bytes[2], (unsigned int)addr.bytes[3]);
-}
-
-
-/**
- * @brief Show function for the use_ns pvtcp attribute.
- * @param stateKObj state kobject.
- * @param buf output buffer.
- * @return number of bytes written or negative error code.
- */
-
-static ssize_t
-StateKObjUseNSShow(PvtcpStateKObj *stateKObj,
- char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n", stateKObj->useNS);
-}
-
-
-/**
- * @brief Store function for the use_ns pvtcp attribute.
- * @param stateKObj state kobject.
- * @param buf input buffer.
- * @param count input buffer length.
- * @return number of bytes consumed or negative error code.
- */
-
-static ssize_t
-StateKObjUseNSStore(PvtcpStateKObj *stateKObj,
- const char *buf,
- size_t count)
-{
- int rc = -EINVAL;
-
- /* coverity[secure_coding] */
- if (stateKObj->haveNS && (sscanf(buf, "%d", &stateKObj->useNS) == 1)) {
- stateKObj->useNS = !!stateKObj->useNS;
- rc = count;
- }
-
- return rc;
-}
-
-
-static PvtcpStateKObjAttr stateKObjCommInfoAttr =
- __ATTR(comm_info, 0444, StateKObjCommInfoShow, NULL);
-
-static PvtcpStateKObjAttr stateKObjPvsockAddrAttr =
- __ATTR(pvsock_addr, 0444, StateKObjPvsockAddrShow, NULL);
-
-static PvtcpStateKObjAttr stateKObjUseNSAttr =
- __ATTR(use_ns, 0644, StateKObjUseNSShow, StateKObjUseNSStore);
-
-
-static struct attribute *stateKObjDefaultAttrs[] = {
- &stateKObjCommInfoAttr.attr,
- &stateKObjPvsockAddrAttr.attr,
- &stateKObjUseNSAttr.attr,
- NULL
-};
-
-
-static struct kobj_type stateKType = {
- .sysfs_ops = &StateKObjSysfsOps,
- .release = StateKObjRelease,
- .default_attrs = stateKObjDefaultAttrs
-};
-
-
-/*
- * Initialization of module entry and exit callbacks.
- */
-
-static int Init(void *args);
-static void Exit(void);
-
-COMM_OS_MOD_INIT(Init, Exit);
-
-
-/*
- * AIO socket read buffers, stats and other global state.
- */
-
-static CommOSMutex globalLock;
-static char perCpuBuf[NR_CPUS][PVTCP_SOCK_BUF_SIZE];
-
-#define PVTCP_OFF_MAX_LB_ADDRS 255
-static unsigned int loopbackAddrs[PVTCP_OFF_MAX_LB_ADDRS] = {
- 0xffffffff, // Network address always on, all ports allowed.
- 0x7fffffff // Host address not yet on, all ports allowed.
- // All the rest zeroed out.
-};
-
-static const unsigned int loopbackReserved = 0x00000001 << 31;
-
-
-#define PvtcpTestLoopbackBit(entry, mask) \
- ((entry) & (mask))
-
-#define PvtcpSetLoopbackBit(entry, mask) \
- ((entry) |= (mask))
-
-#define PvtcpResetLoopbackBit(entry, mask) \
- ((entry) &= ~(mask))
-
-
-static inline int
-PvtcpTestPortIndexBit(unsigned int addr,
- unsigned int portIdx)
-{
- return PvtcpTestLoopbackBit(loopbackAddrs[*((unsigned char *)&addr + 3)],
- BIT(portIdx));
-}
-
-
-static inline void
-PvtcpSetPortIndexBit(unsigned int addr,
- unsigned int portIdx)
-{
- PvtcpSetLoopbackBit(loopbackAddrs[*((unsigned char *)&addr + 3)],
- BIT(portIdx));
-}
-
-
-static inline void
-PvtcpResetPortIndexBit(unsigned int addr,
- unsigned int portIdx)
-{
- PvtcpResetLoopbackBit(loopbackAddrs[*((unsigned char *)&addr + 3)],
- BIT(portIdx));
-}
-
-
-unsigned int pvtcpLoopbackOffAddr;
-
-unsigned long long pvtcpOffDgramAllocations = 0;
-
-/*
- * Destructor shim addresses and function pointer
- */
-
-extern void asmDestructorShim(struct sock*);
-
-
-/*
- * Functions.
- */
-
-/**
- * @brief Release a socket, NULLing out the fake file field to avoid confusing
- * Linux on the release path
- * @param sock socket to release
- */
-static void
-SockReleaseWrapper(struct socket *sock)
-{
- sock->file = NULL;
- sock_release(sock);
-}
-
-/**
- * @brief Gets a new loopback address in the 127.238.0.255 network.
- * Note that the first address, 127.238.0.1, is always the host's.
- * @return new address or -1U if none is available.
- */
-
-static unsigned int
-GetLoopbackAddr(void)
-{
- static unsigned char addrTempl[4] = { 127, 238, 0, 0 };
- unsigned int rc = -1U;
- unsigned int idx;
- struct socket *sock;
-
- CommOS_MutexLock(&globalLock);
- for (idx = 1; idx < PVTCP_OFF_MAX_LB_ADDRS; idx++) {
- if (!PvtcpTestLoopbackBit(loopbackAddrs[idx], loopbackReserved)) {
- addrTempl[3] = (unsigned char)idx;
- memcpy(&rc, addrTempl, sizeof rc);
-
- /* Create a dgram socket to configure/bring-up the lo:N interface. */
-
- if (!sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock)) {
- int err;
- struct sockaddr_in sin = {
- .sin_family = AF_INET,
- .sin_addr = { .s_addr = rc }
- };
- struct ifreq ifr = {
- .ifr_flags = IFF_UP
- };
-
- snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "lo:%u", idx);
- memcpy(&ifr.ifr_addr, &sin, sizeof ifr.ifr_addr);
- err = kernel_sock_ioctl(sock, SIOCSIFADDR, (unsigned long)&ifr);
- sock_release(sock);
- if (err) {
- CommOS_Log(("%s: Could not set loopback address (ioctl)!\n",
- __FUNCTION__));
- rc = -1U;
- continue; /* Try next address. */
- } else {
- PvtcpSetLoopbackBit(loopbackAddrs[idx], loopbackReserved);
- CommOS_Debug(("%s: Allocated loopback address [%u.%u.%u.%u].\n",
- __FUNCTION__,
- addrTempl[0], addrTempl[1],
- addrTempl[2], addrTempl[3]));
- break;
- }
- } else {
- CommOS_Log(("%s: Could not set loopback address (create)!\n",
- __FUNCTION__));
- rc = -1U;
- break;
- }
- }
- }
- if (idx == PVTCP_OFF_MAX_LB_ADDRS) {
- CommOS_Log(("%s: loopback address range exceeded!\n", __FUNCTION__));
- }
-
- CommOS_MutexUnlock(&globalLock);
- return rc;
-}
-
-
-/**
- * @brief Puts back a loopback address in the 127.238.0.255 network.
- * @param uaddr address to put back.
- */
-
-static void
-PutLoopbackAddr(unsigned int uaddr)
-{
- const unsigned char addrTempl[3] = { 127, 238, 0 };
- unsigned char addr[4];
- unsigned int idx;
- struct socket *sock;
-
- memcpy(addr, &uaddr, sizeof uaddr);
- if (memcmp(addrTempl, addr, sizeof addrTempl)) {
- return;
- }
-
- idx = addr[3];
- if ((idx == 0) || (idx >= PVTCP_OFF_MAX_LB_ADDRS)) {
- return;
- }
-
- CommOS_MutexLock(&globalLock);
- if (!PvtcpTestLoopbackBit(loopbackAddrs[idx], loopbackReserved)) {
- CommOS_Debug(("%s: loopback entry [%u] already freed.\n",
- __FUNCTION__, idx));
- goto out;
- }
-
- if (!sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock)) {
- struct sockaddr_in sin = {
- .sin_family = AF_INET,
- .sin_addr = { .s_addr = uaddr }
- };
- struct ifreq ifr = {
- .ifr_flags = 0
- };
-
- snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "lo:%u", idx);
- memcpy(&ifr.ifr_addr, &sin, sizeof ifr.ifr_addr);
- kernel_sock_ioctl(sock, SIOCSIFFLAGS, (unsigned long)&ifr);
- sock_release(sock);
- loopbackAddrs[idx] = 0; // Zero everything out.
- CommOS_Debug(("%s: Deallocated loopback address [%u.%u.%u.%u].\n",
- __FUNCTION__, addr[0], addr[1], addr[2], addr[3]));
- } else {
- CommOS_Log(("%s: Could not delete loopback address!\n",
- __FUNCTION__));
- }
-
-out:
- CommOS_MutexUnlock(&globalLock);
-}
-
-
-/**
- * @brief Retrieves and retains the namespace associated with a channel.
- * A server must be listening for requests to retrieve the pid of the
- * process owning the net namespace for the passed context/vm id.
- * Communication takes place over a datagram socket in the AF_UNIX family,
- * bound to "/usr/lib/vmware/pvtcp/config/serv_addr".
- * @param state channel state for which to retrieve the network namespace.
- * @sideeffect If an associated namespace is found, it is retained and saved
- * in the state object.
- */
-
-static void
-GetNetNamespace(PvtcpState *state)
-{
-#if defined(CONFIG_NET_NS) && !defined(PVTCP_NET_NS_DISABLE)
- CommTranspInitArgs args;
- pid_t pidn;
- struct pid *pid;
- struct task_struct *tsk;
- struct nsproxy *nsproxy;
- struct net *ns;
- struct socket *sock;
- struct sockaddr_un addr = {
- .sun_family = AF_UNIX
- };
- struct timeval timeout = {
- .tv_sec = 3000,
- .tv_usec = 0
- };
- const int passcred = 1;
- char buf[64];
- struct kvec vec;
- const char *sockname = "pvtcp-vpn"; /* abstract namespace for AF_UNIX/LOCAL sockets */
- const size_t socknamelen = strlen(sockname);
-
- struct msghdr msg = {
- .msg_name = (struct sockaddr *)&addr,
- .msg_namelen = 1 + offsetof(struct sockaddr_un, sun_path) + socknamelen
- };
-
-
- if (!state) {
- return;
- }
-
- args = CommSvc_GetTranspInitArgs(state->channel);
- ns = NULL;
- pidn = 0;
-
- if (sock_create_kern(AF_UNIX, SOCK_DGRAM, 0, &sock)) {
- CommOS_Debug(("%s: Can't create config socket!\n", __FUNCTION__));
- goto out;
- }
- if (kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
- (char *)&timeout, sizeof timeout)) {
- sock_release(sock);
- CommOS_Debug(("%s: Can't set timeout on config socket!\n", __FUNCTION__));
- goto out;
- }
- if (kernel_setsockopt(sock, SOL_SOCKET, SO_PASSCRED,
- (char *)&passcred, sizeof passcred)) {
- sock_release(sock);
- CommOS_Debug(("%s: Can't set passcred on config socket!\n",
- __FUNCTION__));
- goto out;
- }
-
- /*
- * Send the configuration request and receive the reply:
- * - the request carries the VM/guest ID as used in the transport
- * arguments used to create the channel.
- * - the reply is expected to contain the pid of the namespace owner.
- */
-
- memset(buf, 0, sizeof buf);
- snprintf(buf, sizeof buf, "%u\n", args.id.d32[0]);
- buf[sizeof buf - 1] = '\0';
- vec.iov_base = buf;
- vec.iov_len = strlen(buf);
-
- /* use anonymous name */
- addr.sun_path[0] = 0;
- memcpy(addr.sun_path+1, sockname, socknamelen);
-
- if (kernel_sendmsg(sock, &msg, &vec, 1, vec.iov_len) <= 0) {
- sock_release(sock);
- CommOS_Debug(("%s: Could not send config request for vm [%u]!\n",
- __FUNCTION__, args.id.d32[0]));
- goto out;
- }
-
- memset(buf, 0, sizeof buf);
- vec.iov_base = buf;
- vec.iov_len = sizeof buf;
- if (kernel_recvmsg(sock, &msg, &vec, 1, vec.iov_len, 0) <= 0) {
- CommOS_Debug(("%s: Could not receive config reply for vm [%u]!\n",
- __FUNCTION__, args.id.d32[0]));
- } else {
- buf[sizeof buf - 1] = '\0';
- /* coverity[secure_coding] */
- sscanf(buf, "%d", &pidn);
- }
- sock_release(sock);
-
- if (!pidn) {
- goto out;
- }
-
- pid = find_get_pid(pidn);
- if (pid) {
- tsk = pid_task(pid, PIDTYPE_PID);
- if (tsk) {
- rcu_read_lock();
- nsproxy = task_nsproxy(tsk);
- if (nsproxy && nsproxy->net_ns) {
- ns = maybe_get_net(nsproxy->net_ns);
- }
- rcu_read_unlock();
- }
- put_pid(pid);
- }
-
-out:
- if (!ns) {
- CommOS_Debug(("%s: Not using a namespace for vm [%u].\n",
- __FUNCTION__, args.id.d32[0]));
- ns = &init_net;
- } else {
- CommOS_Debug(("%s: Found the net namespace for vm [%u].\n",
- __FUNCTION__, args.id.d32[0]));
- }
-#else
- void *ns = NULL;
-#endif
-
- state->namespace = ns;
-}
-
-
-/**
- * @brief Releases the network namespace associated with a channel state.
- * @param namespace namespace to be released.
- * @sideeffect If the namespace is not the initial one, it is released.
- */
-
-static void
-PutNetNamespace(void *namespace)
-{
-#if defined(CONFIG_NET_NS) && !defined(PVTCP_NET_NS_DISABLE)
- if (namespace && (namespace != &init_net)) {
- put_net((struct net *)namespace);
- }
-#endif
-}
-
-
-/**
- * @brief Offload state constructor called when a channel is created.
- * The function first calls the default state allocator; it then retrieves
- * the n/w namespace associated with this client, retains it and stores it
- * in the state object. Finally, it creates a sysfs node.
- * @param[in,out] channel channel to initialize.
- * @return pointer to a new state structure or NULL.
- * @sideeffect Allocates memory.
- */
-
-static void *
-StateAlloc(CommChannel channel)
-{
- extern struct kset *Mvpkm_FindVMNamedKSet(int, const char *);
- PvtcpState *state = NULL;
- PvtcpIf *loopbackNetif = NULL;
- PvtcpStateKObj *stateKObj = NULL;
- struct kset *kset = NULL;
- int rc;
- CommTranspInitArgs transpArgs;
-
- transpArgs = CommSvc_GetTranspInitArgs(channel);
-
- /*
- * The transport ID is assigned in an implementation-dependent way.
- * (see lib/comm/comm_transp.h for transport type definitions.)
- * However, the first 32 bits are expected to denote the guest/VM ID,
- * while the last 32 bits are a resource handle within that VM. On MVP,
- * transports map to queue pairs, which follow this convention.
- */
-
- kset = Mvpkm_FindVMNamedKSet((int)transpArgs.id.d32[0], "devices");
- if (!kset) {
- CommOS_Debug(("%s: Could not find sysfs '.../vm/N/devices' kset!\n",
- __FUNCTION__));
- goto error;
- }
-
- state = PvtcpStateAlloc(channel);
- if (!state) {
- CommOS_Debug(("%s: Could not allocate state!\n", __FUNCTION__));
- goto error;
- }
-
- /* coverity[leaked_storage] */
- stateKObj = kzalloc(sizeof *stateKObj, GFP_KERNEL);
- if (!stateKObj) {
- CommOS_Debug(("%s: Could not allocate state kobject!\n", __FUNCTION__));
- goto error;
- }
-
- stateKObj->kobj.kset = kset;
- /* coverity[leaked_storage] */
- rc = kobject_init_and_add(&stateKObj->kobj, &stateKType, NULL, "pvtcp");
- if (rc) {
- CommOS_Debug(("%s: Could not add state kobject to parent kset [%d]!\n",
- __FUNCTION__, rc));
- goto error;
- }
-
- loopbackNetif = PvtcpStateFindIf(state, pvtcpIfLoopbackInet4);
- BUG_ON(loopbackNetif == NULL);
- loopbackNetif->conf.addr.in.s_addr = GetLoopbackAddr();
- if (loopbackNetif->conf.addr.in.s_addr == -1U) {
- CommOS_Log(("%s: Could not allocate loopback address!\n", __FUNCTION__));
- goto error;
- }
-
- GetNetNamespace(state);
-
- stateKObj->transpArgs = transpArgs;
- stateKObj->pvsockAddr = loopbackNetif->conf.addr.in.s_addr;
-#if defined(CONFIG_NET_NS)
- stateKObj->haveNS = (state->namespace != &init_net);
- stateKObj->useNS = stateKObj->haveNS;
-#endif
- state->extra = stateKObj;
-
- _cred.uid = _cred.gid = _cred.suid = _cred.sgid =
- _cred.euid = _cred.egid = _cred.fsuid = _cred.fsgid = Mvpkm_vmwareUid;
-
-
-out:
- if (kset) {
- kset_put(kset);
- }
- return state;
-
-error:
- if (stateKObj) {
- kobject_del(&stateKObj->kobj);
- kobject_put(&stateKObj->kobj);
- }
- if (loopbackNetif && (loopbackNetif->conf.addr.in.s_addr != -1U)) {
- PutLoopbackAddr(loopbackNetif->conf.addr.in.s_addr);
- }
- if (state) {
- PvtcpStateFree(state);
- state = NULL;
- }
- goto out;
-}
-
-
-/**
- * @brief Offload state destructor called when a channel is closed.
- * The function releases this client's n/w namespace and then calls the
- * default state deallocator.
- * @param arg pointer to state structure.
- * @sideeffect Destroys all netifs and their sockets, deallocates memory.
- */
-
-static void
-StateFree(void *arg)
-{
- PvtcpState *state = arg;
- PvtcpIf *loopbackNetif;
- void *namespace;
-
- if (!state) {
- return;
- }
-
- if (state->extra) {
- PvtcpStateKObj *stateKObj = state->extra;
-
- kobject_del(&stateKObj->kobj);
- kobject_put(&stateKObj->kobj);
- }
-
- namespace = state->namespace;
- loopbackNetif = PvtcpStateFindIf(state, pvtcpIfLoopbackInet4);
- BUG_ON(loopbackNetif == NULL);
- PutLoopbackAddr(loopbackNetif->conf.addr.in.s_addr);
- PvtcpStateFree(state);
- PutNetNamespace(namespace);
-}
-
-
-/**
- * @brief Releases socket. This function is called when the channel state
- * owning the socket is closed.
- * @param[in,out] pvsk PV socket to release.
- * @sideeffect the socket eventually gets deallocated.
- */
-
-void
-PvtcpReleaseSocket(PvtcpSock *pvsk)
-{
- struct socket *sock = SkFromPvsk(pvsk)->sk_socket;
-
- SOCK_IN_LOCK(pvsk);
- SOCK_OUT_LOCK(pvsk);
- pvsk->peerSockSet = 0;
- SockReleaseWrapper(sock);
- SOCK_OUT_UNLOCK(pvsk);
- SOCK_IN_UNLOCK(pvsk);
- CommOS_Debug(("%s: [0x%p].\n", __FUNCTION__, pvsk));
-}
-
-
-/**
- * @brief Tests if the passed address is 127.238.0.1 or 127.0.0.1.
- * @param pvsk socket to test.
- * @param addr inet4 address to test.
- * @return > 1: morph and propagate new address to caller, 1: just morph,
- * 0: don't morph, < 0 (-EADDRNOTAVAIL): bad loopback.
- */
-
-static inline int
-TestLoopbackInet4(PvtcpSock *pvsk,
- unsigned int addr)
-{
- if (!ipv4_is_loopback(addr)) {
- return 0;
- }
-
- if (addr != htonl(PVTCP_PVSOCK_ADDR)) {
- if (addr != htonl(INADDR_LOOPBACK)) {
- return -EADDRNOTAVAIL;
- }
- if (PvtcpHasSockNamespace(pvsk)) {
- /* We don't morph normal 127.0.0.1 when NS present. */
-
- return 0;
- }
- return 2;
- }
-
- return 1;
-}
-
-
-/**
- * @brief Tests if the passed address is 127.238.0.1 or 127.0.0.1 and the
- * socket has a namespace. If yes, the address will be morphed into
- * the actual loopback address, then a bind() is performed.
- * Note that the function returns EADDRNOTAVAIL for any other loopbacks.
- * @param pvsk socket to test.
- * @param[in,out] addr inet4 address to test.
- * @param port port to bind, or zero for any port.
- * @return 1 if bind should be performed by caller, bind return code otherwise.
- */
-
-int
-PvtcpTestAndBindLoopbackInet4(PvtcpSock *pvsk,
- unsigned int *addr,
- unsigned short port)
-{
- int rc;
- struct sockaddr_in sin;
- unsigned int morphedAddr;
- int propagate = 0;
-
- rc = TestLoopbackInet4(pvsk, *addr);
- switch (rc) {
- case 2:
- propagate = 1; // Fall through.
- case 1:
- break; // Proceed with morphing.
- case 0:
- return 1; // Don't morph, let bind() be done by caller.
- default:
- return rc;
- }
-
- if (pvsk->netif->conf.family == PVTCP_PF_LOOPBACK_INET4) {
- /* The socket has already been morphed/bound. */
-
- morphedAddr = pvsk->netif->conf.addr.in.s_addr;
- rc = 0;
- goto out;
- }
-
- /*
- * Move the socket to the initial namespace before binding it
- * such that the loopback address is accessible to the host.
- */
-
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_INITIAL);
- PvtcpStateAddSocket(pvsk->channel, pvtcpIfLoopbackInet4, pvsk);
- morphedAddr = pvsk->netif->conf.addr.in.s_addr;
- memset(&sin, 0, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_port = port;
- sin.sin_addr.s_addr = morphedAddr;
-
- /* Bind to the channel loopback address. */
-
- rc = kernel_bind(SkFromPvsk(pvsk)->sk_socket,
- (struct sockaddr *)&sin, sizeof sin);
- if (rc) {
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_CHANNEL);
- PvtcpStateAddSocket(pvsk->channel, pvtcpIfUnbound, pvsk);
- } else {
- /*
- * Bind succeeded on pvsock address.
- * If this is a pvsock UDP reserved port, record it.
- */
-
- port = ntohs(port) - portRangeBase;
- if ((SkFromPvsk(pvsk)->sk_socket->type == SOCK_DGRAM) &&
- (port < portRangeSize)) {
- CommOS_MutexLock(&globalLock);
- PvtcpSetPortIndexBit(pvsk->netif->conf.addr.in.s_addr, port);
- CommOS_MutexUnlock(&globalLock);
- }
-
- /*
- * pvsock data usage shouldn't be counted as MVP external traffic.
- */
- SkFromPvsk(pvsk)->sk_socket->file = NULL;
- }
-
-out:
- if (propagate) {
- *addr = morphedAddr;
- }
- return rc;
-}
-
-
-/**
- * @brief Tests if the passed address is IPV4-mapped 127.238.0.1 or 127.0.0.1,
- * clean ::1, and whether the socket has a namespace.
- * If needed, the address will be morphed into the actual loopback address,
- * then a bind() is performed.
- * Note that the function returns EADDRNOTAVAIL for any other loopbacks.
- * @param pvsk socket to test.
- * @param[in,out] addr0 first 64 bits of inet6 address to test.
- * @param[in,out] addr1 last 64 bits of inet6 address to test.
- * @param port port to bind, or zero for any port.
- * @return 1 if bind should be performed by caller, bind return code otherwise.
- */
-
-int
-PvtcpTestAndBindLoopbackInet6(PvtcpSock *pvsk,
- unsigned long long *addr0,
- unsigned long long *addr1,
- unsigned short port)
-{
- int rc;
- struct sockaddr_in6 sin6;
- union {
- unsigned long long halves[2];
- struct in6_addr in6;
- } in6Addr = {
- .halves = { *addr0, *addr1 }
- };
- int propagate = 0;
- const int ipv6Only = 0;
-
- if (ipv6_addr_loopback(&in6Addr.in6)) {
- if (PvtcpHasSockNamespace(pvsk)) {
- return 1;
- }
-
- /* Remember that we were passed '::1'. */
-
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_IPV6_LOOP, 1);
- ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), &in6Addr.in6);
- }
-
- if (!ipv6_addr_v4mapped(&in6Addr.in6)) {
- /* If the address is not ipv4-mapped, stop testing. */
-
- return 1;
- }
-
- rc = TestLoopbackInet4(pvsk, in6Addr.in6.s6_addr32[3]);
- switch (rc) {
- case 2:
- propagate = 1; // Fall through.
- case 1:
- break; // Proceed with morphing.
- case 0:
- return 1; // Don't morph, let bind() be done by caller.
- default:
- return rc;
- }
-
- if (pvsk->netif->conf.family == PVTCP_PF_LOOPBACK_INET4) {
- /* The socket has already been morphed/bound. */
-
- ipv6_addr_set_v4mapped(pvsk->netif->conf.addr.in.s_addr, &in6Addr.in6);
- rc = 0;
- goto out;
- }
-
- /*
- * Move the socket to the initial namespace before binding it
- * such that the loopback address is accessible to the host.
- */
-
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_INITIAL);
- PvtcpStateAddSocket(pvsk->channel, pvtcpIfLoopbackInet4, pvsk);
- ipv6_addr_set_v4mapped(pvsk->netif->conf.addr.in.s_addr, &in6Addr.in6);
- memset(&sin6, 0, sizeof sin6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = port;
- sin6.sin6_addr = in6Addr.in6;
-
- /*
- * Ensure we can use ipv4 mapped addresses and bind to the channel
- * loopback address.
- */
-
- (void)kernel_setsockopt(SkFromPvsk(pvsk)->sk_socket, IPPROTO_IPV6,
- IPV6_V6ONLY, (char *)&ipv6Only, sizeof ipv6Only);
- rc = kernel_bind(SkFromPvsk(pvsk)->sk_socket,
- (struct sockaddr *)&sin6, sizeof sin6);
- if (rc) {
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_CHANNEL);
- PvtcpStateAddSocket(pvsk->channel, pvtcpIfUnbound, pvsk);
- } else {
- /*
- * Bind succeeded on pvsock address.
- * If this is a pvsock UDP reserved port, record it.
- */
-
- port = ntohs(port) - portRangeBase;
- if ((SkFromPvsk(pvsk)->sk_socket->type == SOCK_DGRAM) &&
- (port < portRangeSize)) {
- CommOS_MutexLock(&globalLock);
- PvtcpSetPortIndexBit(pvsk->netif->conf.addr.in.s_addr, port);
- CommOS_MutexUnlock(&globalLock);
- }
-
- /*
- * pvsock data usage shouldn't be counted as MVP external traffic.
- */
- SkFromPvsk(pvsk)->sk_socket->file = NULL;
- }
-
-out:
- if (propagate) {
- *addr0 = in6Addr.halves[0];
- *addr1 = in6Addr.halves[1];
- }
- return rc;
-}
-
-
-/**
- * @brief Resets a 127.238.0.N address to 127.0.0.1.
- * @param pvsk socket whose address needs resetting.
- * @param[in,out] addr inet4 address to reset.
- */
-
-void
-PvtcpResetLoopbackInet4(PvtcpSock *pvsk,
- unsigned int *addr)
-{
- if (!PvtcpHasSockNamespace(pvsk)) {
- static const unsigned int pvsockAddr = htonl(PVTCP_PVSOCK_ADDR);
-
- if (!memcmp(&pvsockAddr, addr, 3) && memcmp(&pvsockAddr, addr, 4)) {
- /* If it's a pvsock address but _not_ the host's, overwrite it. */
-
- *addr = htonl(INADDR_LOOPBACK);
- }
- }
-}
-
-
-/**
- * @brief Resets an IPV4-mapped ::ffff:127.238.0.N IPV6 address to loopback.
- * @param pvsk socket whose address needs resetting.
- * @param[in,out] in6 inet6 address to reset.
- */
-
-void
-PvtcpResetLoopbackInet6(PvtcpSock *pvsk,
- struct in6_addr *in6)
-{
- if (!PvtcpHasSockNamespace(pvsk) && ipv6_addr_v4mapped(in6)) {
- if (PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_IPV6_LOOP)) {
- /* If the original address came in as ::1, we reset as such. */
-
- static const struct in6_addr in6Loopback = IN6ADDR_LOOPBACK_INIT;
-
- *in6 = in6Loopback;
- } else {
- PvtcpResetLoopbackInet4(pvsk, &in6->s6_addr32[3]);
- }
- }
-}
-
-
-/**
- * @brief Called at module load time. It registers with the Comm runtime.
- * @param args initialization arguments
- * @return zero if successful, -1 otherwise
- * @sideeffect Leaves the module loaded
- */
-
-static int
-Init(void *args)
-{
- int rc = -1;
-
-#if !defined(PVTCP_DISABLE_NETFILTER)
- rc = nf_register_hooks(netfilterHooks, ARRAY_SIZE(netfilterHooks));
- if (rc) {
- CommOS_Log(("%s: Could not register netfilter hooks!\n", __FUNCTION__));
- goto out;
- } else {
- CommOS_Debug(("%s: Registered netfilter hooks.\n", __FUNCTION__));
- }
- hooksRegistered = 1;
-#else
- CommOS_Log(("%s: Netfilter hooks disabled.\n", __FUNCTION__));
-#endif
-
- CommOS_MutexInit(&globalLock);
- CommOS_WriteAtomic(&PvtcpOutputAIOSection, 0);
- PvtcpOffLargeDgramBufInit();
-
- pvtcpImpl.owner = CommOS_ModuleSelf();
- pvtcpImpl.stateCtor = StateAlloc;
- pvtcpImpl.stateDtor = StateFree;
- if (CommSvc_RegisterImpl(&pvtcpImpl) == 0) {
- rc = 0;
- pvtcpLoopbackOffAddr = GetLoopbackAddr();
- if (pvtcpLoopbackOffAddr == -1U) {
- CommOS_Log(("%s: Could not allocate offload loopback address!\n",
- __FUNCTION__));
- rc = -1;
- CommSvc_UnregisterImpl(&pvtcpImpl);
- }
- }
-
-out:
- if (rc) {
- if (hooksRegistered) {
- nf_unregister_hooks(netfilterHooks, ARRAY_SIZE(netfilterHooks));
- }
- }
- return rc;
-}
-
-
-/**
- * @brief Called at module unload time. It shuts down pvtcp.
- * @sideeffect Total and utter destruction.
- */
-
-static void
-Exit(void)
-{
- PutLoopbackAddr(pvtcpLoopbackOffAddr);
- CommSvc_UnregisterImpl(&pvtcpImpl);
-#if !defined(PVTCP_DISABLE_NETFILTER)
- if (hooksRegistered) {
- nf_unregister_hooks(netfilterHooks, ARRAY_SIZE(netfilterHooks));
- CommOS_Debug(("%s: Netfilter hooks unregistered.\n", __FUNCTION__));
- }
-#endif
- CommOS_Log(("%s: Allocations of large datagrams: %llu.\n",
- __FUNCTION__, pvtcpOffDgramAllocations));
-}
-
-
-/*
- * Socket callback interceptors.
- */
-
-/**
- * @brief Callback called when socket is destroyed.
- * @param[in,out] sk socket to cleanup
- * @return 0 if socket memory is freed, < 0 otherwise (no-op)
- * @sideeffect Send queue buffers are deallocated
- */
-
-int
-DestructCB(struct sock *sk)
-{
- PvtcpOffBuf *internalBuf;
- PvtcpOffBuf *tmp;
- PvtcpSock *pvsk = PvskFromSk(sk);
-
- if (!pvsk ||
- (SkFromPvsk(pvsk) != sk) ||
- (pvsk->destruct == asmDestructorShim)) {
- /* Module put _not_ to be performed by asmDestructorShim. */
-
- CommOS_Debug(("%s: pvsk / sk inconsistency. Ignored.\n", __FUNCTION__));
- return -1;
- }
-
- CommOS_ListForEachSafe(&pvsk->queue, internalBuf, tmp, link) {
- CommOS_ListDel(&internalBuf->link);
- PvtcpBufFree(PvtcpOffBufFromInternal(internalBuf));
- }
- if (pvsk->destruct) {
- pvsk->destruct(sk);
- }
-
- if (pvsk->rpcReply) {
- CommOS_Kfree(pvsk->rpcReply);
- }
- CommOS_Kfree(pvsk);
-
- /*
- * Module put is performed by asmDestructorShim.
- */
-
- return 0;
-}
-
-
-/**
- * @brief Callback called when socket state changes occur.
- * @param sk socket specified socket which changed state
- * @sideeffect A writer task may be scheduled
- */
-
-static void
-StateChangeCB(struct sock *sk)
-{
- PvtcpSock *pvsk = PvskFromSk(sk);
-
- if (!pvsk ||
- (SkFromPvsk(pvsk) != sk) ||
- (pvsk->stateChange == StateChangeCB)) {
- CommOS_Debug(("%s: pvsk / sk inconsistency. Ignored.\n", __FUNCTION__));
- return;
- }
-
- /*
- * The socket (spin) lock is held when this function is called.
- */
-
- CommOS_Debug(("%s: [0x%p] sk_state [%u] sk_err [%d] sk_err_soft [%d].\n",
- __FUNCTION__, pvsk, sk->sk_state,
- sk->sk_err, sk->sk_err_soft));
- if (pvsk->stateChange) {
- pvsk->stateChange(sk);
- }
- if (sk->sk_state == TCP_ESTABLISHED) {
- PvskSetOpFlag(pvsk, PVTCP_OP_CONNECT);
- }
- PvtcpSchedSock(pvsk);
-}
-
-
-/**
- * @brief Callback called when an error is set on the socket.
- * @param sk socket the error happened on
- * @sideeffect A writer task may be scheduled
- */
-
-static void
-ErrorReportCB(struct sock *sk)
-{
- PvtcpSock *pvsk = PvskFromSk(sk);
-
- if (!pvsk ||
- (SkFromPvsk(pvsk) != sk) ||
- (pvsk->errorReport == ErrorReportCB)) {
- CommOS_Debug(("%s: pvsk / sk inconsistency. Ignored\n", __FUNCTION__));
- return;
- }
-
- /*
- * The socket (spin) lock is held when this function is called.
- * Interesting sk_err-s:
- * ECONNRESET - tcp_disconnect(), tcp_reset()
- * ECONNREFUSED - tcp_reset()
- * EPIPE - tcp_reset()
- * ETIMEDOUT - tcp_write_error()
- * EHOSTUNREACH, etc. - tcp_v4_error()??, icmp errors
- * etc. - __udp4_lib_err(), icmp errors
- */
-
- CommOS_Debug(("%s: [0x%p] sk_err [%d] sk_err_soft [%d].\n",
- __FUNCTION__, pvsk, sk->sk_err, sk->sk_err_soft));
- if (pvsk->errorReport) {
- pvsk->errorReport(sk);
- }
- pvsk->err = sk->sk_err;
- PvtcpSchedSock(pvsk);
-}
-
-
-/**
- * @brief Callback called when data is available to be read from a socket.
- * @param sk socket in question
- * @param bytes number of bytes to read
- * @sideeffect A writer task is scheduled _iff_ the peer can safely
- * receive.
- */
-
-static void
-DataReadyCB(struct sock *sk,
- int bytes)
-{
- PvtcpSock *pvsk = PvskFromSk(sk);
-
- if (!pvsk ||
- (SkFromPvsk(pvsk) != sk) ||
- (pvsk->dataReady == DataReadyCB)) {
- CommOS_Debug(("%s: pvsk / sk inconsistency. Ignored.\n", __FUNCTION__));
- return;
- }
-
- /*
- * The socket (spin) lock is held when this function is called.
- */
-
- if (pvsk->dataReady) {
- pvsk->dataReady(sk, bytes);
- }
- if (sk->sk_state == TCP_LISTEN) {
- CommOS_Debug(("%s: Listen socket ready to accept [0x%p].\n",
- __FUNCTION__, pvsk));
- }
- PvtcpSchedSock(pvsk);
-}
-
-
-/**
- * @brief Callback called when writing is possible on a socket.
- * @param sk socket in question
- * @sideeffect An AIO thread is scheduled.
- */
-
-static void
-WriteSpaceCB(struct sock *sk)
-{
- PvtcpSock *pvsk = PvskFromSk(sk);
-
- if (!pvsk ||
- (SkFromPvsk(pvsk) != sk) ||
- (pvsk->writeSpace == WriteSpaceCB)) {
- CommOS_Debug(("%s: pvsk / sk inconsistency. Ignored.\n", __FUNCTION__));
- return;
- }
-
- /*
- * The socket (spin) lock is held when this function is called.
- */
-
- if (pvsk->writeSpace) {
- pvsk->writeSpace(sk);
- }
- PvtcpSchedSock(pvsk);
-}
-
-
-/**
- * @brief Initializes a newly created socket for offload operations.
- * @param[in,out] sock socket to initialize
- * @param channel channel to update
- * @param peerSock peer PV socket of this socket
- * @param parentPvsk parent of this socket or NULL
- * @return zero on success, error code otherwise
- */
-
-static int
-SockAllocInit(struct socket *sock,
- CommChannel channel,
- unsigned long long peerSock,
- PvtcpSock *parentPvsk)
-{
- struct sock *sk;
- PvtcpSock *pvsk;
- int sndBuf = PVTCP_SOCK_RCVSIZE * 4;
-
- if (!sock || !channel || !peerSock) {
- return -EINVAL;
- }
-
- sk = sock->sk;
- sk->sk_user_data = NULL;
-
- pvsk = CommOS_Kmalloc(sizeof *pvsk);
- if (!pvsk) {
- return -ENOMEM;
- }
-
- if (PvtcpOffSockInit(pvsk, channel)) {
- CommOS_Kfree(pvsk);
- return -ENOMEM;
- }
-
- /*
- * PVTCP sockets should be billed against the vmware uid.
- */
- sk->sk_socket->file = &_file;
-
- /* Set peer (pv) socket. */
- pvsk->peerSock = peerSock;
- pvsk->peerSockSet = 1;
-
- /* Set up back pointer. */
- pvsk->sk = sk;
-
- /* Keep track of new socket. */
- if (PvtcpStateAddSocket(channel, pvtcpIfUnbound, pvsk) != 0) {
- CommOS_Kfree(pvsk);
- return -ENOMEM;
- }
-
- /*
- * Keep pvtcp around for at least the lifetime of this socket
- */
- CommOS_ModuleGet(pvtcpImpl.owner);
-
- if (!parentPvsk) {
- pvsk->destruct = sk->sk_destruct;
- sk->sk_destruct = asmDestructorShim;
- pvsk->stateChange = sk->sk_state_change;
- sk->sk_state_change = StateChangeCB;
- pvsk->errorReport = sk->sk_error_report;
- sk->sk_error_report = ErrorReportCB;
- pvsk->dataReady = sk->sk_data_ready;
- sk->sk_data_ready = DataReadyCB;
- pvsk->writeSpace = sk->sk_write_space;
- sk->sk_write_space = WriteSpaceCB;
- } else {
- /*
- * Copy the parent's saved callbacks. The parent pvsk is only passed
- * when creating/initializing a socket after an 'accept'.
- */
-
- pvsk->destruct = parentPvsk->destruct;
- sk->sk_destruct = asmDestructorShim;
- pvsk->stateChange = parentPvsk->stateChange;
- sk->sk_state_change = StateChangeCB;
- pvsk->errorReport = parentPvsk->errorReport;
- sk->sk_error_report = ErrorReportCB;
- pvsk->dataReady = parentPvsk->dataReady;
- sk->sk_data_ready = DataReadyCB;
- pvsk->writeSpace = parentPvsk->writeSpace;
- sk->sk_write_space = WriteSpaceCB;
-
- if (parentPvsk->netif->conf.family == PVTCP_PF_LOOPBACK_INET4) {
- /* The parent socket was morphed/bound. */
-
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_INITIAL);
- PvtcpStateAddSocket(pvsk->channel, pvtcpIfLoopbackInet4, pvsk);
- }
- }
-
- /* Install forward socket reference. */
- sk->sk_user_data = pvsk;
-
- /*
- * Force the send buffer size high enough, such that we don't lose the
- * just-a-bit-over-the-limit bytes. This is mainly needed for datagrams.
- * Note that we always apply flow control between host and guest modules,
- * according to the sizing model; so this is not artificially inflated.
- */
-
- kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUFFORCE,
- (void *)&sndBuf, sizeof sndBuf);
-
- return 0;
-}
-
-
-/**
- * @brief Allocates a pvsk socket for error reporting (create operation).
- * @param err error code to report to PV side
- * @param channel channel error socket belongs to
- * @param peerSock peer PV socket of this socket
- * @return error socket on success, NULL otherwise
- */
-
-static PvtcpSock *
-SockAllocErrInit(int err,
- CommChannel channel,
- unsigned long long peerSock)
-{
- PvtcpSock *pvsk;
-
- if (!channel || !peerSock) {
- return NULL;
- }
-
- pvsk = CommOS_Kmalloc(sizeof *pvsk);
- if (!pvsk) {
- return NULL;
- }
-
- if (PvtcpOffSockInit(pvsk, channel)) {
- CommOS_Kfree(pvsk);
- return NULL;
- }
-
- /* Set peer (pv) socket and error. */
- pvsk->peerSock = peerSock;
- pvsk->peerSockSet = 1;
- pvsk->err = err;
-
- /* Set up back pointer to NULL such that PvtcpPutSock deallocates it. */
- pvsk->sk = NULL;
- return pvsk;
-}
-
-
-/*
- * Offload operations.
- */
-
-/**
- * @brief Creates an offload socket and schedules it for reply.
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back.
- */
-
-void
-PvtcpCreateOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- int rc;
- struct socket *sock;
- PvtcpSock *pvsk;
- PvtcpState *state = (PvtcpState *)upperLayerState;
- const int enable = 1;
-
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
-
-#if defined(PVTCP_IPV6_DISABLE)
- if (packet->data16 == AF_INET6) {
- CommOS_Debug(("%s: AF_INET6 support is disabled.\n", __FUNCTION__));
- rc = -EAFNOSUPPORT;
- } else
-#endif
- {
- rc = sock_create_kern(packet->data16, packet->data32,
- packet->data32ex, &sock);
- }
-
- if (!rc) {
- rc = SockAllocInit(sock, channel, packet->data64, NULL);
- if (rc) {
- SockReleaseWrapper(sock);
- goto fail;
- }
- kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (void *)&enable, sizeof enable);
- pvsk = PvskFromSk(sock->sk);
- if (state->extra &&
- ((PvtcpStateKObj *)(state->extra))->useNS) {
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_CHANNEL);
- } else {
- PvtcpSwitchSock(pvsk, PVTCP_SOCK_NAMESPACE_INITIAL);
- }
- PvtcpStateAddSocket(pvsk->channel, pvtcpIfUnbound, pvsk);
- PvskSetOpFlag(pvsk, PVTCP_OP_CREATE);
- } else {
- CommOS_Debug(("%s: Error creating offload socket: %d\n",
- __FUNCTION__, rc));
- /*
- * Pass -rc so we follow error conventions for other reply ops.
- * The error code is fixed by the PV side so error codes are properly
- * reported.
- */
- pvsk = SockAllocErrInit(-rc, channel, packet->data64);
- if (!pvsk) {
- goto fail;
- }
- }
-
- PvtcpSchedSock(pvsk);
- return;
-
-fail:
- CommOS_Log(("%s: BOOG ** FAILED TO CREATE OFFLOAD SOCKET [%d] "
- "_AND_ ERROR REPORTING SOCKET!\n"
- " PV SIDE MAY BE LOCKED UP UNTIL CREATE RPC TIMES OUT!",
- __FUNCTION__, rc));
-}
-
-
-/**
- * @brief Schedules an offload socket to be removed.
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back and
- * then release the socket.
- */
-
-void
-PvtcpReleaseOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
-
- /*
- * Check if this is a pvsock datagram socket bound on a reserved port.
- * If so, reset the bit such that filtering drops rogue packets.
- */
-
- if ((sk->sk_socket->type == SOCK_DGRAM) &&
- (pvsk->netif->conf.family == PVTCP_PF_LOOPBACK_INET4)) {
- unsigned short port = 0;
-
- if (sk->sk_family == AF_INET) {
- struct sockaddr_in sin = { .sin_family = AF_INET };
- int addrLen = sizeof sin;
-
- if(!kernel_getsockname(sk->sk_socket,
- (struct sockaddr *)&sin, &addrLen)) {
- port = sin.sin_port;
- }
- } else { /* AF_INET6 */
- struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
- int addrLen = sizeof sin;
-
- if(!kernel_getsockname(sk->sk_socket,
- (struct sockaddr *)&sin, &addrLen)) {
- port = sin.sin6_port;
- }
- }
-
- port = ntohs(port) - portRangeBase;
- if (port < portRangeSize) {
- CommOS_MutexLock(&globalLock);
- PvtcpResetPortIndexBit(pvsk->netif->conf.addr.in.s_addr, port);
- CommOS_MutexUnlock(&globalLock);
- }
- }
-
- /*
- * - hold the socket before setting the 'release' flag and until after
- * the call to PvtcpSchedSock(): if the socket had already been scheduled
- * ReleaseAIO may run, find the flag set and release this socket while
- * it's being unlocked here.
- *
- * - hold the dispatch lock until done to ensure that subsequent Ops for
- * this socket see peerSockSet == 0.
- */
-
- PvtcpHoldSock(pvsk);
- SOCK_STATE_LOCK(pvsk);
- pvsk->peerSockSet = 0;
- SOCK_STATE_UNLOCK(pvsk);
- PvskSetOpFlag(pvsk, PVTCP_OP_RELEASE);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
-}
-
-
-/**
- * @brief Binds an offload socket to a given address
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back
- */
-
-void
-PvtcpBindOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- struct sockaddr *addr;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- int reuseAddr;
- int addrLen;
- int rc;
-
- PvtcpHoldSock(pvsk);
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
-
- /*
- * The socket-level option SO_REUSEADDR is set in the common socket code,
- * meaning that we cannot intercept it in the guest pvtcp implementation.
- * In order to respect the setting, the guest would pass the current
- * setting in 'bind' requests.
- * If the guest requires 'reuse address' setting, the value is incremented
- * such that we differentiate between: 0) not requested, 1) 'false' and
- * 2) 'true'.
- */
-
- reuseAddr = COMM_OPF_GET_VAL(packet->flags);
- if ((reuseAddr == 1) || (reuseAddr == 2)) {
- /* Explicit request, so decrement the value. */
-
- reuseAddr--;
- kernel_setsockopt(sk->sk_socket, SOL_SOCKET, SO_REUSEADDR,
- (void *)&reuseAddr, sizeof reuseAddr);
- }
-
- if (sk->sk_family == AF_INET) {
- memset(&sin, 0, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_port = packet->data16;
- sin.sin_addr.s_addr = (unsigned int)packet->data64ex;
- addr = (struct sockaddr *)&sin;
- addrLen = sizeof sin;
-
- rc = PvtcpTestAndBindLoopbackInet4(pvsk, &sin.sin_addr.s_addr,
- sin.sin_port);
- if (rc <= 0) {
- /* Bind has already happened. */
-
- pvsk->err = -rc;
- goto out;
- }
- } else { /* AF_INET6 */
- memset(&sin6, 0, sizeof sin6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = packet->data16;
- addr = (struct sockaddr *)&sin6;
- addrLen = sizeof sin6;
-
- rc = PvtcpTestAndBindLoopbackInet6(pvsk, &packet->data64ex,
- &packet->data64ex2, sin6.sin6_port);
- if (rc <= 0) {
- /* Bind has already happened. */
-
- pvsk->err = -rc;
- goto out;
- }
- PvtcpI6AddrUnpack(&sin6.sin6_addr.s6_addr32[0],
- packet->data64ex, packet->data64ex2);
- }
-
- /* coverity[check_return] */
- pvsk->err = -kernel_bind(sk->sk_socket, addr, addrLen);
-
-out:
- PvskSetOpFlag(pvsk, PVTCP_OP_BIND);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Sets a socket option.
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back
- */
-void
-PvtcpSetSockOptOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- unsigned int optlen = packet->len - sizeof *packet;
-
- PvtcpHoldSock(pvsk);
-
- if ((vecLen != 1) || (vec[0].iov_len != optlen) || (optlen < sizeof(int))) {
- pvsk->rpcStatus = -EINVAL;
- goto out;
- }
-
- if (packet->data32 == SOL_TCP) {
- /*
- * The back-end implementation must always run in 'nodelay' mode.
- * Consequently, we ignore, but we cache the TCP_NODELAY and TCP_CORK
- * settings such that getsockopt() can return them as they were 'set'.
- * Applications use these settings for performance; pvtcp does quite
- * well if it's not interfered with.
- */
-
- int on;
-
- switch (packet->data32ex) {
- case TCP_NODELAY:
- memcpy(&on, vec[0].iov_base, sizeof on);
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_TCP_NODELAY, on);
- pvsk->rpcStatus = 0;
- goto out;
- case TCP_CORK:
- memcpy(&on, vec[0].iov_base, sizeof on);
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_TCP_CORK, on);
- pvsk->rpcStatus = 0;
- goto out;
- }
- }
-
- pvsk->rpcStatus = kernel_setsockopt(sock,
- packet->data32,
- packet->data32ex,
- vec[0].iov_base,
- optlen);
-
-out:
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
- PvskSetOpFlag(pvsk, PVTCP_OP_SETSOCKOPT);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Retrieves a socket option.
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back
- */
-void
-PvtcpGetSockOptOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- unsigned int optLen = (unsigned int)(packet->data64ex);
- char *optBuf;
- int rc = 0;
-
- PvtcpHoldSock(pvsk);
-
- if ((optLen < sizeof(int)) || (optLen > PVTCP_SOCK_SAFE_RCVSIZE)) {
- pvsk->rpcStatus = -EINVAL;
- goto out;
- }
-
- optBuf = CommOS_Kmalloc(optLen);
- if (!optBuf) {
- pvsk->rpcStatus = -EINVAL;
- goto out;
- }
-
- if (packet->data32 == SOL_TCP) {
- /*
- * See comment in PvtcpSetSockOptOp() regarding special treatment for
- * the TCP_NODELAY and TCP_CORK settings.
- */
-
- int on;
-
- switch (packet->data32ex) {
- case TCP_NODELAY:
- on = PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_TCP_NODELAY);
- optLen = sizeof on;
- memcpy(optBuf, &on, optLen);
- goto done;
- case TCP_CORK:
- on = PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_TCP_CORK);
- optLen = sizeof on;
- memcpy(optBuf, &on, optLen);
- goto done;
- }
- }
-
- rc = kernel_getsockopt(sock, packet->data32,
- packet->data32ex, optBuf, &optLen);
-
-done:
- if (!rc) {
- pvsk->rpcReply = optBuf;
- CommOS_MemBarrier();
- pvsk->rpcStatus = (int)optLen;
- } else {
- CommOS_Kfree(optBuf);
- pvsk->rpcStatus = rc;
- }
-
-out:
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
- PvskSetOpFlag(pvsk, PVTCP_OP_GETSOCKOPT);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Performs ioctl on offload socket.
- * @param channel communication channel with offloader
- * @param state state associated with this channel
- * @param packet packet header received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- */
-
-void
-PvtcpIoctlOp(CommChannel channel,
- void *state,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, state);
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
-
- PvtcpHoldSock(pvsk);
-
- /* Not implemented yet. */
-
- (void)sock;
- pvsk->rpcStatus = -ENOIOCTLCMD;
-
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
- PvskSetOpFlag(pvsk, PVTCP_OP_IOCTL);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Marks a socket for listening to incoming connections
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back
- */
-
-void
-PvtcpListenOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- int backlog = (int)packet->data32;
-
- PvtcpHoldSock(pvsk);
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
-
- pvsk->err = -kernel_listen(sk->sk_socket, backlog);
- PvskSetOpFlag(pvsk, PVTCP_OP_LISTEN);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Accepts a connected socket
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back.
- */
-
-void
-PvtcpAcceptOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- int rc;
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *newsock = NULL;
-
- PvtcpHoldSock(pvsk);
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
-
- rc = kernel_accept(sk->sk_socket, &newsock, O_NONBLOCK);
- if (rc == 0) {
- rc = SockAllocInit(newsock, channel, packet->data64ex, pvsk);
- if (rc) {
- SockReleaseWrapper(newsock);
- }
- }
-
- if (rc == 0) {
- struct sock *newsk = newsock->sk;
- PvtcpSock *newpvsk = PvskFromSk(newsk);
-
- /* We temporarily use the state field to cache parent socket. */
-
- newpvsk->state = (PvtcpState *)pvsk;
- PvskSetOpFlag(newpvsk, PVTCP_OP_ACCEPT);
- PvtcpSchedSock(newpvsk);
- } else {
- pvsk->err = -rc;
- PvskSetOpFlag(pvsk, PVTCP_OP_ACCEPT);
- PvtcpSchedSock(pvsk);
- }
-
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Connects an offload socket to given address
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect A writer task is scheduled, which will send reply back
- */
-
-void
-PvtcpConnectOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- struct sock *sk = SkFromPvsk(pvsk);
- struct sockaddr *addr;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- int addrLen;
- int flags = 0;
- int rc = 0;
- int disconnect = 0;
-
- PvtcpHoldSock(pvsk);
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
-
- if (sk->sk_family == AF_INET) {
- addr = (struct sockaddr *)&sin;
- addrLen = sizeof sin;
- memset(&sin, 0, sizeof sin);
- sin.sin_port = packet->data16;
- sin.sin_addr.s_addr = (unsigned int)packet->data64ex;
- if (COMM_OPF_GET_VAL(packet->flags)) {
- sin.sin_family = AF_UNSPEC;
- disconnect = 1;
- goto connect;
- }
- sin.sin_family = AF_INET;
- PvtcpTestAndBindLoopbackInet4(pvsk, &sin.sin_addr.s_addr, 0);
- } else { /* AF_INET6 */
- addr = (struct sockaddr *)&sin6;
- addrLen = sizeof sin6;
- memset(&sin6, 0, sizeof sin6);
- sin6.sin6_port = packet->data16;
- if (COMM_OPF_GET_VAL(packet->flags)) {
- sin6.sin6_family = AF_UNSPEC;
- PvtcpI6AddrUnpack(&sin6.sin6_addr.s6_addr32[0],
- packet->data64ex, packet->data64ex2);
- disconnect = 1;
- goto connect;
- }
- sin6.sin6_family = AF_INET6;
- PvtcpTestAndBindLoopbackInet6(pvsk, &packet->data64ex,
- &packet->data64ex2, 0);
- PvtcpI6AddrUnpack(&sin6.sin6_addr.s6_addr32[0],
- packet->data64ex, packet->data64ex2);
- }
-
-connect:
- rc = kernel_connect(sk->sk_socket, addr, addrLen, flags | O_NONBLOCK);
-
- /*
- * For datagram sockets, ErrorReportCB is not called, so we need to
- * explicitly set the pvsk error to be returned back to the guest.
- * This should not be used on SOCK_STREAM sockets. You have been
- * warned.
- */
-
- if (rc && (sk->sk_socket->type == SOCK_DGRAM)) {
- pvsk->err = -rc;
- }
-
- /*
- * Quite likely, stream actual connect requests will set err to EINPROGRESS.
- * That's fine, error_report will trigger an AIO/flow-op reply. When the
- * connection is established, state_change schedules an AIO/connect reply.
- * Record whether the request was a disconnect.
- */
-
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_DISCONNECT, disconnect);
- PvskSetOpFlag(pvsk, PVTCP_OP_CONNECT);
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/**
- * @brief Initiates socket shutdown on an offload socket
- * @param channel communication channel with offloader
- * @param upperLayerState state associated with this channel
- * @param packet first packet received in reply
- * @param vec payload buffer descriptors
- * @param vecLen payload buffer descriptor count
- * @sideeffect Socket queue will be drained and socket shutdown performed.
- */
-
-void
-PvtcpShutdownOp(CommChannel channel,
- void *upperLayerState,
- CommPacket *packet,
- struct kvec *vec,
- unsigned int vecLen)
-{
- PvtcpSock *pvsk = PvtcpGetPvskOrReturn(packet->data64, upperLayerState);
- int how = (int)packet->data32;
-
- PvtcpHoldSock(pvsk);
- if ((how == SHUT_RD) || (how == SHUT_RDWR)) {
- kernel_sock_shutdown(SkFromPvsk(pvsk)->sk_socket, SHUT_RD);
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_RD, 1);
- }
- if ((how == SHUT_WR) || (how == SHUT_RDWR)) {
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_SHUT_WR, 1);
- }
- PVTCP_UNLOCK_DISP_DISCARD_VEC();
- PvtcpSchedSock(pvsk);
- PvtcpPutSock(pvsk);
-}
-
-
-/*
- * AIO functions called from the main AIO processing function.
- * Most of these functions complete processing initiated by the corresponding
- * offload operations above.
- */
-
-/**
- * @brief Processes socket release in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket to release.
- * @sideeffect the socket will be released upon return from this function.
- */
-
-static inline void
-ReleaseAIO(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- CommPacket packet = {
- .len = sizeof packet,
- .flags = 0,
- .opCode = PVTCP_OP_RELEASE,
- .data64 = pvsk->peerSock,
- .data64ex = PvtcpGetHandle(pvsk)
- };
- unsigned long long timeout = COMM_MAX_TO;
-
- SOCK_OUT_LOCK(pvsk);
- CommSvc_Write(pvsk->channel, &packet, &timeout);
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sent 'Release' [0x%p] -> 0x%0x] reply.\n",
- __FUNCTION__, pvsk, (unsigned)(pvsk->peerSock)));
-#endif
- /*
- * 'sk' goes away in the final ProcessAIO::sock_put()
- */
- SockReleaseWrapper(sock);
- SOCK_OUT_UNLOCK(pvsk);
-
- PvtcpStateRemoveSocket(pvsk->channel, pvsk);
-}
-
-
-/**
- * @brief Processes socket create reply in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk newly created socket to send ack for.
- */
-
-static inline void
-CreateAIO(PvtcpSock *pvsk)
-{
- struct sock *sk;
- struct socket *sock;
- CommPacket packet = {
- .len = sizeof packet,
- .flags = 0,
- .opCode = PVTCP_OP_CREATE,
- .data64 = pvsk->peerSock,
- };
- unsigned long long timeout = COMM_MAX_TO;
- int rc;
-
- sk = SkFromPvsk(pvsk);
- if (!sk) {
- /*
- * This is a create-error socket. The error reply has been sent out
- * already, by PvtcpFlowAIO(). This is a paranoid safety measure, as
- * PVTCP_OP_CREATE OpFlag should not have been set.
- */
-
- return;
- }
-
- sock = sk->sk_socket;
- packet.data64ex = PvtcpGetHandle(pvsk);
-
- rc = CommSvc_Write(pvsk->channel, &packet, &timeout);
- if (rc != packet.len) {
- /* We mustn't leak it if PV can't get a hold of it. */
-
- PvtcpStateRemoveSocket(pvsk->channel, pvsk);
- SockReleaseWrapper(sock);
- CommOS_Log(("%s: BOOG -- Couldn't send 'Create' reply [0x%p]!\n",
- __FUNCTION__, sk));
- } else {
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sent 'Create' [0x%p] reply [%d].\n",
- __FUNCTION__, pvsk, rc));
-#endif
- }
-}
-
-
-/**
- * @brief Processes socket bind in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket being bound.
- */
-
-static inline void
-BindAIO(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- CommPacket packet = {
- .len = sizeof packet,
- .flags = 0,
- .opCode = PVTCP_OP_BIND,
- .data64 = pvsk->peerSock
- };
- unsigned long long timeout = COMM_MAX_TO;
- int rc;
-
- if (pvsk->peerSockSet) {
- if (sk->sk_family == AF_INET) {
- struct sockaddr_in sin = { .sin_family = AF_INET };
- int addrLen = sizeof sin;
-
- rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &addrLen);
- if (rc == 0) {
- packet.data16 = sin.sin_port;
- PvtcpResetLoopbackInet4(pvsk, &sin.sin_addr.s_addr);
- packet.data64ex = (unsigned long long)sin.sin_addr.s_addr;
- }
- } else { /* AF_INET6 */
- struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
- int addrLen = sizeof sin;
-
- rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &addrLen);
- if (rc == 0) {
- packet.data16 = sin.sin6_port;
- PvtcpResetLoopbackInet6(pvsk, &sin.sin6_addr);
- PvtcpI6AddrPack(&sin.sin6_addr.s6_addr32[0],
- &packet.data64ex, &packet.data64ex2);
- }
- }
-
- if (rc) {
- COMM_OPF_SET_ERR(packet.flags);
- packet.data32ex = (unsigned int)(-rc);
- packet.opCode = PVTCP_OP_FLOW;
- }
- CommSvc_Write(pvsk->channel, &packet, &timeout);
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sent 'Bind' [0x%p, %d] reply.\n",
- __FUNCTION__, pvsk, rc));
-#endif
- }
-}
-
-
-/**
- * @brief Sends result of setsockopt back to guest.
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket that was modified.
- */
-
-static inline void
-SetSockOptAIO(PvtcpSock *pvsk)
-{
- CommPacket packet;
- unsigned long long timeout;
-
- packet.len = sizeof packet;
- packet.flags = 0;
- packet.opCode = PVTCP_OP_SETSOCKOPT;
- packet.data64 = pvsk->peerSock;
- packet.data32 = (unsigned int)(pvsk->rpcStatus);
- timeout = COMM_MAX_TO;
- CommSvc_Write(pvsk->channel, &packet, &timeout);
- pvsk->rpcStatus = 0;
-}
-
-
-/**
- * @brief Sends result of getsockopt back to guest.
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket that was modified.
- */
-
-static inline void
-GetSockOptAIO(PvtcpSock *pvsk)
-{
- CommPacket packet = {
- .opCode = PVTCP_OP_GETSOCKOPT,
- .flags = 0
- };
- unsigned long long timeout = COMM_MAX_TO;
-
- struct kvec vec[1];
- struct kvec *inVec = vec;
- unsigned int vecLen = 1;
- unsigned int iovOffset = 0;
-
- if (pvsk->rpcStatus > 0) {
- packet.len = sizeof packet + pvsk->rpcStatus;
- vec[0].iov_base = pvsk->rpcReply;
- vec[0].iov_len = pvsk->rpcStatus;
- } else {
- vecLen = 0;
- }
-
- packet.data64 = pvsk->peerSock;
- packet.data32 = pvsk->rpcStatus;
-
- CommSvc_WriteVec(pvsk->channel, &packet, &inVec, &vecLen,
- &timeout, &iovOffset);
-
- if (pvsk->rpcReply) {
- CommOS_Kfree(pvsk->rpcReply);
- pvsk->rpcReply = NULL;
- }
- pvsk->rpcStatus = 0;
-}
-
-
-/**
- * @brief Sends result of ioctl back to guest.
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket that was modified.
- */
-
-static inline void
-IoctlAIO(PvtcpSock *pvsk)
-{
- CommPacket packet = {
- .len = sizeof packet,
- .opCode = PVTCP_OP_IOCTL,
- .flags = 0
- };
- unsigned long long timeout = COMM_MAX_TO;
-
- packet.data64 = pvsk->peerSock;
- packet.data32 = pvsk->rpcStatus;
- CommSvc_Write(pvsk->channel, &packet, &timeout);
- pvsk->rpcStatus = 0;
-}
-
-
-/**
- * @brief Processes socket listen reply in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket being put in listen mode.
- */
-
-static inline void
-ListenAIO(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
- CommPacket packet = {
- .len = sizeof packet,
- .flags = 0,
- .opCode = PVTCP_OP_LISTEN,
- .data64 = pvsk->peerSock
- };
- unsigned long long timeout = COMM_MAX_TO;
-
- if (pvsk->peerSockSet) {
- if (sk->sk_state != TCP_LISTEN) {
- COMM_OPF_SET_ERR(packet.flags);
- packet.data32ex = (unsigned int)pvsk->err;
- packet.opCode = PVTCP_OP_FLOW;
- }
-
- CommSvc_Write(pvsk->channel, &packet, &timeout);
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sent 'Listen' [0x%p] reply.\n", __FUNCTION__, pvsk));
-#endif
- }
-}
-
-
-/**
- * @brief Processes socket accept reply in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk new socket or socket to accept on (see PvtcpAcceptOp).
- */
-
-static inline void
-AcceptAIO(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- CommPacket packet = {
- .len = sizeof packet,
- .flags = 0,
- .opCode = PVTCP_OP_ACCEPT
- };
- unsigned long long timeout = COMM_MAX_TO;
- const int enable = 1;
- int rc;
-
- if (pvsk->peerSockSet) {
- unsigned long long payloadSocks[2] = { 0, 0 };
- struct kvec payloadVec[] = {
- { .iov_base = &payloadSocks, .iov_len = sizeof payloadSocks }
- };
- struct kvec *payload = payloadVec;
- unsigned int payloadLen = 1;
- unsigned int iovOffset = 0;
-
- packet.len = sizeof packet + sizeof payloadSocks;
-
- /*
- * accept() succeeded, so this is the child socket; its state field
- * was temporarily changed to hold the parent/accepting socket.
- * The newly accepted socket and its peer need to be put in a
- * payload since we use up all available header fields with
- * addressing information. Finally, the state field is restored.
- */
-
- packet.data64 = ((PvtcpSock *)pvsk->state)->peerSock;
- pvsk->state = CommSvc_GetState(pvsk->channel);
-
- payloadSocks[0] = pvsk->peerSock;
- payloadSocks[1] = PvtcpGetHandle(pvsk);
-
- rc = 0;
- if (sk->sk_family == AF_INET) {
- struct sockaddr_in sin = { .sin_family = AF_INET };
- int addrLen = sizeof sin;
-
- rc = kernel_getpeername(sock, (struct sockaddr *)&sin, &addrLen);
- if (rc == 0) {
- packet.data16 = sin.sin_port;
- PvtcpResetLoopbackInet4(pvsk, &sin.sin_addr.s_addr);
- packet.data64ex = (unsigned long long)sin.sin_addr.s_addr;
- }
- } else { /* AF_INET6 */
- struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
- int addrLen = sizeof sin;
-
- rc = kernel_getpeername(sock, (struct sockaddr *)&sin, &addrLen);
- if (rc == 0) {
- packet.data16 = sin.sin6_port;
- PvtcpResetLoopbackInet6(pvsk, &sin.sin6_addr);
- PvtcpI6AddrPack(&sin.sin6_addr.s6_addr32[0],
- &packet.data64ex, &packet.data64ex2);
- }
- }
-
- if (rc == 0) {
- kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
- (void *)&enable, sizeof enable);
- kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
- (void *)&enable, sizeof enable);
- kernel_setsockopt(sock, SOL_SOCKET, SO_OOBINLINE,
- (void *)&enable, sizeof enable);
- } else {
- PvtcpStateRemoveSocket(pvsk->channel, pvsk);
- SockReleaseWrapper(sock);
- COMM_OPF_SET_ERR(packet.flags);
- packet.data32ex = (unsigned int)ECONNABORTED;
- packet.len = sizeof packet;
- packet.opCode = PVTCP_OP_FLOW;
- }
-
- rc = CommSvc_WriteVec(pvsk->channel, &packet,
- &payload, &payloadLen, &timeout, &iovOffset);
- if ((rc != packet.len) && !COMM_OPF_TEST_ERR(packet.flags)) {
- /* Mustn't leak the new socket if PV can't get a hold of it. */
-
- PvtcpStateRemoveSocket(pvsk->channel, pvsk);
- SockReleaseWrapper(sock);
- }
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sent 'Accept' [0x%p] reply.\n", __FUNCTION__, pvsk));
-#endif
- }
-}
-
-
-/**
- * @brief Processes socket connect in an AIO thread. This function is
- * called with the socket 'in' lock taken.
- * @param[in,out] pvsk socket being connected.
- */
-
-static inline void
-ConnectAIO(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
- struct socket *sock = sk->sk_socket;
- CommPacket packet = {
- .len = sizeof packet,
- .flags = 0,
- .opCode = PVTCP_OP_CONNECT,
- .data64 = pvsk->peerSock
- };
- unsigned long long timeout = COMM_MAX_TO;
- const int enable = 1;
- int rc;
-
- if (!pvsk->peerSockSet ||
- (!PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_DISCONNECT) &&
- (sk->sk_state != TCP_ESTABLISHED))) {
- return;
- }
-
- if (PvskTestFlag(pvsk, PVTCP_OFF_PVSKF_DISCONNECT)) {
- COMM_OPF_SET_VAL(packet.flags, 1);
- PvskSetFlag(pvsk, PVTCP_OFF_PVSKF_DISCONNECT, 0);
- } else if (sk->sk_state == TCP_ESTABLISHED) {
- if (sk->sk_family == AF_INET) {
- struct sockaddr_in sin = { .sin_family = AF_INET };
- int addrLen = sizeof sin;
-
- rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &addrLen);
- if (rc == 0) {
- packet.data16 = sin.sin_port;
- PvtcpResetLoopbackInet4(pvsk, &sin.sin_addr.s_addr);
- packet.data64ex = (unsigned long long)sin.sin_addr.s_addr;
- }
- } else { /* AF_INET6 */
- struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
- int addrLen = sizeof sin;
-
- rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &addrLen);
- if (rc == 0) {
- packet.data16 = sin.sin6_port;
- PvtcpResetLoopbackInet6(pvsk, &sin.sin6_addr);
- PvtcpI6AddrPack(&sin.sin6_addr.s6_addr32[0],
- &packet.data64ex, &packet.data64ex2);
- }
- }
-
- if (rc == 0) {
- kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
- (void *)&enable, sizeof enable);
- kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
- (void *)&enable, sizeof enable);
- kernel_setsockopt(sock, SOL_SOCKET, SO_OOBINLINE,
- (void *)&enable, sizeof enable);
- } else {
- COMM_OPF_SET_ERR(packet.flags);
- packet.data32ex = ECONNABORTED;
- packet.opCode = PVTCP_OP_FLOW;
- }
- }
-
- CommSvc_Write(pvsk->channel, &packet, &timeout);
-#if defined(PVTCP_FULL_DEBUG)
- CommOS_Debug(("%s: Sent 'Connect' [0x%p] reply.\n", __FUNCTION__, pvsk));
-#endif
-}
-
-
-/**
- * @brief Server side main asynchronous processing function. It writes to
- * socket queued output buffers, it reads from socket and outputs to PV; it
- * also completes operation processing and sends applicable replies to PV.
- * Finally, processes error reporting and delta size acks.
- * @param arg socket work item.
- */
-
-void
-PvtcpProcessAIO(CommOSWork *arg)
-{
- PvtcpSock *pvsk = container_of(arg, PvtcpSock, work);
- struct sock *sk = SkFromPvsk(pvsk);
-
- if (!SOCK_OUT_TRYLOCK(pvsk)) {
- /*
- * Queued output processing. If trylock failed, we don't retry.
- * There are only two reasons for not being able to take the lock:
- * - IoOp() has it -- when done, it reschedules us if we're not running.
- * - OutputAIO() is already running on another core.
- */
-
- if (sk && sk->sk_socket) {
- PvtcpOutputAIO(pvsk);
- }
- SOCK_OUT_UNLOCK(pvsk);
- }
-
- /* All other processing needs the socket IN lock. */
-
- if (!SOCK_IN_TRYLOCK(pvsk)) {
-
- if (sk && sk->sk_socket) {
- int err;
-
- /* Input processing. */
-
- /*
- * Workqueue handlers are pinned to a CPU core and therefore not
- * migratable. No need to disable preemption.
- */
- err = PvtcpInputAIO(pvsk, perCpuBuf[smp_processor_id()]);
-
- /* Error and ack notifications. */
-
- PvtcpFlowAIO(pvsk, err);
-
- if (!pvsk->opFlags) {
- /* No other operations need to be completed. */
-
- goto doneInUnlock;
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_RELEASE)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_RELEASE);
- ReleaseAIO(pvsk);
-
- /* All possible in-flight operations must be dropped. */
- goto doneInUnlock;
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_CREATE)) {
- /* No state locking required. */
-
- PvskResetOpFlag(pvsk, PVTCP_OP_CREATE);
- CreateAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_BIND)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_BIND);
- BindAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_SETSOCKOPT)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_SETSOCKOPT);
- SetSockOptAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_GETSOCKOPT)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_GETSOCKOPT);
- GetSockOptAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_IOCTL)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_IOCTL);
- IoctlAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_LISTEN)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_LISTEN);
- ListenAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_ACCEPT)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_ACCEPT);
- AcceptAIO(pvsk);
- }
-
- if (PvskTestOpFlag(pvsk, PVTCP_OP_CONNECT)) {
- PvskResetOpFlag(pvsk, PVTCP_OP_CONNECT);
- ConnectAIO(pvsk);
- }
-
-doneInUnlock:
- SOCK_IN_UNLOCK(pvsk);
- } else {
- /*
- * Special case for error sockets which don't have a sk.
- * Note that this socket was created by SockAllocErrInit() and so
- * no 'real' socket sits atop it and is not present on any state
- * netif list. The socket has a refcnt of one and it will get
- * deallocated by the PvtcpPutSock() call below, so we don't need
- * to unlock it.
- */
-
- PvtcpFlowAIO(pvsk, -ENETDOWN);
- }
- } else {
- if ((pvsk->peerSockSet || PvskTestOpFlag(pvsk, PVTCP_OP_RELEASE)) &&
- sk && sk->sk_socket) {
- PvtcpSchedSock(pvsk);
- }
- }
-
- PvtcpPutSock(pvsk);
-}
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp_off_linux.h b/arch/arm/mvp/pvtcpkm/pvtcp_off_linux.h
deleted file mode 100644
index 34992da..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp_off_linux.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief Linux Offload definitions.
- * This file is only meant to be included via pvtcp_off.h.
- */
-
-#ifndef _PVTCP_OFF_LINUX_H_
-#define _PVTCP_OFF_LINUX_H_
-
-#include <linux/socket.h>
-#include <net/sock.h>
-#include <net/tcp_states.h>
-#include <net/tcp.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/skbuff.h>
-#include <linux/random.h>
-#include <linux/fs.h>
-#include <linux/cred.h>
-
-
-typedef struct PvtcpSock {
- struct sock *sk;
- PVTCP_SOCK_COMMON_FIELDS;
- PVTCP_OFF_SOCK_COMMON_FIELDS;
- void (*destruct)(struct sock *sk);
- void (*stateChange)(struct sock *sk);
- void (*dataReady)(struct sock *sk, int bytes);
- void (*writeSpace)(struct sock *sk);
- void (*errorReport)(struct sock *sk);
-} PvtcpSock;
-
-
-typedef enum PvtcpSockNamespace {
- PVTCP_SOCK_NAMESPACE_INITIAL,
- PVTCP_SOCK_NAMESPACE_CHANNEL
-} PvtcpSockNamespace;
-
-
-/* Number of large datagram allocations. */
-extern unsigned long long pvtcpOffDgramAllocations;
-
-/* Inet4 loopback addresses. */
-extern unsigned int pvtcpLoopbackOffAddr;
-
-/* Get the 'struct sock' from a PvtcpSock. */
-#define SkFromPvsk(pvsk) ((pvsk)->sk)
-
-/* Get the PvtcpSock from a 'struct sock'. */
-#define PvskFromSk(sk) ((PvtcpSock *)(sk)->sk_user_data)
-
-int
-PvtcpTestAndBindLoopbackInet4(PvtcpSock *pvsk,
- unsigned int *addr,
- unsigned short port);
-int
-PvtcpTestAndBindLoopbackInet6(PvtcpSock *pvsk,
- unsigned long long *addr0,
- unsigned long long *addr1,
- unsigned short port);
-
-void PvtcpResetLoopbackInet4(PvtcpSock *pvsk, unsigned int *addr);
-void PvtcpResetLoopbackInet6(PvtcpSock *pvsk, struct in6_addr *in6);
-
-void PvtcpFlowAIO(PvtcpSock *pvsk, int eof);
-void PvtcpOutputAIO(PvtcpSock *pvsk);
-int PvtcpInputAIO(PvtcpSock *pvsk, void *perCpuBuf);
-
-
-/**
- * @brief Switches a socket to the channel, or the initial name space.
- * @param pvsk socket to switch.
- * @param ns which namespace to switch to.
- */
-
-static inline void
-PvtcpSwitchSock(PvtcpSock *pvsk,
- PvtcpSockNamespace ns)
-{
-#if defined(CONFIG_NET_NS) && !defined(PVTCP_NET_NS_DISABLE)
- struct sock *sk;
- struct net *prevNet;
-
- if (!pvsk) {
- return;
- }
- sk = SkFromPvsk(pvsk);
- if (!sk) {
- /* If this is a phony, create fail reporting pvsk, just return. */
-
- return;
- }
-
- prevNet = sock_net(sk);
- switch (ns) {
- case PVTCP_SOCK_NAMESPACE_INITIAL:
- sock_net_set(sk, get_net(&init_net));
- break;
- case PVTCP_SOCK_NAMESPACE_CHANNEL:
- sock_net_set(sk, get_net(pvsk->state->namespace));
- break;
- }
- put_net(prevNet);
-#endif
-}
-
-
-/**
- * @brief Tests whether a socket has an explicit namespace.
- * @param pvsk socket to test.
- * @return 1 if the socket has a namespace, 0 otherwise.
- */
-
-static inline int
-PvtcpHasSockNamespace(PvtcpSock *pvsk)
-{
-#if defined(CONFIG_NET_NS) && !defined(PVTCP_NET_NS_DISABLE)
- struct sock *sk;
- int rc = 0;
-
- if (!pvsk) {
- return rc;
- }
- sk = SkFromPvsk(pvsk);
- if (!sk) {
- /* If this is a phony, create fail reporting pvsk, just return 0. */
-
- return rc;
- }
-
- rc = (sock_net(sk) != &init_net);
- return rc;
-#else
- return 0;
-#endif
-}
-
-
-/**
- * @brief Retains the pvsock's underlying socket.
- * @param pvsk socket to retain.
- */
-
-static inline void
-PvtcpHoldSock(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
-
- if (likely(sk)) {
- sock_hold(sk);
- }
-}
-
-
-/**
- * @brief Releases a hold on the pvsock's underlying socket. If the underlying
- * socket is NULL, this is an error socket and we deallocate it.
- * @param pvsk socket to release hold on.
- */
-
-static inline void
-PvtcpPutSock(PvtcpSock *pvsk)
-{
- struct sock *sk = SkFromPvsk(pvsk);
-
- if (likely(sk)) {
- sock_put(sk);
- } else {
- /*
- * This is an error socket, which does _not_ have an underlying socket.
- * We simply need to free it.
- */
-
- CommOS_Kfree(pvsk);
- }
-}
-
-
-/**
- * @brief Schedules an offload socket for AIO.
- * @param pvsk socket to schedule.
- * @sideeffect the socket will be processed by AIO threads.
- */
-
-static inline void
-PvtcpSchedSock(PvtcpSock *pvsk)
-{
- /*
- * We must hold the socket before we enqueue it for AIO, such that it may
- * not be released while in the workqueue. If CommSvc_ScheduleAIOWork()
- * returned non-zero, it means the socket had already been enqueued. In
- * that case, we release the hold. Otherwise, the hold is released by the
- * AIO function (PvtcpProcessAIO()).
- * Note that error pv sockets may only originate from synchronized RPCs,
- * or to be more precise, from PvtcpCreateOp(), and not from IO processing;
- * this means that they cannot be attempted to be enqueued more than once.
- */
-
- PvtcpHoldSock(pvsk);
- if (CommSvc_ScheduleAIOWork(&pvsk->work)) {
- PvtcpPutSock(pvsk);
- }
-}
-
-#endif // _PVTCP_OFF_LINUX_H_
diff --git a/arch/arm/mvp/pvtcpkm/pvtcp_off_linux_shim.S b/arch/arm/mvp/pvtcpkm/pvtcp_off_linux_shim.S
deleted file mode 100644
index 824286b..0000000
--- a/arch/arm/mvp/pvtcpkm/pvtcp_off_linux_shim.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
- *
- * Copyright (C) 2010-2012 VMware, Inc. 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief PVTCP socket destructor shim.
- *
- * The module reference accounting code for socket destruction in the core
- * Linux kernel does not know about PVTCP sockets, so it does not properly
- * increment/decrement the reference count on pvtcpkm when calling through a
- * function pointer into our destructor. If a module unload is requested on
- * pvtcpkm while a socket is being destroyed, it is possible for the destructor
- * to be preempted after decrementing the module reference count but before
- * returning to the core kernel. If the module code is unmapped before the
- * function return, it is possible that we will attempt to execute unmapped
- * code, resulting in a host crash.
- *
- * This shim proxies socket destruction requests through to the PVTCP socket
- * destructor, then jumps directly to module_put to drop the reference count.
- * module_put will return directly to the caller, eliminating the race.
- */
-
-.text
-.p2align 4
-
-.global asmDestructorShim
-
-/**
- * @brief Socket destructor callback. Calls into pvtcpkm to destroy a socket
- * and then decrements the refcount.
- * @param r0 pointer to struct sock
- */
-
-asmDestructorShim:
- push {lr}
- ldr r1, targetAddr @ Destroy socket
- blx r1
- pop {lr}
- cmp r0, #0
- bxne lr @ We shouldn't module_put, just return.
- ldr r0, owner
- ldr r1, modulePutAddr @ Jump to module_put. module_put
- bx r1 @ returns directly to caller
-
-owner:
- .word __this_module
-
-targetAddr:
- .word DestructCB
-
-modulePutAddr:
- .word module_put
diff --git a/block/genhd.c b/block/genhd.c
index 6ece7ab..6c93aa1 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -831,6 +831,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v)
if (iter) {
class_dev_iter_exit(iter);
kfree(iter);
+ seqf->private = NULL;
}
}
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 0d12110..efd8816 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -865,6 +865,22 @@ config CRYPTO_LZO
help
This is the LZO algorithm.
+config CRYPTO_LZ4
+ tristate "LZ4 compression algorithm"
+ select CRYPTO_ALGAPI
+ select LZ4_COMPRESS
+ select LZ4_DECOMPRESS
+ help
+ This is the LZ4 algorithm.
+
+config CRYPTO_LZ4HC
+ tristate "LZ4HC compression algorithm"
+ select CRYPTO_ALGAPI
+ select LZ4HC_COMPRESS
+ select LZ4_DECOMPRESS
+ help
+ This is the LZ4 high compression mode algorithm.
+
comment "Random Number Generation"
config CRYPTO_ANSI_CPRNG
diff --git a/crypto/Makefile b/crypto/Makefile
index 69c46ed..a6c3035 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -85,6 +85,8 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
+obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
obj-$(CONFIG_CRYPTO_RNG2) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
diff --git a/crypto/lz4.c b/crypto/lz4.c
new file mode 100644
index 0000000..34d072b
--- /dev/null
+++ b/crypto/lz4.c
@@ -0,0 +1,106 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2013 Chanho Min <chanho.min@lge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/lz4.h>
+
+struct lz4_ctx {
+ void *lz4_comp_mem;
+};
+
+static int lz4_init(struct crypto_tfm *tfm)
+{
+ struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->lz4_comp_mem = vmalloc(LZ4_MEM_COMPRESS);
+ if (!ctx->lz4_comp_mem)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void lz4_exit(struct crypto_tfm *tfm)
+{
+ struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+ vfree(ctx->lz4_comp_mem);
+}
+
+static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+ size_t tmp_len = *dlen;
+ int err;
+
+ err = lz4_compress(src, slen, dst, &tmp_len, ctx->lz4_comp_mem);
+
+ if (err < 0)
+ return -EINVAL;
+
+ *dlen = tmp_len;
+ return 0;
+}
+
+static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ int err;
+ size_t tmp_len = *dlen;
+ size_t __slen = slen;
+
+ err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
+ if (err < 0)
+ return -EINVAL;
+
+ *dlen = tmp_len;
+ return err;
+}
+
+static struct crypto_alg alg_lz4 = {
+ .cra_name = "lz4",
+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+ .cra_ctxsize = sizeof(struct lz4_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg_lz4.cra_list),
+ .cra_init = lz4_init,
+ .cra_exit = lz4_exit,
+ .cra_u = { .compress = {
+ .coa_compress = lz4_compress_crypto,
+ .coa_decompress = lz4_decompress_crypto } }
+};
+
+static int __init lz4_mod_init(void)
+{
+ return crypto_register_alg(&alg_lz4);
+}
+
+static void __exit lz4_mod_fini(void)
+{
+ crypto_unregister_alg(&alg_lz4);
+}
+
+module_init(lz4_mod_init);
+module_exit(lz4_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4 Compression Algorithm");
diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c
new file mode 100644
index 0000000..9218b3f
--- /dev/null
+++ b/crypto/lz4hc.c
@@ -0,0 +1,106 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2013 Chanho Min <chanho.min@lge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/lz4.h>
+
+struct lz4hc_ctx {
+ void *lz4hc_comp_mem;
+};
+
+static int lz4hc_init(struct crypto_tfm *tfm)
+{
+ struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->lz4hc_comp_mem = vmalloc(LZ4HC_MEM_COMPRESS);
+ if (!ctx->lz4hc_comp_mem)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void lz4hc_exit(struct crypto_tfm *tfm)
+{
+ struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ vfree(ctx->lz4hc_comp_mem);
+}
+
+static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+ size_t tmp_len = *dlen;
+ int err;
+
+ err = lz4hc_compress(src, slen, dst, &tmp_len, ctx->lz4hc_comp_mem);
+
+ if (err < 0)
+ return -EINVAL;
+
+ *dlen = tmp_len;
+ return 0;
+}
+
+static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ int err;
+ size_t tmp_len = *dlen;
+ size_t __slen = slen;
+
+ err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
+ if (err < 0)
+ return -EINVAL;
+
+ *dlen = tmp_len;
+ return err;
+}
+
+static struct crypto_alg alg_lz4hc = {
+ .cra_name = "lz4hc",
+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+ .cra_ctxsize = sizeof(struct lz4hc_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg_lz4hc.cra_list),
+ .cra_init = lz4hc_init,
+ .cra_exit = lz4hc_exit,
+ .cra_u = { .compress = {
+ .coa_compress = lz4hc_compress_crypto,
+ .coa_decompress = lz4hc_decompress_crypto } }
+};
+
+static int __init lz4hc_mod_init(void)
+{
+ return crypto_register_alg(&alg_lz4hc);
+}
+
+static void __exit lz4hc_mod_fini(void)
+{
+ crypto_unregister_alg(&alg_lz4hc);
+}
+
+module_init(lz4hc_mod_init);
+module_exit(lz4hc_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4HC Compression Algorithm");
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 717d6e4..b7ac932 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -116,6 +116,8 @@ config PARIDE
source "drivers/block/paride/Kconfig"
+source "drivers/block/zram/Kconfig"
+
config BLK_CPQ_DA
tristate "Compaq SMART2 support"
depends on PCI && VIRT_TO_BUS
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 76646e9..edc9543 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -40,4 +40,5 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += xen-blkback/
obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
+obj-$(CONFIG_ZRAM) += zram/
swim_mod-y := swim.o swim_asm.o
diff --git a/drivers/staging/zram/Kconfig b/drivers/block/zram/Kconfig
index 06f741a..0f95557 100644
--- a/drivers/staging/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -1,11 +1,6 @@
-config XVMALLOC
- bool
- default n
-
config ZRAM
tristate "Compressed RAM block device support"
- depends on BLOCK && SYSFS
- select XVMALLOC
+ depends on BLOCK && SYSFS && ZSMALLOC
select LZO_COMPRESS
select LZO_DECOMPRESS
default n
@@ -19,7 +14,17 @@ config ZRAM
disks and maybe many more.
See zram.txt for more information.
- Project home: http://compcache.googlecode.com/
+ Project home: <https://compcache.googlecode.com/>
+
+config ZRAM_LZ4_COMPRESS
+ bool "Enable LZ4 algorithm support"
+ depends on ZRAM
+ select LZ4_COMPRESS
+ select LZ4_DECOMPRESS
+ default n
+ help
+ This option enables LZ4 compression algorithm support. Compression
+ algorithm can be changed using `comp_algorithm' device attribute.
config ZRAM_DEBUG
bool "Compressed RAM block device debug support"
@@ -28,10 +33,3 @@ config ZRAM_DEBUG
help
This option adds additional debugging code to the compressed
RAM block device driver.
-
-config ZRAM_FOR_ANDROID
- bool "Optimize zram behavior for android"
- depends on ZRAM && ANDROID
- default n
- help
- This option enables modified zram behavior optimized for android
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
new file mode 100644
index 0000000..be0763f
--- /dev/null
+++ b/drivers/block/zram/Makefile
@@ -0,0 +1,5 @@
+zram-y := zcomp_lzo.o zcomp.o zram_drv.o
+
+zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o
+
+obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
new file mode 100644
index 0000000..54d946a
--- /dev/null
+++ b/drivers/block/zram/zcomp.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * 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/string.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "zcomp.h"
+#include "zcomp_lzo.h"
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+#include "zcomp_lz4.h"
+#endif
+
+/*
+ * single zcomp_strm backend
+ */
+struct zcomp_strm_single {
+ struct mutex strm_lock;
+ struct zcomp_strm *zstrm;
+};
+
+/*
+ * multi zcomp_strm backend
+ */
+struct zcomp_strm_multi {
+ /* protect strm list */
+ spinlock_t strm_lock;
+ /* max possible number of zstrm streams */
+ int max_strm;
+ /* number of available zstrm streams */
+ int avail_strm;
+ /* list of available strms */
+ struct list_head idle_strm;
+ wait_queue_head_t strm_wait;
+};
+
+static struct zcomp_backend *backends[] = {
+ &zcomp_lzo,
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+ &zcomp_lz4,
+#endif
+ NULL
+};
+
+static struct zcomp_backend *find_backend(const char *compress)
+{
+ int i = 0;
+ while (backends[i]) {
+ if (sysfs_streq(compress, backends[i]->name))
+ break;
+ i++;
+ }
+ return backends[i];
+}
+
+static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+ if (zstrm->private)
+ comp->backend->destroy(zstrm->private);
+ free_pages((unsigned long)zstrm->buffer, 1);
+ kfree(zstrm);
+}
+
+/*
+ * allocate new zcomp_strm structure with ->private initialized by
+ * backend, return NULL on error
+ */
+static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
+{
+ struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
+ if (!zstrm)
+ return NULL;
+
+ zstrm->private = comp->backend->create();
+ /*
+ * allocate 2 pages. 1 for compressed data, plus 1 extra for the
+ * case when compressed size is larger than the original one
+ */
+ zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+ if (!zstrm->private || !zstrm->buffer) {
+ zcomp_strm_free(comp, zstrm);
+ zstrm = NULL;
+ }
+ return zstrm;
+}
+
+/*
+ * get idle zcomp_strm or wait until other process release
+ * (zcomp_strm_release()) one for us
+ */
+static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
+{
+ struct zcomp_strm_multi *zs = comp->stream;
+ struct zcomp_strm *zstrm;
+
+ while (1) {
+ spin_lock(&zs->strm_lock);
+ if (!list_empty(&zs->idle_strm)) {
+ zstrm = list_entry(zs->idle_strm.next,
+ struct zcomp_strm, list);
+ list_del(&zstrm->list);
+ spin_unlock(&zs->strm_lock);
+ return zstrm;
+ }
+ /* zstrm streams limit reached, wait for idle stream */
+ if (zs->avail_strm >= zs->max_strm) {
+ spin_unlock(&zs->strm_lock);
+ wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
+ continue;
+ }
+ /* allocate new zstrm stream */
+ zs->avail_strm++;
+ spin_unlock(&zs->strm_lock);
+
+ zstrm = zcomp_strm_alloc(comp);
+ if (!zstrm) {
+ spin_lock(&zs->strm_lock);
+ zs->avail_strm--;
+ spin_unlock(&zs->strm_lock);
+ wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
+ continue;
+ }
+ break;
+ }
+ return zstrm;
+}
+
+/* add stream back to idle list and wake up waiter or free the stream */
+static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+ struct zcomp_strm_multi *zs = comp->stream;
+
+ spin_lock(&zs->strm_lock);
+ if (zs->avail_strm <= zs->max_strm) {
+ list_add(&zstrm->list, &zs->idle_strm);
+ spin_unlock(&zs->strm_lock);
+ wake_up(&zs->strm_wait);
+ return;
+ }
+
+ zs->avail_strm--;
+ spin_unlock(&zs->strm_lock);
+ zcomp_strm_free(comp, zstrm);
+}
+
+/* change max_strm limit */
+static bool zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm)
+{
+ struct zcomp_strm_multi *zs = comp->stream;
+ struct zcomp_strm *zstrm;
+
+ spin_lock(&zs->strm_lock);
+ zs->max_strm = num_strm;
+ /*
+ * if user has lowered the limit and there are idle streams,
+ * immediately free as much streams (and memory) as we can.
+ */
+ while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) {
+ zstrm = list_entry(zs->idle_strm.next,
+ struct zcomp_strm, list);
+ list_del(&zstrm->list);
+ zcomp_strm_free(comp, zstrm);
+ zs->avail_strm--;
+ }
+ spin_unlock(&zs->strm_lock);
+ return true;
+}
+
+static void zcomp_strm_multi_destroy(struct zcomp *comp)
+{
+ struct zcomp_strm_multi *zs = comp->stream;
+ struct zcomp_strm *zstrm;
+
+ while (!list_empty(&zs->idle_strm)) {
+ zstrm = list_entry(zs->idle_strm.next,
+ struct zcomp_strm, list);
+ list_del(&zstrm->list);
+ zcomp_strm_free(comp, zstrm);
+ }
+ kfree(zs);
+}
+
+static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
+{
+ struct zcomp_strm *zstrm;
+ struct zcomp_strm_multi *zs;
+
+ comp->destroy = zcomp_strm_multi_destroy;
+ comp->strm_find = zcomp_strm_multi_find;
+ comp->strm_release = zcomp_strm_multi_release;
+ comp->set_max_streams = zcomp_strm_multi_set_max_streams;
+ zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
+ if (!zs)
+ return -ENOMEM;
+
+ comp->stream = zs;
+ spin_lock_init(&zs->strm_lock);
+ INIT_LIST_HEAD(&zs->idle_strm);
+ init_waitqueue_head(&zs->strm_wait);
+ zs->max_strm = max_strm;
+ zs->avail_strm = 1;
+
+ zstrm = zcomp_strm_alloc(comp);
+ if (!zstrm) {
+ kfree(zs);
+ return -ENOMEM;
+ }
+ list_add(&zstrm->list, &zs->idle_strm);
+ return 0;
+}
+
+static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
+{
+ struct zcomp_strm_single *zs = comp->stream;
+ mutex_lock(&zs->strm_lock);
+ return zs->zstrm;
+}
+
+static void zcomp_strm_single_release(struct zcomp *comp,
+ struct zcomp_strm *zstrm)
+{
+ struct zcomp_strm_single *zs = comp->stream;
+ mutex_unlock(&zs->strm_lock);
+}
+
+static bool zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm)
+{
+ /* zcomp_strm_single support only max_comp_streams == 1 */
+ return false;
+}
+
+static void zcomp_strm_single_destroy(struct zcomp *comp)
+{
+ struct zcomp_strm_single *zs = comp->stream;
+ zcomp_strm_free(comp, zs->zstrm);
+ kfree(zs);
+}
+
+static int zcomp_strm_single_create(struct zcomp *comp)
+{
+ struct zcomp_strm_single *zs;
+
+ comp->destroy = zcomp_strm_single_destroy;
+ comp->strm_find = zcomp_strm_single_find;
+ comp->strm_release = zcomp_strm_single_release;
+ comp->set_max_streams = zcomp_strm_single_set_max_streams;
+ zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL);
+ if (!zs)
+ return -ENOMEM;
+
+ comp->stream = zs;
+ mutex_init(&zs->strm_lock);
+ zs->zstrm = zcomp_strm_alloc(comp);
+ if (!zs->zstrm) {
+ kfree(zs);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/* show available compressors */
+ssize_t zcomp_available_show(const char *comp, char *buf)
+{
+ ssize_t sz = 0;
+ int i = 0;
+
+ while (backends[i]) {
+ if (sysfs_streq(comp, backends[i]->name))
+ sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
+ "[%s] ", backends[i]->name);
+ else
+ sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
+ "%s ", backends[i]->name);
+ i++;
+ }
+ sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
+ return sz;
+}
+
+bool zcomp_set_max_streams(struct zcomp *comp, int num_strm)
+{
+ return comp->set_max_streams(comp, num_strm);
+}
+
+struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
+{
+ return comp->strm_find(comp);
+}
+
+void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+ comp->strm_release(comp, zstrm);
+}
+
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+ const unsigned char *src, size_t *dst_len)
+{
+ return comp->backend->compress(src, zstrm->buffer, dst_len,
+ zstrm->private);
+}
+
+int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
+ size_t src_len, unsigned char *dst)
+{
+ return comp->backend->decompress(src, src_len, dst);
+}
+
+void zcomp_destroy(struct zcomp *comp)
+{
+ comp->destroy(comp);
+ kfree(comp);
+}
+
+/*
+ * search available compressors for requested algorithm.
+ * allocate new zcomp and initialize it. return compressing
+ * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
+ * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
+ * case of allocation error, or any other error potentially
+ * returned by functions zcomp_strm_{multi,single}_create.
+ */
+struct zcomp *zcomp_create(const char *compress, int max_strm)
+{
+ struct zcomp *comp;
+ struct zcomp_backend *backend;
+ int error;
+
+ backend = find_backend(compress);
+ if (!backend)
+ return ERR_PTR(-EINVAL);
+
+ comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
+ if (!comp)
+ return ERR_PTR(-ENOMEM);
+
+ comp->backend = backend;
+ if (max_strm > 1)
+ error = zcomp_strm_multi_create(comp, max_strm);
+ else
+ error = zcomp_strm_single_create(comp);
+ if (error) {
+ kfree(comp);
+ return ERR_PTR(error);
+ }
+ return comp;
+}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
new file mode 100644
index 0000000..c59d1fc
--- /dev/null
+++ b/drivers/block/zram/zcomp.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * 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 _ZCOMP_H_
+#define _ZCOMP_H_
+
+#include <linux/mutex.h>
+
+struct zcomp_strm {
+ /* compression/decompression buffer */
+ void *buffer;
+ /*
+ * The private data of the compression stream, only compression
+ * stream backend can touch this (e.g. compression algorithm
+ * working memory)
+ */
+ void *private;
+ /* used in multi stream backend, protected by backend strm_lock */
+ struct list_head list;
+};
+
+/* static compression backend */
+struct zcomp_backend {
+ int (*compress)(const unsigned char *src, unsigned char *dst,
+ size_t *dst_len, void *private);
+
+ int (*decompress)(const unsigned char *src, size_t src_len,
+ unsigned char *dst);
+
+ void *(*create)(void);
+ void (*destroy)(void *private);
+
+ const char *name;
+};
+
+/* dynamic per-device compression frontend */
+struct zcomp {
+ void *stream;
+ struct zcomp_backend *backend;
+
+ struct zcomp_strm *(*strm_find)(struct zcomp *comp);
+ void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm);
+ bool (*set_max_streams)(struct zcomp *comp, int num_strm);
+ void (*destroy)(struct zcomp *comp);
+};
+
+ssize_t zcomp_available_show(const char *comp, char *buf);
+
+struct zcomp *zcomp_create(const char *comp, int max_strm);
+void zcomp_destroy(struct zcomp *comp);
+
+struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
+void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm);
+
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+ const unsigned char *src, size_t *dst_len);
+
+int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
+ size_t src_len, unsigned char *dst);
+
+bool zcomp_set_max_streams(struct zcomp *comp, int num_strm);
+#endif /* _ZCOMP_H_ */
diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c
new file mode 100644
index 0000000..f2afb7e
--- /dev/null
+++ b/drivers/block/zram/zcomp_lz4.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * 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/lz4.h>
+
+#include "zcomp_lz4.h"
+
+static void *zcomp_lz4_create(void)
+{
+ return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void zcomp_lz4_destroy(void *private)
+{
+ kfree(private);
+}
+
+static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
+ size_t *dst_len, void *private)
+{
+ /* return : Success if return 0 */
+ return lz4_compress(src, PAGE_SIZE, dst, dst_len, private);
+}
+
+static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len,
+ unsigned char *dst)
+{
+ size_t dst_len = PAGE_SIZE;
+ /* return : Success if return 0 */
+ return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len);
+}
+
+struct zcomp_backend zcomp_lz4 = {
+ .compress = zcomp_lz4_compress,
+ .decompress = zcomp_lz4_decompress,
+ .create = zcomp_lz4_create,
+ .destroy = zcomp_lz4_destroy,
+ .name = "lz4",
+};
diff --git a/drivers/block/zram/zcomp_lz4.h b/drivers/block/zram/zcomp_lz4.h
new file mode 100644
index 0000000..60613fb
--- /dev/null
+++ b/drivers/block/zram/zcomp_lz4.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * 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 _ZCOMP_LZ4_H_
+#define _ZCOMP_LZ4_H_
+
+#include "zcomp.h"
+
+extern struct zcomp_backend zcomp_lz4;
+
+#endif /* _ZCOMP_LZ4_H_ */
diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c
new file mode 100644
index 0000000..da1bc47
--- /dev/null
+++ b/drivers/block/zram/zcomp_lzo.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * 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/lzo.h>
+
+#include "zcomp_lzo.h"
+
+static void *lzo_create(void)
+{
+ return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void lzo_destroy(void *private)
+{
+ kfree(private);
+}
+
+static int lzo_compress(const unsigned char *src, unsigned char *dst,
+ size_t *dst_len, void *private)
+{
+ int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
+ return ret == LZO_E_OK ? 0 : ret;
+}
+
+static int lzo_decompress(const unsigned char *src, size_t src_len,
+ unsigned char *dst)
+{
+ size_t dst_len = PAGE_SIZE;
+ int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+ return ret == LZO_E_OK ? 0 : ret;
+}
+
+struct zcomp_backend zcomp_lzo = {
+ .compress = lzo_compress,
+ .decompress = lzo_decompress,
+ .create = lzo_create,
+ .destroy = lzo_destroy,
+ .name = "lzo",
+};
diff --git a/drivers/block/zram/zcomp_lzo.h b/drivers/block/zram/zcomp_lzo.h
new file mode 100644
index 0000000..128c580
--- /dev/null
+++ b/drivers/block/zram/zcomp_lzo.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * 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 _ZCOMP_LZO_H_
+#define _ZCOMP_LZO_H_
+
+#include "zcomp.h"
+
+extern struct zcomp_backend zcomp_lzo;
+
+#endif /* _ZCOMP_LZO_H_ */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
new file mode 100644
index 0000000..a4eb55d
--- /dev/null
+++ b/drivers/block/zram/zram_drv.c
@@ -0,0 +1,1081 @@
+/*
+ * Compressed RAM block device
+ *
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
+ * 2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ * Project home: http://compcache.googlecode.com
+ */
+
+#define KMSG_COMPONENT "zram"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#ifdef CONFIG_ZRAM_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bio.h>
+#include <linux/bitops.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/device.h>
+#include <linux/genhd.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/ratelimit.h>
+#include <linux/err.h>
+
+#include "zram_drv.h"
+
+/* Globals */
+static int zram_major;
+static struct zram *zram_devices;
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+static const char *default_compressor = "lz4";
+#else
+static const char *default_compressor = "lzo";
+#endif
+
+/*
+ * We don't need to see memory allocation errors more than once every 1
+ * second to know that a problem is occurring.
+ */
+#define ALLOC_ERROR_LOG_RATE_MS 1000
+
+/* Module params (documentation at end) */
+static unsigned int num_devices = 1;
+
+#define ZRAM_ATTR_RO(name) \
+static ssize_t zram_attr_##name##_show(struct device *d, \
+ struct device_attribute *attr, char *b) \
+{ \
+ struct zram *zram = dev_to_zram(d); \
+ return scnprintf(b, PAGE_SIZE, "%llu\n", \
+ (u64)atomic64_read(&zram->stats.name)); \
+} \
+static struct device_attribute dev_attr_##name = \
+ __ATTR(name, S_IRUGO, zram_attr_##name##_show, NULL);
+
+static inline int init_done(struct zram *zram)
+{
+ return zram->meta != NULL;
+}
+
+static inline struct zram *dev_to_zram(struct device *dev)
+{
+ return (struct zram *)dev_to_disk(dev)->private_data;
+}
+
+static ssize_t disksize_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct zram *zram = dev_to_zram(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize);
+}
+
+static ssize_t initstate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u32 val;
+ struct zram *zram = dev_to_zram(dev);
+
+ down_read(&zram->init_lock);
+ val = init_done(zram);
+ up_read(&zram->init_lock);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", val);
+}
+
+static ssize_t orig_data_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct zram *zram = dev_to_zram(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%llu\n",
+ (u64)(atomic64_read(&zram->stats.pages_stored)) << PAGE_SHIFT);
+}
+
+static ssize_t mem_used_total_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u64 val = 0;
+ struct zram *zram = dev_to_zram(dev);
+ struct zram_meta *meta = zram->meta;
+
+ down_read(&zram->init_lock);
+ if (init_done(zram))
+ val = zs_get_total_pages(meta->mem_pool);
+ up_read(&zram->init_lock);
+
+ return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
+}
+
+static ssize_t max_comp_streams_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int val;
+ struct zram *zram = dev_to_zram(dev);
+
+ down_read(&zram->init_lock);
+ val = zram->max_comp_streams;
+ up_read(&zram->init_lock);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t max_comp_streams_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ int num;
+ struct zram *zram = dev_to_zram(dev);
+ int ret;
+
+ ret = kstrtoint(buf, 0, &num);
+ if (ret < 0)
+ return ret;
+ if (num < 1)
+ return -EINVAL;
+
+ down_write(&zram->init_lock);
+ if (init_done(zram)) {
+ if (!zcomp_set_max_streams(zram->comp, num)) {
+ pr_info("Cannot change max compression streams\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ zram->max_comp_streams = num;
+ ret = len;
+out:
+ up_write(&zram->init_lock);
+ return ret;
+}
+
+static ssize_t comp_algorithm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ size_t sz;
+ struct zram *zram = dev_to_zram(dev);
+
+ down_read(&zram->init_lock);
+ sz = zcomp_available_show(zram->compressor, buf);
+ up_read(&zram->init_lock);
+
+ return sz;
+}
+
+static ssize_t comp_algorithm_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct zram *zram = dev_to_zram(dev);
+ down_write(&zram->init_lock);
+ if (init_done(zram)) {
+ up_write(&zram->init_lock);
+ pr_info("Can't change algorithm for initialized device\n");
+ return -EBUSY;
+ }
+ strlcpy(zram->compressor, buf, sizeof(zram->compressor));
+ up_write(&zram->init_lock);
+ return len;
+}
+
+/* flag operations needs meta->tb_lock */
+static int zram_test_flag(struct zram_meta *meta, u32 index,
+ enum zram_pageflags flag)
+{
+ return meta->table[index].value & BIT(flag);
+}
+
+static void zram_set_flag(struct zram_meta *meta, u32 index,
+ enum zram_pageflags flag)
+{
+ meta->table[index].value |= BIT(flag);
+}
+
+static void zram_clear_flag(struct zram_meta *meta, u32 index,
+ enum zram_pageflags flag)
+{
+ meta->table[index].value &= ~BIT(flag);
+}
+
+static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
+{
+ return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
+}
+
+static void zram_set_obj_size(struct zram_meta *meta,
+ u32 index, size_t size)
+{
+ unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
+
+ meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
+}
+
+static inline int is_partial_io(struct bio_vec *bvec)
+{
+ return bvec->bv_len != PAGE_SIZE;
+}
+
+/*
+ * Check if request is within bounds and aligned on zram logical blocks.
+ */
+static inline int valid_io_request(struct zram *zram, struct bio *bio)
+{
+ u64 start, end, bound;
+
+ /* unaligned request */
+ if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
+ return 0;
+ if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
+ return 0;
+
+ start = bio->bi_sector;
+ end = start + (bio->bi_size >> SECTOR_SHIFT);
+ bound = zram->disksize >> SECTOR_SHIFT;
+ /* out of range range */
+ if (unlikely(start >= bound || end > bound || start > end))
+ return 0;
+
+ /* I/O request is valid */
+ return 1;
+}
+
+static void zram_meta_free(struct zram_meta *meta)
+{
+ zs_destroy_pool(meta->mem_pool);
+ vfree(meta->table);
+ kfree(meta);
+}
+
+static struct zram_meta *zram_meta_alloc(u64 disksize)
+{
+ size_t num_pages;
+ struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
+ if (!meta)
+ goto out;
+
+ num_pages = disksize >> PAGE_SHIFT;
+ meta->table = vzalloc(num_pages * sizeof(*meta->table));
+ if (!meta->table) {
+ pr_err("Error allocating zram address table\n");
+ goto free_meta;
+ }
+
+ meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM |
+ __GFP_NOWARN);
+ if (!meta->mem_pool) {
+ pr_err("Error creating memory pool\n");
+ goto free_table;
+ }
+
+ return meta;
+
+free_table:
+ vfree(meta->table);
+free_meta:
+ kfree(meta);
+ meta = NULL;
+out:
+ return meta;
+}
+
+static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
+{
+ if (*offset + bvec->bv_len >= PAGE_SIZE)
+ (*index)++;
+ *offset = (*offset + bvec->bv_len) % PAGE_SIZE;
+}
+
+static int page_zero_filled(void *ptr)
+{
+ unsigned int pos;
+ unsigned long *page;
+
+ page = (unsigned long *)ptr;
+
+ for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
+ if (page[pos])
+ return 0;
+ }
+
+ return 1;
+}
+
+static void handle_zero_page(struct bio_vec *bvec)
+{
+ struct page *page = bvec->bv_page;
+ void *user_mem;
+
+ user_mem = kmap_atomic(page);
+ if (is_partial_io(bvec))
+ memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
+ else
+ clear_page(user_mem);
+ kunmap_atomic(user_mem);
+
+ flush_dcache_page(page);
+}
+
+
+/*
+ * To protect concurrent access to the same index entry,
+ * caller should hold this table index entry's bit_spinlock to
+ * indicate this index entry is accessing.
+ */
+static void zram_free_page(struct zram *zram, size_t index)
+{
+ struct zram_meta *meta = zram->meta;
+ unsigned long handle = meta->table[index].handle;
+
+ if (unlikely(!handle)) {
+ /*
+ * No memory is allocated for zero filled pages.
+ * Simply clear zero page flag.
+ */
+ if (zram_test_flag(meta, index, ZRAM_ZERO)) {
+ zram_clear_flag(meta, index, ZRAM_ZERO);
+ atomic64_dec(&zram->stats.zero_pages);
+ }
+ return;
+ }
+
+ zs_free(meta->mem_pool, handle);
+
+ atomic64_sub(zram_get_obj_size(meta, index),
+ &zram->stats.compr_data_size);
+ atomic64_dec(&zram->stats.pages_stored);
+
+ meta->table[index].handle = 0;
+ zram_set_obj_size(meta, index, 0);
+}
+
+static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
+{
+ int ret = 0;
+ unsigned char *cmem;
+ struct zram_meta *meta = zram->meta;
+ unsigned long handle;
+ size_t size;
+
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+ handle = meta->table[index].handle;
+ size = zram_get_obj_size(meta, index);
+
+ if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+ clear_page(mem);
+ return 0;
+ }
+
+ cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
+ if (size == PAGE_SIZE)
+ copy_page(mem, cmem);
+ else
+ ret = zcomp_decompress(zram->comp, cmem, size, mem);
+ zs_unmap_object(meta->mem_pool, handle);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+ /* Should NEVER happen. Return bio error if it does. */
+ if (unlikely(ret)) {
+ pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+ u32 index, int offset, struct bio *bio)
+{
+ int ret;
+ struct page *page;
+ unsigned char *user_mem, *uncmem = NULL;
+ struct zram_meta *meta = zram->meta;
+ page = bvec->bv_page;
+
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+ if (unlikely(!meta->table[index].handle) ||
+ zram_test_flag(meta, index, ZRAM_ZERO)) {
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+ handle_zero_page(bvec);
+ return 0;
+ }
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+ if (is_partial_io(bvec))
+ /* Use a temporary buffer to decompress the page */
+ uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+
+ user_mem = kmap_atomic(page);
+ if (!is_partial_io(bvec))
+ uncmem = user_mem;
+
+ if (!uncmem) {
+ pr_info("Unable to allocate temp memory\n");
+ ret = -ENOMEM;
+ goto out_cleanup;
+ }
+
+ ret = zram_decompress_page(zram, uncmem, index);
+ /* Should NEVER happen. Return bio error if it does. */
+ if (unlikely(ret))
+ goto out_cleanup;
+
+ if (is_partial_io(bvec))
+ memcpy(user_mem + bvec->bv_offset, uncmem + offset,
+ bvec->bv_len);
+
+ flush_dcache_page(page);
+ ret = 0;
+out_cleanup:
+ kunmap_atomic(user_mem);
+ if (is_partial_io(bvec))
+ kfree(uncmem);
+ return ret;
+}
+
+static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
+ int offset)
+{
+ int ret = 0;
+ size_t clen;
+ unsigned long handle;
+ struct page *page;
+ unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
+ struct zram_meta *meta = zram->meta;
+ static unsigned long zram_rs_time;
+ struct zcomp_strm *zstrm;
+ bool locked = false;
+
+ page = bvec->bv_page;
+ if (is_partial_io(bvec)) {
+ /*
+ * This is a partial IO. We need to read the full page
+ * before to write the changes.
+ */
+ uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+ if (!uncmem) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = zram_decompress_page(zram, uncmem, index);
+ if (ret)
+ goto out;
+ }
+
+ zstrm = zcomp_strm_find(zram->comp);
+ locked = true;
+ user_mem = kmap_atomic(page);
+
+ if (is_partial_io(bvec)) {
+ memcpy(uncmem + offset, user_mem + bvec->bv_offset,
+ bvec->bv_len);
+ kunmap_atomic(user_mem);
+ user_mem = NULL;
+ } else {
+ uncmem = user_mem;
+ }
+
+ if (page_zero_filled(uncmem)) {
+ kunmap_atomic(user_mem);
+ /* Free memory associated with this sector now. */
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+ zram_free_page(zram, index);
+ zram_set_flag(meta, index, ZRAM_ZERO);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+ atomic64_inc(&zram->stats.zero_pages);
+ ret = 0;
+ goto out;
+ }
+
+ ret = zcomp_compress(zram->comp, zstrm, uncmem, &clen);
+ if (!is_partial_io(bvec)) {
+ kunmap_atomic(user_mem);
+ user_mem = NULL;
+ uncmem = NULL;
+ }
+
+ if (unlikely(ret)) {
+ pr_err("Compression failed! err=%d\n", ret);
+ goto out;
+ }
+ src = zstrm->buffer;
+ if (unlikely(clen > max_zpage_size)) {
+ clen = PAGE_SIZE;
+ if (is_partial_io(bvec))
+ src = uncmem;
+ }
+
+ handle = zs_malloc(meta->mem_pool, clen);
+ if (!handle) {
+ if (printk_timed_ratelimit(&zram_rs_time,
+ ALLOC_ERROR_LOG_RATE_MS))
+ pr_info("Error allocating memory for compressed page: %u, size=%zu\n",
+ index, clen);
+ ret = -ENOMEM;
+ goto out;
+ }
+ cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO);
+
+ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
+ src = kmap_atomic(page);
+ copy_page(cmem, src);
+ kunmap_atomic(src);
+ } else {
+ memcpy(cmem, src, clen);
+ }
+
+ zcomp_strm_release(zram->comp, zstrm);
+ locked = false;
+ zs_unmap_object(meta->mem_pool, handle);
+
+ /*
+ * Free memory associated with this sector
+ * before overwriting unused sectors.
+ */
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+ zram_free_page(zram, index);
+
+ meta->table[index].handle = handle;
+ zram_set_obj_size(meta, index, clen);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+ /* Update stats */
+ atomic64_add(clen, &zram->stats.compr_data_size);
+ atomic64_inc(&zram->stats.pages_stored);
+out:
+ if (locked)
+ zcomp_strm_release(zram->comp, zstrm);
+ if (is_partial_io(bvec))
+ kfree(uncmem);
+ return ret;
+}
+
+static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
+ int offset, struct bio *bio)
+{
+ int ret;
+ int rw = bio_data_dir(bio);
+
+ if (rw == READ) {
+ atomic64_inc(&zram->stats.num_reads);
+ ret = zram_bvec_read(zram, bvec, index, offset, bio);
+ } else {
+ atomic64_inc(&zram->stats.num_writes);
+ ret = zram_bvec_write(zram, bvec, index, offset);
+ }
+
+ if (unlikely(ret)) {
+ if (rw == READ)
+ atomic64_inc(&zram->stats.failed_reads);
+ else
+ atomic64_inc(&zram->stats.failed_writes);
+ }
+
+ return ret;
+}
+
+/*
+ * zram_bio_discard - handler on discard request
+ * @index: physical block index in PAGE_SIZE units
+ * @offset: byte offset within physical block
+ */
+static void zram_bio_discard(struct zram *zram, u32 index,
+ int offset, struct bio *bio)
+{
+ size_t n = bio->bi_size;
+ struct zram_meta *meta = zram->meta;
+
+ /*
+ * zram manages data in physical block size units. Because logical block
+ * size isn't identical with physical block size on some arch, we
+ * could get a discard request pointing to a specific offset within a
+ * certain physical block. Although we can handle this request by
+ * reading that physiclal block and decompressing and partially zeroing
+ * and re-compressing and then re-storing it, this isn't reasonable
+ * because our intent with a discard request is to save memory. So
+ * skipping this logical block is appropriate here.
+ */
+ if (offset) {
+ if (n <= (PAGE_SIZE - offset))
+ return;
+
+ n -= (PAGE_SIZE - offset);
+ index++;
+ }
+
+ while (n >= PAGE_SIZE) {
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+ zram_free_page(zram, index);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+ index++;
+ n -= PAGE_SIZE;
+ }
+}
+
+static void zram_reset_device(struct zram *zram, bool reset_capacity)
+{
+ size_t index;
+ struct zram_meta *meta;
+
+ down_write(&zram->init_lock);
+ if (!init_done(zram)) {
+ up_write(&zram->init_lock);
+ return;
+ }
+
+ meta = zram->meta;
+ /* Free all pages that are still in this zram device */
+ for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) {
+ unsigned long handle = meta->table[index].handle;
+ if (!handle)
+ continue;
+
+ zs_free(meta->mem_pool, handle);
+ }
+
+ zcomp_destroy(zram->comp);
+ zram->max_comp_streams = 1;
+
+ zram_meta_free(zram->meta);
+ zram->meta = NULL;
+ /* Reset stats */
+ memset(&zram->stats, 0, sizeof(zram->stats));
+
+ zram->disksize = 0;
+ if (reset_capacity)
+ set_capacity(zram->disk, 0);
+
+ up_write(&zram->init_lock);
+
+ /*
+ * Revalidate disk out of the init_lock to avoid lockdep splat.
+ * It's okay because disk's capacity is protected by init_lock
+ * so that revalidate_disk always sees up-to-date capacity.
+ */
+ if (reset_capacity)
+ revalidate_disk(zram->disk);
+}
+
+static ssize_t disksize_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ u64 disksize;
+ struct zcomp *comp;
+ struct zram_meta *meta;
+ struct zram *zram = dev_to_zram(dev);
+ int err;
+
+ disksize = memparse(buf, NULL);
+ if (!disksize)
+ return -EINVAL;
+
+ disksize = PAGE_ALIGN(disksize);
+ meta = zram_meta_alloc(disksize);
+ if (!meta)
+ return -ENOMEM;
+
+ comp = zcomp_create(zram->compressor, zram->max_comp_streams);
+ if (IS_ERR(comp)) {
+ pr_info("Cannot initialise %s compressing backend\n",
+ zram->compressor);
+ err = PTR_ERR(comp);
+ goto out_free_meta;
+ }
+
+ down_write(&zram->init_lock);
+ if (init_done(zram)) {
+ pr_info("Cannot change disksize for initialized device\n");
+ err = -EBUSY;
+ goto out_destroy_comp;
+ }
+
+ zram->meta = meta;
+ zram->comp = comp;
+ zram->disksize = disksize;
+ set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
+ up_write(&zram->init_lock);
+
+ /*
+ * Revalidate disk out of the init_lock to avoid lockdep splat.
+ * It's okay because disk's capacity is protected by init_lock
+ * so that revalidate_disk always sees up-to-date capacity.
+ */
+ revalidate_disk(zram->disk);
+
+ return len;
+
+out_destroy_comp:
+ up_write(&zram->init_lock);
+ zcomp_destroy(comp);
+out_free_meta:
+ zram_meta_free(meta);
+ return err;
+}
+
+static ssize_t reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ int ret;
+ unsigned short do_reset;
+ struct zram *zram;
+ struct block_device *bdev;
+
+ zram = dev_to_zram(dev);
+ bdev = bdget_disk(zram->disk, 0);
+
+ if (!bdev)
+ return -ENOMEM;
+
+ /* Do not reset an active device! */
+ if (bdev->bd_holders) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = kstrtou16(buf, 10, &do_reset);
+ if (ret)
+ goto out;
+
+ if (!do_reset) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Make sure all pending I/O is finished */
+ fsync_bdev(bdev);
+ bdput(bdev);
+
+ zram_reset_device(zram, true);
+ return len;
+
+out:
+ bdput(bdev);
+ return ret;
+}
+
+static void __zram_make_request(struct zram *zram, struct bio *bio)
+{
+ int i, offset;
+ u32 index;
+ struct bio_vec *bvec;
+
+ index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+ offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
+
+ if (unlikely(bio->bi_rw & REQ_DISCARD)) {
+ zram_bio_discard(zram, index, offset, bio);
+ bio_endio(bio, 0);
+ return;
+ }
+
+ bio_for_each_segment(bvec, bio, i) {
+ int max_transfer_size = PAGE_SIZE - offset;
+
+ if (bvec->bv_len > max_transfer_size) {
+ /*
+ * zram_bvec_rw() can only make operation on a single
+ * zram page. Split the bio vector.
+ */
+ struct bio_vec bv;
+
+ bv.bv_page = bvec->bv_page;
+ bv.bv_len = max_transfer_size;
+ bv.bv_offset = bvec->bv_offset;
+
+ if (zram_bvec_rw(zram, &bv, index, offset, bio) < 0)
+ goto out;
+
+ bv.bv_len = bvec->bv_len - max_transfer_size;
+ bv.bv_offset += max_transfer_size;
+ if (zram_bvec_rw(zram, &bv, index + 1, 0, bio) < 0)
+ goto out;
+ } else
+ if (zram_bvec_rw(zram, bvec, index, offset, bio) < 0)
+ goto out;
+
+ update_position(&index, &offset, bvec);
+ }
+
+ set_bit(BIO_UPTODATE, &bio->bi_flags);
+ bio_endio(bio, 0);
+ return;
+
+out:
+ bio_io_error(bio);
+}
+
+/*
+ * Handler function for all zram I/O requests.
+ */
+static int zram_make_request(struct request_queue *queue, struct bio *bio)
+{
+ struct zram *zram = queue->queuedata;
+
+ down_read(&zram->init_lock);
+ if (unlikely(!init_done(zram)))
+ goto error;
+
+ if (!valid_io_request(zram, bio)) {
+ atomic64_inc(&zram->stats.invalid_io);
+ goto error;
+ }
+
+ __zram_make_request(zram, bio);
+ up_read(&zram->init_lock);
+
+ return 0;
+
+error:
+ up_read(&zram->init_lock);
+ bio_io_error(bio);
+
+ return 0;
+}
+
+static void zram_slot_free_notify(struct block_device *bdev,
+ unsigned long index)
+{
+ struct zram *zram;
+ struct zram_meta *meta;
+
+ zram = bdev->bd_disk->private_data;
+ meta = zram->meta;
+
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+ zram_free_page(zram, index);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+ atomic64_inc(&zram->stats.notify_free);
+}
+
+static const struct block_device_operations zram_devops = {
+ .swap_slot_free_notify = zram_slot_free_notify,
+ .owner = THIS_MODULE
+};
+
+static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
+ disksize_show, disksize_store);
+static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
+static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
+static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
+static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
+static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
+ max_comp_streams_show, max_comp_streams_store);
+static DEVICE_ATTR(comp_algorithm, S_IRUGO | S_IWUSR,
+ comp_algorithm_show, comp_algorithm_store);
+
+ZRAM_ATTR_RO(num_reads);
+ZRAM_ATTR_RO(num_writes);
+ZRAM_ATTR_RO(failed_reads);
+ZRAM_ATTR_RO(failed_writes);
+ZRAM_ATTR_RO(invalid_io);
+ZRAM_ATTR_RO(notify_free);
+ZRAM_ATTR_RO(zero_pages);
+ZRAM_ATTR_RO(compr_data_size);
+
+static struct attribute *zram_disk_attrs[] = {
+ &dev_attr_disksize.attr,
+ &dev_attr_initstate.attr,
+ &dev_attr_reset.attr,
+ &dev_attr_num_reads.attr,
+ &dev_attr_num_writes.attr,
+ &dev_attr_failed_reads.attr,
+ &dev_attr_failed_writes.attr,
+ &dev_attr_invalid_io.attr,
+ &dev_attr_notify_free.attr,
+ &dev_attr_zero_pages.attr,
+ &dev_attr_orig_data_size.attr,
+ &dev_attr_compr_data_size.attr,
+ &dev_attr_mem_used_total.attr,
+ &dev_attr_max_comp_streams.attr,
+ &dev_attr_comp_algorithm.attr,
+ NULL,
+};
+
+static struct attribute_group zram_disk_attr_group = {
+ .attrs = zram_disk_attrs,
+};
+
+static int create_device(struct zram *zram, int device_id)
+{
+ int ret = -ENOMEM;
+
+ init_rwsem(&zram->init_lock);
+
+ zram->queue = blk_alloc_queue(GFP_KERNEL);
+ if (!zram->queue) {
+ pr_err("Error allocating disk queue for device %d\n",
+ device_id);
+ goto out;
+ }
+
+ blk_queue_make_request(zram->queue, zram_make_request);
+ zram->queue->queuedata = zram;
+
+ /* gendisk structure */
+ zram->disk = alloc_disk(1);
+ if (!zram->disk) {
+ pr_warn("Error allocating disk structure for device %d\n",
+ device_id);
+ goto out_free_queue;
+ }
+
+ zram->disk->major = zram_major;
+ zram->disk->first_minor = device_id;
+ zram->disk->fops = &zram_devops;
+ zram->disk->queue = zram->queue;
+ zram->disk->private_data = zram;
+ snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
+
+ __set_bit(QUEUE_FLAG_FAST, &zram->queue->queue_flags);
+ /* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
+ set_capacity(zram->disk, 0);
+ /* zram devices sort of resembles non-rotational disks */
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
+ /*
+ * To ensure that we always get PAGE_SIZE aligned
+ * and n*PAGE_SIZED sized I/O requests.
+ */
+ blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE);
+ blk_queue_logical_block_size(zram->disk->queue,
+ ZRAM_LOGICAL_BLOCK_SIZE);
+ blk_queue_io_min(zram->disk->queue, PAGE_SIZE);
+ blk_queue_io_opt(zram->disk->queue, PAGE_SIZE);
+ zram->disk->queue->limits.discard_granularity = PAGE_SIZE;
+ zram->disk->queue->limits.max_discard_sectors = UINT_MAX;
+ /*
+ * zram_bio_discard() will clear all logical blocks if logical block
+ * size is identical with physical block size(PAGE_SIZE). But if it is
+ * different, we will skip discarding some parts of logical blocks in
+ * the part of the request range which isn't aligned to physical block
+ * size. So we can't ensure that all discarded logical blocks are
+ * zeroed.
+ */
+ if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE)
+ zram->disk->queue->limits.discard_zeroes_data = 1;
+ else
+ zram->disk->queue->limits.discard_zeroes_data = 0;
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zram->disk->queue);
+
+ add_disk(zram->disk);
+
+ ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
+ &zram_disk_attr_group);
+ if (ret < 0) {
+ pr_warn("Error creating sysfs group");
+ goto out_free_disk;
+ }
+ strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
+ zram->meta = NULL;
+ zram->max_comp_streams = 1;
+ return 0;
+
+out_free_disk:
+ del_gendisk(zram->disk);
+ put_disk(zram->disk);
+out_free_queue:
+ blk_cleanup_queue(zram->queue);
+out:
+ return ret;
+}
+
+static void destroy_device(struct zram *zram)
+{
+ sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
+ &zram_disk_attr_group);
+
+ del_gendisk(zram->disk);
+ put_disk(zram->disk);
+
+ blk_cleanup_queue(zram->queue);
+}
+
+static int __init zram_init(void)
+{
+ int ret, dev_id;
+
+ if (num_devices > max_num_devices) {
+ pr_warn("Invalid value for num_devices: %u\n",
+ num_devices);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ zram_major = register_blkdev(0, "zram");
+ if (zram_major <= 0) {
+ pr_warn("Unable to get major number\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Allocate the device array and initialize each one */
+ zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
+ if (!zram_devices) {
+ ret = -ENOMEM;
+ goto unregister;
+ }
+
+ for (dev_id = 0; dev_id < num_devices; dev_id++) {
+ ret = create_device(&zram_devices[dev_id], dev_id);
+ if (ret)
+ goto free_devices;
+ }
+
+ pr_info("Created %u device(s) ...\n", num_devices);
+
+ return 0;
+
+free_devices:
+ while (dev_id)
+ destroy_device(&zram_devices[--dev_id]);
+ kfree(zram_devices);
+unregister:
+ unregister_blkdev(zram_major, "zram");
+out:
+ return ret;
+}
+
+static void __exit zram_exit(void)
+{
+ int i;
+ struct zram *zram;
+
+ for (i = 0; i < num_devices; i++) {
+ zram = &zram_devices[i];
+
+ destroy_device(zram);
+ /*
+ * Shouldn't access zram->disk after destroy_device
+ * because destroy_device already released zram->disk.
+ */
+ zram_reset_device(zram, false);
+ }
+
+ unregister_blkdev(zram_major, "zram");
+
+ kfree(zram_devices);
+ pr_debug("Cleanup done!\n");
+}
+
+module_init(zram_init);
+module_exit(zram_exit);
+
+module_param(num_devices, uint, 0);
+MODULE_PARM_DESC(num_devices, "Number of zram devices");
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
+MODULE_DESCRIPTION("Compressed RAM Block Device");
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
new file mode 100644
index 0000000..2a4f29c
--- /dev/null
+++ b/drivers/block/zram/zram_drv.h
@@ -0,0 +1,118 @@
+/*
+ * Compressed RAM block device
+ *
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
+ * 2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ * Project home: http://compcache.googlecode.com
+ */
+
+#ifndef _ZRAM_DRV_H_
+#define _ZRAM_DRV_H_
+
+#include <linux/spinlock.h>
+#include <linux/zsmalloc.h>
+
+#include "zcomp.h"
+
+/*
+ * Some arbitrary value. This is just to catch
+ * invalid value for num_devices module parameter.
+ */
+static const unsigned max_num_devices = 32;
+
+/*-- Configurable parameters */
+
+/*
+ * Pages that compress to size greater than this are stored
+ * uncompressed in memory.
+ */
+static const size_t max_zpage_size = PAGE_SIZE / 10 * 9;
+
+/*
+ * NOTE: max_zpage_size must be less than or equal to:
+ * ZS_MAX_ALLOC_SIZE. Otherwise, zs_malloc() would
+ * always return failure.
+ */
+
+/*-- End of configurable params */
+
+#define SECTOR_SHIFT 9
+#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
+#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)
+#define ZRAM_LOGICAL_BLOCK_SHIFT 12
+#define ZRAM_LOGICAL_BLOCK_SIZE (1 << ZRAM_LOGICAL_BLOCK_SHIFT)
+#define ZRAM_SECTOR_PER_LOGICAL_BLOCK \
+ (1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
+
+
+/*
+ * The lower ZRAM_FLAG_SHIFT bits of table.value is for
+ * object size (excluding header), the higher bits is for
+ * zram_pageflags.
+ *
+ * zram is mainly used for memory efficiency so we want to keep memory
+ * footprint small so we can squeeze size and flags into a field.
+ * The lower ZRAM_FLAG_SHIFT bits is for object size (excluding header),
+ * the higher bits is for zram_pageflags.
+ */
+#define ZRAM_FLAG_SHIFT 24
+
+/* Flags for zram pages (table[page_no].value) */
+enum zram_pageflags {
+ /* Page consists entirely of zeros */
+ ZRAM_ZERO = ZRAM_FLAG_SHIFT + 1,
+ ZRAM_ACCESS, /* page in now accessed */
+
+ __NR_ZRAM_PAGEFLAGS,
+};
+
+/*-- Data structures */
+
+/* Allocated for each disk page */
+struct zram_table_entry {
+ unsigned long handle;
+ unsigned long value;
+};
+
+struct zram_stats {
+ atomic64_t compr_data_size; /* compressed size of pages stored */
+ atomic64_t num_reads; /* failed + successful */
+ atomic64_t num_writes; /* --do-- */
+ atomic64_t failed_reads; /* can happen when memory is too low */
+ atomic64_t failed_writes; /* can happen when memory is too low */
+ atomic64_t invalid_io; /* non-page-aligned I/O requests */
+ atomic64_t notify_free; /* no. of swap slot free notifications */
+ atomic64_t zero_pages; /* no. of zero filled pages */
+ atomic64_t pages_stored; /* no. of pages currently stored */
+};
+
+struct zram_meta {
+ struct zram_table_entry *table;
+ struct zs_pool *mem_pool;
+};
+
+struct zram {
+ struct zram_meta *meta;
+ struct request_queue *queue;
+ struct gendisk *disk;
+ struct zcomp *comp;
+
+ /* Prevent concurrent execution of device init, reset and R/W request */
+ struct rw_semaphore init_lock;
+ /*
+ * This is the limit on amount of *uncompressed* worth of data
+ * we can store in a disk.
+ */
+ u64 disksize; /* bytes */
+ int max_comp_streams;
+ struct zram_stats stats;
+ char compressor[10];
+};
+#endif
diff --git a/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c b/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c
index af5e808..485ad26 100644
--- a/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c
+++ b/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c
@@ -1 +1 @@
-const char *__malidrv_build_info(void) { return "malidrv: API_VERSION=23 REPO_URL=heads/master REVISION=r3p2-01rel3-137c649 CHANGED_REVISION=137c649 CHANGE_DATE=2013-08-22 17:45:49 +0900 BUILD_DATE=Fri Aug 23 20:48:48 KST 2013 BUILD=release TARGET_PLATFORM=pegasus-m400 MALI_PLATFORM=pegasus-m400 KDIR= OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=16 USING_UMP=y USING_PROFILING= USING_INTERNAL_PROFILING= USING_GPU_UTILIZATION=1 MALI_UPPER_HALF_SCHEDULING=1";}
+const char *__malidrv_build_info(void) { return "mali: BUILD=RELEASE ARCH=arch_011_udd PLATFORM=default_7a TRACE=0 THREAD= GEOM=mali_gp_geometry_common CORES=MALI400 USING_MALI400=1 TARGET_CORE_REVISION=0x0101 TOPLEVEL_REPO_URL=Linux-r3p2-01rel3 REVISION=Linux-r3p2-01rel3 CHANGED_REVISION=Linux-r3p2-01rel3 REPO_URL=Linux-r3p2-01rel3 BUILD_DATE=Tue Aug 26 17:05:16 KST 2014 CHANGE_DATE=Linux-r3p2-01rel3 TARGET_TOOLCHAIN=arm-linux-gcc HOST_TOOLCHAIN=gcc TARGET_TOOLCHAIN_VERSION=gcc version 4.6.x-google 20120106 (prerelease) (GCC) HOST_TOOLCHAIN_VERSION=gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5.1) TARGET_SYSTEM=gcc-arm-linux HOST_SYSTEM=gcc-x86_64-linux CPPFLAGS= CUSTOMER=internal VARIANT=mali400-r1p1-gles11-gles20-linux-android-max_pp_split_count_4-ump-smp-rgb_is_xrgb-jellybean_mr2-gp_cache_alloc HOSTLIB=direct INSTRUMENTED=FALSE USING_MRI=FALSE MALI_TEST_API= UDD_OS=linux";}
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8f8728b..9d09e9e 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -977,6 +977,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
/* Ignore report if ErrorRollOver */
if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
value[n] >= min && value[n] <= max &&
+ value[n] - min < field->maxusage &&
field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
goto exit;
}
@@ -989,11 +990,13 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
}
if (field->value[n] >= min && field->value[n] <= max
+ && field->value[n] - min < field->maxusage
&& field->usage[field->value[n] - min].hid
&& search(value, field->value[n], count))
hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
if (value[n] >= min && value[n] <= max
+ && value[n] - min < field->maxusage
&& field->usage[value[n] - min].hid
&& search(field->value, value[n], count))
hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 7c1188b..fd78f2b 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -515,13 +515,13 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
goto inval;
} else if (uref->usage_index >= field->report_count)
goto inval;
-
- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
- (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
- uref->usage_index + uref_multi->num_values > field->report_count))
- goto inval;
}
+ if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+ (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+ uref->usage_index + uref_multi->num_values > field->report_count))
+ goto inval;
+
switch (cmd) {
case HIDIOCGUSAGE:
uref->value = field->value[uref->usage_index];
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 61e680e..83820c0 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -570,4 +570,6 @@ config SENSORS_HALL
source "drivers/input/keyboard/cypress/Kconfig"
+source "drivers/input/keyboard/cypressbln/Kconfig"
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 9ac639a..5664d66 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
obj-$(CONFIG_KEYBOARD_CYPRESS_TOUCH) += cypress/
+obj-$(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN)+= cypressbln/
ifeq ($(TARGET_BUILD_VARIANT), eng)
KBUILD_CFLAGS += -DSEC_TKEY_EVENT_DEBUG
diff --git a/drivers/input/keyboard/cypressbln/Kconfig b/drivers/input/keyboard/cypressbln/Kconfig
new file mode 100644
index 0000000..e1c0a8a
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/Kconfig
@@ -0,0 +1,16 @@
+#
+# Cypress touchkey configuration
+#
+
+config KEYBOARD_CYPRESS_TOUCH_BLN
+ tristate "Cypress touchkey support"
+ help
+ Say Y here to enable the cypress touchkey with BLN support.
+
+ To compile this driver as a module, choose M here.
+
+config TOUCHKEY_BLN
+ bool "BLN Support"
+ depends on KEYBOARD_CYPRESS_TOUCH_BLN
+ help
+ BLN support.
diff --git a/drivers/input/keyboard/cypressbln/Makefile b/drivers/input/keyboard/cypressbln/Makefile
new file mode 100644
index 0000000..a50c126
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Cypress touchkey driver
+#
+
+obj-$(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN) += cypress-touchkey.o issp_driver_routines.o issp_main.o issp_routines.o
diff --git a/drivers/input/keyboard/cypressbln/cypress-touchkey.c b/drivers/input/keyboard/cypressbln/cypress-touchkey.c
new file mode 100644
index 0000000..f06eca5
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/cypress-touchkey.c
@@ -0,0 +1,2466 @@
+/*
+ * Driver for keys on GPIO lines capable of generating interrupts.
+ *
+ * Copyright 2005 Phil Blundell
+ *
+ * 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.
+ *
+ * BLN code originally by neldar. Adapted for SGSII by creams. Ported
+ * by gokhanmoral.
+ */
+
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <asm/gpio.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/earlysuspend.h>
+#include <asm/io.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include "u1-cypress-gpio.h"
+
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+
+#include "issp_extern.h"
+#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT540E
+#include <linux/i2c/mxt540e.h>
+#else
+#include <linux/i2c/mxt224_u1.h>
+#endif
+
+/*
+touchkey register
+*/
+#define KEYCODE_REG 0x00
+#define FIRMWARE_VERSION 0x01
+#define TOUCHKEY_MODULE_VERSION 0x02
+#define TOUCHKEY_ADDRESS 0x20
+
+#define UPDOWN_EVENT_BIT 0x08
+#define KEYCODE_BIT 0x07
+
+#define I2C_M_WR 0 /* for i2c */
+
+#define DEVICE_NAME "sec_touchkey"
+#define TOUCH_FIRMWARE_V04 0x04
+#define TOUCH_FIRMWARE_V07 0x07
+#define DOOSUNGTECH_TOUCH_V1_2 0x0C
+
+#if defined(CONFIG_MACH_Q1_BD)
+#define TK_FIRMWARE_VER 0x12
+#define TK_MODULE_VER 0x11
+#elif defined(CONFIG_MACH_C1_NA_USCC_REV05)
+#define TK_FIRMWARE_VER 0x0E
+#define TK_MODULE_VER 0x08
+#else
+#define TK_FIRMWARE_VER 0x04
+#define TK_MODULE_VER 0x00
+#endif
+
+/*
+ * Standard CM7 LED Notification functionality.
+ */
+#include <linux/wakelock.h>
+
+#define BL_STANDARD 3000
+
+int notification_timeout = -1;
+int led_timeout;
+
+static DEFINE_SEMAPHORE(enable_sem);
+
+static struct timer_list breathing_timer;
+static void breathe(struct work_struct *breathe_work);
+static DECLARE_WORK(breathe_work, breathe);
+//breathing variables
+#define MAX_BREATHING_STEPS 10
+static unsigned int breathing = 0;
+static int breathing_step_count = 0;
+struct breathing_step {
+ int start; //mV
+ int end; //mV
+ int period; //ms
+ int step; //mV
+};
+struct breathing_step breathing_steps[MAX_BREATHING_STEPS];
+static int breathing_idx = 0;
+static int breathing_step_idx = 0;
+
+
+static unsigned int touchkey_voltage = 3000;
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT_TEMP)
+/* Temp Fix NAGSM_SEL_ANDROID_MOHAMMAD_ANSARI_20111224*/
+#define CONFIG_TARGET_LOCALE_NAATT
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+static int touchkey_keycode[5] = { 0,
+ KEY_MENU, KEY_ENTER, KEY_BACK, KEY_END };
+#elif defined(CONFIG_TARGET_LOCALE_NA)
+static int touchkey_keycode[5] = { NULL,
+ KEY_SEARCH, KEY_BACK, KEY_HOME, KEY_MENU };
+#else
+static int touchkey_keycode[3] = { 0, KEY_MENU, KEY_BACK };
+#endif
+/* timer related declares */
+static struct timer_list led_timer;
+static void bl_off(struct work_struct *bl_off_work);
+static DECLARE_WORK(bl_off_work, bl_off);
+static struct timer_list notification_timer;
+static void notification_off(struct work_struct *notification_off_work);
+static DECLARE_WORK(notification_off_work, notification_off);
+static const int touchkey_count = sizeof(touchkey_keycode) / sizeof(int);
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT)\
+ || defined(CONFIG_TARGET_LOCALE_NA)\
+ || defined(CONFIG_MACH_Q1_BD)
+
+static u8 home_sensitivity;
+static u8 search_sensitivity;
+static u16 raw_data0;
+static u16 raw_data1;
+static u16 raw_data2;
+static u16 raw_data3;
+static u8 idac0;
+static u8 idac1;
+static u8 idac2;
+static u8 idac3;
+static u8 touchkey_threshold;
+
+static int touchkey_autocalibration(void);
+#endif
+static int get_touchkey_module_version(void);
+
+static u8 menu_sensitivity;
+static u8 back_sensitivity;
+
+static int touchkey_enable;
+static bool touchkey_probe = true;
+
+struct device *sec_touchkey;
+
+#ifdef CONFIG_TOUCHKEY_BLN
+#include <linux/miscdevice.h>
+#include <linux/wakelock.h>
+#define BLN_VERSION 9
+
+bool bln_enabled = false;
+bool BLN_ongoing = false;
+bool bln_blink_enabled = false;
+bool bln_suspended = false;
+
+static void enable_led_notification(void);
+static void disable_led_notification(void);
+
+static struct wake_lock bln_wake_lock;
+#endif
+
+struct i2c_touchkey_driver {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct early_suspend early_suspend;
+};
+struct i2c_touchkey_driver *touchkey_driver;
+struct work_struct touchkey_work;
+struct workqueue_struct *touchkey_wq;
+
+struct work_struct touch_update_work;
+struct delayed_work touch_resume_work;
+
+#ifdef WHY_DO_WE_NEED_THIS
+static void __iomem *gpio_pend_mask_mem;
+#define INT_PEND_BASE 0xE0200A54
+#endif
+
+static const struct i2c_device_id sec_touchkey_id[] = {
+ {"sec_touchkey", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, sec_touchkey_id);
+
+static void init_hw(void);
+static int i2c_touchkey_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+
+extern int get_touchkey_firmware(char *version);
+static int touchkey_led_status;
+static int touchled_cmd_reversed;
+
+struct i2c_driver touchkey_i2c_driver = {
+ .driver = {
+ .name = "sec_touchkey_driver",
+ },
+ .id_table = sec_touchkey_id,
+ .probe = i2c_touchkey_probe,
+};
+
+static int touchkey_debug_count;
+static char touchkey_debug[104];
+static int touch_version;
+static int module_version;
+#ifdef CONFIG_TARGET_LOCALE_NA
+static int store_module_version;
+#endif
+
+static int touchkey_update_status;
+
+int touchkey_led_ldo_on(bool on)
+{
+ struct regulator *regulator;
+
+#if defined(CONFIG_MACH_S2PLUS)
+ if (on) {
+ gpio_direction_output(GPIO_3_TOUCH_EN, 1);
+ } else {
+ gpio_direction_output(GPIO_3_TOUCH_EN, 0);
+ }
+#else
+ if (on) {
+ regulator = regulator_get(NULL, "touch_led");
+ if (IS_ERR(regulator))
+ return 0;
+ regulator_enable(regulator);
+ regulator_put(regulator);
+ } else {
+ regulator = regulator_get(NULL, "touch_led");
+ if (IS_ERR(regulator))
+ return 0;
+ if (regulator_is_enabled(regulator))
+ regulator_force_disable(regulator);
+ regulator_put(regulator);
+ }
+#endif
+ return 0;
+}
+
+int touchkey_ldo_on(bool on)
+{
+ struct regulator *regulator;
+
+#if defined(CONFIG_MACH_S2PLUS)
+ if (on) {
+ regulator = regulator_get(NULL, "3_touch_1.8v");
+ if (IS_ERR(regulator))
+ return 0;
+ regulator_enable(regulator);
+ regulator_put(regulator);
+ } else {
+ regulator = regulator_get(NULL, "3_touch_1.8v");
+ if (IS_ERR(regulator))
+ return 0;
+ if (regulator_is_enabled(regulator))
+ regulator_force_disable(regulator);
+ regulator_put(regulator);
+ }
+#else
+ if (on) {
+ regulator = regulator_get(NULL, "touch");
+ if (IS_ERR(regulator))
+ return 0;
+ regulator_enable(regulator);
+ regulator_put(regulator);
+ } else {
+ regulator = regulator_get(NULL, "touch");
+ if (IS_ERR(regulator))
+ return 0;
+ if (regulator_is_enabled(regulator))
+ regulator_force_disable(regulator);
+ regulator_put(regulator);
+ }
+#endif
+
+ return 1;
+}
+
+static void change_touch_key_led_voltage(int vol_mv)
+{
+ struct regulator *tled_regulator;
+
+ tled_regulator = regulator_get(NULL, "touch_led");
+ if (IS_ERR(tled_regulator)) {
+ pr_err("%s: failed to get resource %s\n", __func__,
+ "touch_led");
+ return;
+ }
+ regulator_set_voltage(tled_regulator, vol_mv * 1000, vol_mv * 1000);
+ regulator_put(tled_regulator);
+}
+
+static ssize_t brightness_control(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int data;
+
+ if (sscanf(buf, "%d\n", &data) == 1) {
+ printk(KERN_ERR "[TouchKey] touch_led_brightness: %d\n", data);
+ change_touch_key_led_voltage(data);
+ touchkey_voltage = data;
+ } else {
+ printk(KERN_ERR "[TouchKey] touch_led_brightness Error\n");
+ }
+
+ return size;
+}
+
+void stop_breathing(void)
+{
+ del_timer(&breathing_timer);
+ change_touch_key_led_voltage(touchkey_voltage);
+}
+
+static void set_touchkey_debug(char value)
+{
+ if (touchkey_debug_count == 100)
+ touchkey_debug_count = 0;
+
+ touchkey_debug[touchkey_debug_count] = value;
+ touchkey_debug_count++;
+}
+
+static int i2c_touchkey_read(u8 reg, u8 *val, unsigned int len)
+{
+ int err = 0;
+ int retry = 2;
+ struct i2c_msg msg[1];
+
+ if ((touchkey_driver == NULL) || !(touchkey_enable == 1)
+ || !touchkey_probe) {
+ printk(KERN_ERR "[TouchKey] touchkey is not enabled. %d\n",
+ __LINE__);
+ return -ENODEV;
+ }
+
+ while (retry--) {
+ msg->addr = touchkey_driver->client->addr;
+ msg->flags = I2C_M_RD;
+ msg->len = len;
+ msg->buf = val;
+ err = i2c_transfer(touchkey_driver->client->adapter, msg, 1);
+
+ if (err >= 0)
+ return 0;
+ printk(KERN_ERR "[TouchKey] %s %d i2c transfer error\n",
+ __func__, __LINE__);
+ mdelay(10);
+ }
+ return err;
+
+}
+
+static int i2c_touchkey_write(u8 *val, unsigned int len)
+{
+ int err = 0;
+ struct i2c_msg msg[1];
+ int retry = 2;
+
+ if ((touchkey_driver == NULL) || !(touchkey_enable == 1)
+ || !touchkey_probe) {
+ printk(KERN_ERR "[TouchKey] touchkey is not enabled. %d\n",
+ __LINE__);
+ return -ENODEV;
+ }
+
+ while (retry--) {
+ msg->addr = touchkey_driver->client->addr;
+ msg->flags = I2C_M_WR;
+ msg->len = len;
+ msg->buf = val;
+ err = i2c_transfer(touchkey_driver->client->adapter, msg, 1);
+
+ if (err >= 0)
+ return 0;
+
+ printk(KERN_DEBUG "[TouchKey] %s %d i2c transfer error\n",
+ __func__, __LINE__);
+ mdelay(10);
+ }
+ return err;
+}
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+static int touchkey_autocalibration(void)
+{
+ u8 data[6] = { 0, };
+ int count = 0;
+ int ret = 0;
+ unsigned short retry = 0;
+
+ while (retry < 3) {
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 4);
+ if (ret < 0) {
+ printk(KERN_ERR "[TouchKey]i2c read fail.\n");
+ return ret;
+ }
+ printk(KERN_DEBUG
+ "[TouchKey] %s : data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
+ __func__, data[0], data[1], data[2], data[3]);
+
+ /* Send autocal Command */
+ data[0] = 0x50;
+ data[3] = 0x01;
+
+ count = i2c_touchkey_write(data, 4);
+
+ msleep(100);
+
+ /* Check autocal status */
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 6);
+
+ if ((data[5] & 0x80)) {
+ printk(KERN_DEBUG "[Touchkey] autocal Enabled\n");
+ break;
+ } else
+ printk(KERN_DEBUG
+ "[Touchkey] autocal disabled, retry %d\n",
+ retry);
+
+ retry = retry + 1;
+ }
+
+ if (retry == 3)
+ printk(KERN_DEBUG "[Touchkey] autocal failed\n");
+
+ return count;
+}
+#endif
+
+#ifdef CONFIG_TARGET_LOCALE_NAATT
+static ssize_t set_touchkey_autocal_testmode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int count = 0;
+ u8 set_data;
+ int on_off;
+
+ if (sscanf(buf, "%d\n", &on_off) == 1) {
+ printk(KERN_ERR "[TouchKey] Test Mode : %d\n", on_off);
+
+ if (on_off == 1) {
+ set_data = 0x40;
+ count = i2c_touchkey_write(&set_data, 1);
+ } else {
+ touchkey_ldo_on(0);
+ msleep(50);
+ touchkey_ldo_on(1);
+ msleep(50);
+ init_hw();
+ msleep(50);
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+ touchkey_autocalibration();
+#endif
+ }
+ } else {
+ printk(KERN_ERR "[TouchKey] touch_led_brightness Error\n");
+ }
+
+ return count;
+}
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+static ssize_t touchkey_raw_data0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[18] =%d,data[19] = %d\n", __func__,
+ data[18], data[19]);
+ raw_data0 = ((0x00FF & data[18]) << 8) | data[19];
+#elif defined(CONFIG_MACH_Q1_BD)
+ printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__,
+ data[16], data[17]);
+ raw_data0 = ((0x00FF & data[14]) << 8) | data[15];
+#else
+ printk(KERN_DEBUG "called %s data[18] =%d,data[19] = %d\n", __func__,
+ data[10], data[11]);
+ raw_data0 = ((0x00FF & data[10]) << 8) | data[11];
+#endif
+ return sprintf(buf, "%d\n", raw_data0);
+}
+
+static ssize_t touchkey_raw_data1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[20] =%d,data[21] = %d\n", __func__,
+ data[20], data[21]);
+ raw_data1 = ((0x00FF & data[20]) << 8) | data[21];
+#elif defined(CONFIG_MACH_Q1_BD)
+ printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__,
+ data[14], data[15]);
+ raw_data1 = ((0x00FF & data[16]) << 8) | data[17];
+#else
+ printk(KERN_DEBUG "called %s data[20] =%d,data[21] = %d\n", __func__,
+ data[12], data[13]);
+ raw_data1 = ((0x00FF & data[12]) << 8) | data[13];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", raw_data1);
+}
+
+static ssize_t touchkey_raw_data2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[22] =%d,data[23] = %d\n", __func__,
+ data[22], data[23]);
+ raw_data2 = ((0x00FF & data[22]) << 8) | data[23];
+#else
+ printk(KERN_DEBUG "called %s data[22] =%d,data[23] = %d\n", __func__,
+ data[14], data[15]);
+ raw_data2 = ((0x00FF & data[14]) << 8) | data[15];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", raw_data2);
+}
+
+static ssize_t touchkey_raw_data3_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[24] =%d,data[25] = %d\n", __func__,
+ data[24], data[25]);
+ raw_data3 = ((0x00FF & data[24]) << 8) | data[25];
+#else
+ printk(KERN_DEBUG "called %s data[24] =%d,data[25] = %d\n", __func__,
+ data[16], data[17]);
+ raw_data3 = ((0x00FF & data[16]) << 8) | data[17];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", raw_data3);
+}
+
+static ssize_t touchkey_idac0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[6] =%d\n", __func__, data[6]);
+ idac0 = data[6];
+ return sprintf(buf, "%d\n", idac0);
+}
+
+static ssize_t touchkey_idac1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[7] = %d\n", __func__, data[7]);
+ idac1 = data[7];
+ return sprintf(buf, "%d\n", idac1);
+}
+
+static ssize_t touchkey_idac2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[8] =%d\n", __func__, data[8]);
+ idac2 = data[8];
+ return sprintf(buf, "%d\n", idac2);
+}
+
+static ssize_t touchkey_idac3_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[9] = %d\n", __func__, data[9]);
+ idac3 = data[9];
+ return sprintf(buf, "%d\n", idac3);
+}
+
+static ssize_t touchkey_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[10];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[4] = %d\n", __func__, data[4]);
+ touchkey_threshold = data[4];
+ return sprintf(buf, "%d\n", touchkey_threshold);
+}
+#endif
+
+#if defined(CONFIG_MACH_C1_NA_SPR_EPIC2_REV00) \
+ || defined(CONFIG_MACH_Q1_BD) \
+ || defined(CONFIG_MACH_C1_NA_USCC_REV05) \
+ || defined(CONFIG_TARGET_LOCALE_NA)
+void touchkey_firmware_update(void)
+{
+ char data[3];
+ int retry = 3;
+ int ret = 0;
+
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 3);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read fail. do not excute firm update.\n");
+ return;
+ }
+
+ touch_version = data[1];
+ module_version = data[2];
+
+#ifdef CONFIG_MACH_C1_NA_SPR_EPIC2_REV00
+ if (system_rev > 6) {
+ printk(KERN_DEBUG "[TouchKey] not firmup hw(system_rev=%d)\n",
+ system_rev);
+ return;
+ }
+#endif
+
+ if ((touch_version < TK_FIRMWARE_VER) &&
+ (module_version == TK_MODULE_VER)) {
+ printk(KERN_DEBUG "[TouchKey] firmware auto update excute\n");
+ disable_irq(IRQ_TOUCH_INT);
+ touchkey_update_status = 1;
+
+ while (retry--) {
+ if (ISSP_main() == 0) {
+ printk(KERN_DEBUG
+ "[TouchKey]firmware update succeeded\n");
+ touchkey_update_status = 0;
+ break;
+ }
+ msleep(100);
+ printk(KERN_DEBUG
+ "[TouchKey] firmware update failed. retry\n");
+ }
+ if (retry <= 0) {
+ touchkey_ldo_on(0);
+ touchkey_update_status = -1;
+ printk(KERN_DEBUG
+ "[TouchKey] firmware update failed.\n");
+ msleep(300);
+ }
+ enable_irq(IRQ_TOUCH_INT);
+ init_hw();
+ } else {
+ printk(KERN_DEBUG
+ "[TouchKey] firmware auto update do not excute\n");
+ printk(KERN_DEBUG
+ "[TouchKey] firmware_ver(banary=%d, current=%d)\n",
+ TK_FIRMWARE_VER, touch_version);
+ printk(KERN_DEBUG
+ "[TouchKey] module_ver(banary=%d, current=%d)\n",
+ TK_MODULE_VER, module_version);
+ return;
+ }
+ msleep(100);
+ i2c_touchkey_read(KEYCODE_REG, data, 3);
+ touch_version = data[1];
+ module_version = data[2];
+ printk(KERN_DEBUG "[TouchKey] firm ver = %d, module ver = %d\n",
+ touch_version, module_version);
+}
+#else
+void touchkey_firmware_update(void)
+{
+ char data[3];
+ int retry;
+ int ret = 0;
+
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 3);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read fail. do not excute firm update.\n");
+ return;
+ }
+
+ printk(KERN_ERR "%s F/W version: 0x%x, Module version:0x%x\n", __func__,
+ data[1], data[2]);
+ retry = 3;
+
+ touch_version = data[1];
+ module_version = data[2];
+
+ if (touch_version < 0x0A) {
+ touchkey_update_status = 1;
+ while (retry--) {
+ if (ISSP_main() == 0) {
+ printk(KERN_ERR
+ "[TOUCHKEY]Touchkey_update succeeded\n");
+ touchkey_update_status = 0;
+ break;
+ }
+ printk(KERN_ERR "touchkey_update failed...retry...\n");
+ }
+ if (retry <= 0) {
+ touchkey_ldo_on(0);
+ touchkey_update_status = -1;
+ msleep(300);
+ }
+
+ init_hw();
+ } else {
+ if (touch_version >= 0x0A) {
+ printk(KERN_ERR
+ "[TouchKey] Not F/W update. Cypess touch-key F/W version is latest\n");
+ } else {
+ printk(KERN_ERR
+ "[TouchKey] Not F/W update. Cypess touch-key version(module or F/W) is not valid\n");
+ }
+ }
+}
+#endif
+
+#ifndef TEST_JIG_MODE
+void touchkey_work_func(struct work_struct *p)
+{
+ u8 data[3];
+ int ret;
+ int retry = 10;
+ int keycode_type = 0;
+ int pressed;
+ int status;
+
+ set_touchkey_debug('a');
+
+ retry = 3;
+ while (retry--) {
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 3);
+ if (!ret)
+ break;
+ else {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read failed, ret:%d, retry: %d\n",
+ ret, retry);
+ continue;
+ }
+ }
+ if (ret < 0) {
+ enable_irq(IRQ_TOUCH_INT);
+ return;
+ }
+ set_touchkey_debug(data[0]);
+
+ keycode_type = (data[0] & KEYCODE_BIT);
+ pressed = !(data[0] & UPDOWN_EVENT_BIT);
+
+ if (keycode_type <= 0 || keycode_type >= touchkey_count) {
+ printk(KERN_DEBUG "[Touchkey] keycode_type err\n");
+ enable_irq(IRQ_TOUCH_INT);
+ return;
+ }
+
+ if (pressed)
+ set_touchkey_debug('P');
+
+ if (get_tsp_status() && pressed)
+ printk(KERN_DEBUG "[TouchKey] touchkey pressed but don't send event because touch is pressed.\n");
+ else {
+ input_report_key(touchkey_driver->input_dev,
+ touchkey_keycode[keycode_type], pressed);
+ input_sync(touchkey_driver->input_dev);
+ /* printk(KERN_DEBUG "[TouchKey] keycode:%d pressed:%d\n",
+ touchkey_keycode[keycode_index], pressed); */
+ }
+
+ /* we have timed out or the lights should be on */
+ if (led_timeout > 0) {
+ status = 1;
+ i2c_touchkey_write((u8 *)&status, 1); /* turn on */
+ }
+
+ /* restart the timer */
+ if (led_timeout > 0) {
+ mod_timer(&led_timer, jiffies + msecs_to_jiffies(led_timeout));
+ }
+
+ set_touchkey_debug('A');
+ enable_irq(IRQ_TOUCH_INT);
+}
+#else
+void touchkey_work_func(struct work_struct *p)
+{
+ u8 data[18];
+ int ret;
+ int retry = 10;
+ int keycode_type = 0;
+ int pressed;
+
+#if 0
+ if (gpio_get_value(_3_GPIO_TOUCH_INT)) {
+ printk(KERN_DEBUG "[TouchKey] Unknown state.\n", __func__);
+ enable_irq(IRQ_TOUCH_INT);
+ return;
+ }
+#endif
+
+ set_touchkey_debug('a');
+
+#ifdef CONFIG_CPU_FREQ
+ /* set_dvfs_target_level(LEV_800MHZ); */
+#endif
+
+ retry = 3;
+ while (retry--) {
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 18);
+#else
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+#endif
+ if (!ret)
+ break;
+ else {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read failed, ret:%d, retry: %d\n",
+ ret, retry);
+ continue;
+ }
+ }
+ if (ret < 0) {
+ enable_irq(IRQ_TOUCH_INT);
+ return;
+ }
+#if defined(CONFIG_TARGET_LOCALE_NA)
+#if defined(CONFIG_MACH_C1_NA_SPR_EPIC2_REV00)
+ menu_sensitivity = data[11];
+ home_sensitivity = data[13];
+ search_sensitivity = data[15];
+ back_sensitivity = data[17];
+#else
+ if (store_module_version >= 8) {
+ menu_sensitivity = data[17];
+ home_sensitivity = data[15];
+ search_sensitivity = data[11];
+ back_sensitivity = data[13];
+ } else {
+ menu_sensitivity = data[6];
+ home_sensitivity = data[7];
+ search_sensitivity = data[8];
+ back_sensitivity = data[9];
+ }
+#endif
+#elif defined(CONFIG_MACH_Q1_BD)
+ menu_sensitivity = data[13];
+ back_sensitivity = data[11];
+#else
+ menu_sensitivity = data[7];
+ back_sensitivity = data[9];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+
+ set_touchkey_debug(data[0]);
+
+ keycode_type = (data[0] & KEYCODE_BIT);
+ pressed = !(data[0] & UPDOWN_EVENT_BIT);
+
+ if (keycode_type <= 0 || keycode_type >= touchkey_count) {
+ printk(KERN_DEBUG "[Touchkey] keycode_type err\n");
+ enable_irq(IRQ_TOUCH_INT);
+ return;
+ }
+
+ if (pressed)
+ set_touchkey_debug('P');
+
+ if (get_tsp_status() && pressed)
+ printk(KERN_DEBUG "[TouchKey] touchkey pressed"
+ " but don't send event because touch is pressed.\n");
+ else {
+ input_report_key(touchkey_driver->input_dev,
+ touchkey_keycode[keycode_type], pressed);
+ input_sync(touchkey_driver->input_dev);
+ /* printk(KERN_DEBUG "[TouchKey] keycode:%d pressed:%d\n",
+ touchkey_keycode[keycode_index], pressed); */
+ }
+
+ if (keycode_type == 1)
+ printk(KERN_DEBUG "search key sensitivity = %d\n",
+ search_sensitivity);
+ if (keycode_type == 2)
+ printk(KERN_DEBUG "back key sensitivity = %d\n",
+ back_sensitivity);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (keycode_type == 3)
+ printk(KERN_DEBUG "home key sensitivity = %d\n",
+ home_sensitivity);
+ if (keycode_type == 4)
+ printk(KERN_DEBUG "menu key sensitivity = %d\n",
+ menu_sensitivity);
+#endif
+
+#ifdef WHY_DO_WE_NEED_THIS
+ /* clear interrupt */
+ if (readl(gpio_pend_mask_mem) & (0x1 << 1)) {
+ writel(readl(gpio_pend_mask_mem) | (0x1 << 1),
+ gpio_pend_mask_mem);
+ }
+#endif
+ set_touchkey_debug('A');
+ enable_irq(IRQ_TOUCH_INT);
+}
+#endif
+
+static irqreturn_t touchkey_interrupt(int irq, void *dummy)
+{
+#ifdef CONFIG_TOUCHKEY_BLN
+ printk(KERN_ERR "[TouchKey] interrupt touchkey\n");
+#endif
+ set_touchkey_debug('I');
+ disable_irq_nosync(IRQ_TOUCH_INT);
+ queue_work(touchkey_wq, &touchkey_work);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static int sec_touchkey_early_suspend(struct early_suspend *h)
+{
+ int ret;
+ int i;
+
+ disable_irq(IRQ_TOUCH_INT);
+ ret = cancel_work_sync(&touchkey_work);
+ if (ret) {
+ printk(KERN_DEBUG "[Touchkey] enable_irq ret=%d\n", ret);
+ enable_irq(IRQ_TOUCH_INT);
+ }
+
+ /* release keys */
+ for (i = 1; i < touchkey_count; ++i) {
+ input_report_key(touchkey_driver->input_dev,
+ touchkey_keycode[i], 0);
+ }
+
+ touchkey_enable = 0;
+ set_touchkey_debug('S');
+ printk(KERN_DEBUG "[TouchKey] sec_touchkey_early_suspend\n");
+ if (touchkey_enable < 0) {
+ printk(KERN_DEBUG "[TouchKey] ---%s---touchkey_enable: %d\n",
+ __func__, touchkey_enable);
+ return 0;
+ }
+
+ gpio_direction_input(_3_GPIO_TOUCH_INT);
+#if 0
+ gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
+ gpio_direction_output(_3_TOUCH_SDA_28V, 0);
+ gpio_direction_output(_3_TOUCH_SCL_28V, 0);
+ s3c_gpio_setpull(_3_GPIO_TOUCH_INT, S3C_GPIO_PULL_DOWN);
+#endif
+
+ /* disable ldo18 */
+ touchkey_led_ldo_on(0);
+
+ /* disable ldo11 */
+ touchkey_ldo_on(0);
+
+ bln_suspended = 1;
+ return 0;
+}
+
+static int sec_touchkey_late_resume(struct early_suspend *h)
+{
+#ifdef TEST_JIG_MODE
+ unsigned char get_touch = 0x40;
+#endif
+ int status;
+
+ set_touchkey_debug('R');
+ printk(KERN_DEBUG "[TouchKey] sec_touchkey_late_resume\n");
+
+ /* Avoid race condition with LED notification disable */
+ down(&enable_sem);
+
+ /* enable ldo11 */
+ touchkey_ldo_on(1);
+
+ if (touchkey_enable < 0) {
+ printk(KERN_DEBUG "[TouchKey] ---%s---touchkey_enable: %d\n",
+ __func__, touchkey_enable);
+ return 0;
+ }
+ gpio_direction_output(_3_GPIO_TOUCH_EN, 1);
+ gpio_direction_output(_3_TOUCH_SDA_28V, 1);
+ gpio_direction_output(_3_TOUCH_SCL_28V, 1);
+
+ gpio_direction_output(_3_GPIO_TOUCH_INT, 1);
+ irq_set_irq_type(IRQ_TOUCH_INT, IRQF_TRIGGER_FALLING);
+ s3c_gpio_cfgpin(_3_GPIO_TOUCH_INT, _3_GPIO_TOUCH_INT_AF);
+ s3c_gpio_setpull(_3_GPIO_TOUCH_INT, S3C_GPIO_PULL_NONE);
+ msleep(50);
+ touchkey_led_ldo_on(1);
+
+#ifdef WHY_DO_WE_NEED_THIS
+ /* clear interrupt */
+ if (readl(gpio_pend_mask_mem) & (0x1 << 1)) {
+ writel(readl(gpio_pend_mask_mem) | (0x1 << 1),
+ gpio_pend_mask_mem);
+ }
+#endif
+
+ touchkey_enable = 1;
+
+ bln_suspended = 0;
+ /* see if late_resume is running before DISABLE_BL */
+ if (BLN_ongoing) {
+ /* if a notification timeout was set, disable the timer */
+ if (notification_timeout > 0) {
+ del_timer(&notification_timer);
+ }
+ if (breathing) stop_breathing();
+
+ /* we were using a wakelock, unlock it */
+ if( wake_lock_active(&bln_wake_lock) ){
+ printk(KERN_DEBUG "[TouchKey] touchkey clear wake_lock\n");
+ wake_unlock(&bln_wake_lock);
+ }
+ /* force DISABLE_BL to ignore the led state because we want it left on */
+ BLN_ongoing = 0;
+ }
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ if (store_module_version >= 8) {
+#endif
+ msleep(50);
+ touchkey_autocalibration();
+ msleep(200);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ }
+#endif /* CONFIG_TARGET_LOCALE_NA */
+#endif
+
+ if (touchled_cmd_reversed) {
+ touchled_cmd_reversed = 0;
+ i2c_touchkey_write((u8 *) &touchkey_led_status, 1);
+ printk(KERN_DEBUG "LED returned on\n");
+ }
+#ifdef TEST_JIG_MODE
+ i2c_touchkey_write(&get_touch, 1);
+#endif
+
+ /* restart the timer if needed */
+ if (led_timeout > 0) {
+ mod_timer(&led_timer, jiffies + msecs_to_jiffies(led_timeout));
+ }
+
+ /* all done, turn on IRQ */
+ enable_irq(IRQ_TOUCH_INT);
+
+ /* Avoid race condition with LED notification disable */
+ up(&enable_sem);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_TOUCHKEY_BLN
+
+static void touchkey_activate(void){
+
+ if( !wake_lock_active(&bln_wake_lock) ){
+ printk(KERN_DEBUG "[TouchKey] touchkey get wake_lock\n");
+ wake_lock(&bln_wake_lock);
+ }
+
+ printk(KERN_DEBUG "[TouchKey] touchkey activate.\n");
+ touchkey_ldo_on(1);
+
+ msleep(50);
+ touchkey_led_ldo_on(1);
+
+ touchkey_enable = 1;
+}
+
+static void touchkey_deactivate(void){
+
+ touchkey_led_ldo_on(0);
+ touchkey_ldo_on(0);
+
+ if( wake_lock_active(&bln_wake_lock) ){
+ printk(KERN_DEBUG "[TouchKey] touchkey clear wake_lock\n");
+ wake_unlock(&bln_wake_lock);
+ }
+
+ touchkey_enable = 0;
+}
+
+static void bln_late_resume(struct early_suspend *h){
+
+ /* the lights should be off */
+ //we only need this part to disable lights way before ROM specific parts interfere -gm
+ int status;
+ status = 2;
+ i2c_touchkey_write((u8 *)&status, 1); /* turn off */
+}
+
+static struct early_suspend bln_suspend_data = {
+ .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1,
+ .resume = bln_late_resume,
+};
+
+static void enable_touchkey_backlights(void){
+ int status = 1;
+ printk(KERN_ERR "[TouchKey] enable LED from BLN app\n");
+ i2c_touchkey_write((u8 *)&status, 1 );
+}
+
+static void disable_touchkey_backlights(void){
+ int status = 2;
+ printk(KERN_ERR "[TouchKey] disable LED from BLN app\n");
+ i2c_touchkey_write((u8 *)&status, 1 );
+}
+
+static void enable_led_notification(void){
+
+ if( bln_enabled ){
+ if( touchkey_enable != 1 ){
+ if( bln_suspended ){
+ touchkey_activate();
+ }
+ }
+ if( touchkey_enable == 1 ){
+ printk(KERN_DEBUG "[TouchKey] BLN_ongoing set to true\n");
+ BLN_ongoing = true;
+ enable_touchkey_backlights();
+ }
+ /* See if a timeout value has been set for the notification */
+ if (notification_timeout > 0) {
+ /* restart the timer */
+ mod_timer(&notification_timer, jiffies + msecs_to_jiffies(notification_timeout));
+ }
+ if ( breathing ) mod_timer(&breathing_timer, jiffies + 4);
+
+ }
+
+}
+
+static void disable_led_notification(void){
+
+ down(&enable_sem);
+ bln_blink_enabled = false;
+ BLN_ongoing = false;
+ printk(KERN_DEBUG "[TouchKey] BLN_ongoing set to false\n");
+
+ if( touchkey_enable == 1 ){
+ disable_touchkey_backlights();
+ if( bln_suspended ){
+ touchkey_deactivate();
+ }
+ /* a notification timeout was set, disable the timer */
+ if (notification_timeout > 0) {
+ del_timer(&notification_timer);
+ }
+ if (breathing) stop_breathing();
+ }
+ up(&enable_sem);
+}
+
+static ssize_t bln_status_read( struct device *dev, struct device_attribute *attr, char *buf ){
+ return sprintf(buf,"%u\n", (bln_enabled ? 1 : 0 ));
+}
+
+static ssize_t bln_status_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size ){
+ unsigned int data;
+
+ if(sscanf(buf,"%u\n", &data) == 1 ){
+ if( data == 0 || data == 1 ){
+
+ if( data == 1 ){
+ bln_enabled = true;
+ }
+
+ if( data == 0 ){
+ bln_enabled = false;
+ if( BLN_ongoing )
+ disable_led_notification();
+ }
+
+ }else{
+ /* error */
+ }
+ }else{
+ if( !strncmp(buf, "on", 2) ) bln_enabled = true;
+ if( !strncmp(buf, "off", 3) ) {
+ bln_enabled = false;
+ if( BLN_ongoing )
+ disable_led_notification();
+ }
+ }
+
+ return size;
+}
+
+static ssize_t notification_led_status_read( struct device *dev, struct device_attribute *attr, char *buf ){
+ return sprintf(buf,"%u\n", (BLN_ongoing ? 1 : 0 ));
+}
+
+static ssize_t notification_led_status_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size ){
+ unsigned int data;
+
+
+ if(sscanf(buf,"%u\n", &data ) == 1 ){
+ if( data == 0 || data == 1 ){
+ if( data == 1 )
+ enable_led_notification();
+
+ if( data == 0 )
+ disable_led_notification();
+ }else{
+ /* error */
+ }
+ }else{
+ /* error */
+ }
+
+ return size;
+}
+
+static ssize_t blink_control_read( struct device *dev, struct device_attribute *attr, char *buf ){
+ return sprintf( buf, "%u\n", (bln_blink_enabled ? 1 : 0 ) );
+}
+
+static ssize_t blink_control_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size ){
+ unsigned int data;
+
+ if( sscanf(buf, "%u\n", &data ) == 1 ){
+ if( data == 0 || data == 1 ){
+ if (data == 1){
+ bln_blink_enabled = true;
+ disable_touchkey_backlights();
+ }
+
+ if(data == 0){
+ bln_blink_enabled = false;
+ enable_touchkey_backlights();
+ }
+ }
+ }
+
+ return size;
+}
+
+static ssize_t bln_version( struct device *dev, struct device_attribute *attr, char *buf ){
+ return sprintf(buf,"%u\n", BLN_VERSION);
+}
+
+static DEVICE_ATTR(blink_control, S_IRUGO | S_IWUGO, blink_control_read, blink_control_write );
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUGO, bln_status_read, bln_status_write );
+static DEVICE_ATTR(notification_led, S_IRUGO | S_IWUGO, notification_led_status_read, notification_led_status_write );
+static DEVICE_ATTR(version, S_IRUGO, bln_version, NULL );
+
+static struct attribute *bln_notification_attributes[] = {
+ &dev_attr_blink_control.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_notification_led.attr,
+ &dev_attr_version.attr,
+ NULL
+};
+
+
+/*
+ * Start of the main LED Notify code block
+ */
+static void bl_off(struct work_struct *bl_off_work)
+{
+ int status;
+
+ /* do nothing if there is an active notification */
+ if (BLN_ongoing == 1 || touchkey_enable != 1)
+ return;
+
+ /* we have timed out, turn the lights off */
+ status = 2;
+ i2c_touchkey_write((u8 *)&status, 1);
+
+ return;
+}
+
+static void handle_led_timeout(unsigned long data)
+{
+ /* we cannot call the timeout directly as it causes a kernel spinlock BUG, schedule it instead */
+ schedule_work(&bl_off_work);
+}
+
+static void notification_off(struct work_struct *notification_off_work)
+{
+ /* do nothing if there is no active notification */
+ if (BLN_ongoing != 1 || touchkey_enable != 1)
+ return;
+
+ disable_touchkey_backlights();
+ touchkey_deactivate();
+ BLN_ongoing = 0;
+}
+
+static void handle_notification_timeout(unsigned long data)
+{
+ /* we cannot call the timeout directly as it causes a kernel spinlock BUG, schedule it instead */
+ schedule_work(&notification_off_work);
+}
+
+static ssize_t led_timeout_read( struct device *dev, struct device_attribute *attr, char *buf )
+{
+ return sprintf(buf,"%d\n", led_timeout);
+}
+
+static ssize_t led_timeout_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size )
+{
+ sscanf(buf,"%d\n", &led_timeout);
+ if(led_timeout == 0) del_timer(&led_timer);
+ else mod_timer(&led_timer, jiffies + msecs_to_jiffies(led_timeout));
+ return size;
+}
+
+static ssize_t notification_timeout_read( struct device *dev, struct device_attribute *attr, char *buf )
+{
+ return sprintf(buf,"%d\n", notification_timeout);
+}
+
+static ssize_t notification_timeout_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size )
+{
+ sscanf(buf,"%d\n", &notification_timeout);
+ return size;
+}
+
+static void breathe(struct work_struct *notification_off_work)
+{
+ int data;
+ if (BLN_ongoing != 1 || touchkey_enable != 1)
+ return;
+
+ if( breathing_steps[breathing_step_idx].start <= breathing_steps[breathing_step_idx].end )
+ {
+ data = breathing_steps[breathing_step_idx].start +
+ breathing_idx++ * breathing_steps[breathing_step_idx].step;
+ if( data > breathing_steps[breathing_step_idx].end )
+ {
+ breathing_idx = 0;
+ breathing_step_idx++;
+ if( breathing_step_idx >= breathing_step_count ) breathing_step_idx = 0;
+ data = breathing_steps[breathing_step_idx].start;
+ }
+ }
+ else
+ {
+ data = breathing_steps[breathing_step_idx].start -
+ breathing_idx++ * breathing_steps[breathing_step_idx].step;
+ if( data < breathing_steps[breathing_step_idx].end )
+ {
+ breathing_idx = 0;
+ breathing_step_idx++;
+ if( breathing_step_idx >= breathing_step_count ) breathing_step_idx = 0;
+ data = breathing_steps[breathing_step_idx].start;
+ }
+ }
+
+ change_touch_key_led_voltage(data);
+ mod_timer(&breathing_timer, jiffies + msecs_to_jiffies(breathing_steps[breathing_step_idx].period));
+}
+
+static void handle_breathe(unsigned long data)
+{
+ schedule_work(&breathe_work);
+}
+
+static ssize_t breathing_read( struct device *dev, struct device_attribute *attr, char *buf )
+{
+ return sprintf(buf,"%d\n", breathing);
+}
+static ssize_t breathing_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size )
+{
+ if( !strncmp(buf, "on", 2) ) breathing = 1;
+ else if( !strncmp(buf, "off", 3) ) breathing = 0;
+ else sscanf(buf,"%d\n", &breathing);
+ if( breathing != 1 ) stop_breathing();
+ return size;
+}
+
+void reset_breathing_steps(void)
+{
+ //this will reset steps to have steady bln
+ breathing_step_count = 0;
+ breathing_steps[0].start = 3000;
+ breathing_steps[0].end = 3000;
+ breathing_steps[0].period = 1000;
+ breathing_steps[0].step = 50;
+}
+
+static ssize_t breathing_steps_read( struct device *dev, struct device_attribute *attr, char *buf )
+{
+ int count = ( breathing_step_count == 0 ? 1 : breathing_step_count );
+ int i, len = 0;
+ for(i=0; i<count; i++)
+ {
+ len += sprintf(buf + len, "%dmV %dmV %dms %dmV\n", breathing_steps[i].start, breathing_steps[i].end,
+ breathing_steps[i].period, breathing_steps[i].step);
+ }
+ return len;
+}
+
+static ssize_t breathing_steps_write( struct device *dev, struct device_attribute *attr, const char *buf, size_t size )
+{
+ int ret;
+ int bstart, bend, bperiod, bstep;
+
+ if(!strncmp(buf, "reset", 5)) {
+ reset_breathing_steps();
+ return size;
+ }
+ if(breathing_step_count >= MAX_BREATHING_STEPS) return -EINVAL;
+ ret = sscanf(buf, "%d %d %d %d", &bstart, &bend, &bperiod, &bstep);
+ if(ret != 4) return -EINVAL;
+ breathing_steps[breathing_step_count].start = bstart;
+ breathing_steps[breathing_step_count].end = bend;
+ breathing_steps[breathing_step_count].period = bperiod;
+ breathing_steps[breathing_step_count].step = bstep;
+ breathing_step_count++;
+ breathing_idx = 0;
+ breathing_step_idx = 0;
+ return size;
+}
+
+static struct miscdevice led_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "notification",
+};
+
+static DEVICE_ATTR(led, S_IRUGO | S_IWUGO, notification_led_status_read, notification_led_status_write );
+static DEVICE_ATTR(notification_timeout, S_IRUGO | S_IWUGO, notification_timeout_read, notification_timeout_write );
+static DEVICE_ATTR(led_timeout, S_IRUGO | S_IWUGO, led_timeout_read, led_timeout_write );
+static DEVICE_ATTR(bl_timeout, S_IRUGO | S_IWUGO, led_timeout_read, led_timeout_write );
+static DEVICE_ATTR(notification_enabled, S_IRUGO | S_IWUGO, bln_status_read, bln_status_write );
+static DEVICE_ATTR(breathing, S_IRUGO | S_IWUGO, breathing_read, breathing_write );
+static DEVICE_ATTR(breathing_steps, S_IRUGO | S_IWUGO, breathing_steps_read, breathing_steps_write );
+
+static struct attribute *led_notification_attributes[] = {
+ &dev_attr_led.attr,
+ &dev_attr_led_timeout.attr,
+ &dev_attr_bl_timeout.attr,
+ &dev_attr_notification_timeout.attr,
+ &dev_attr_notification_enabled.attr,
+ &dev_attr_breathing.attr,
+ &dev_attr_breathing_steps.attr,
+ NULL
+};
+
+static struct attribute_group led_notification_group = {
+ .attrs = led_notification_attributes,
+};
+
+static struct attribute_group bln_notification_group = {
+ .attrs = bln_notification_attributes,
+};
+
+static struct miscdevice bln_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "backlightnotification",
+};
+
+extern void (*mxt224_touch_cb)(void);
+
+void cypress_notify_touch(void)
+{
+ unsigned int status;
+ if (led_timeout > 0) {
+ status = 1;
+ i2c_touchkey_write((u8 *)&status, 1); /* turn on */
+ }
+ if (led_timeout > 0) {
+ mod_timer(&led_timer, jiffies + msecs_to_jiffies(led_timeout));
+ }
+}
+
+#endif
+
+extern int mcsdl_download_binary_data(void);
+static int i2c_touchkey_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct input_dev *input_dev;
+ int err = 0;
+ unsigned char data;
+ int i;
+ int module_version;
+ int status;
+
+ printk(KERN_DEBUG "[TouchKey] i2c_touchkey_probe\n");
+
+ touchkey_driver =
+ kzalloc(sizeof(struct i2c_touchkey_driver), GFP_KERNEL);
+ if (touchkey_driver == NULL) {
+ dev_err(dev, "failed to create our state\n");
+ return -ENOMEM;
+ }
+
+ touchkey_driver->client = client;
+ touchkey_driver->client->irq = IRQ_TOUCH_INT;
+ strlcpy(touchkey_driver->client->name, "sec_touchkey", I2C_NAME_SIZE);
+
+ input_dev = input_allocate_device();
+
+ if (!input_dev)
+ return -ENOMEM;
+
+ touchkey_driver->input_dev = input_dev;
+
+ input_dev->name = DEVICE_NAME;
+ input_dev->phys = "sec_touchkey/input0";
+ input_dev->id.bustype = BUS_HOST;
+
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_LED, input_dev->evbit);
+ set_bit(LED_MISC, input_dev->ledbit);
+ set_bit(EV_KEY, input_dev->evbit);
+
+ for (i = 1; i < touchkey_count; i++)
+ set_bit(touchkey_keycode[i], input_dev->keybit);
+
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+#ifdef WHY_DO_WE_NEED_THIS
+ gpio_pend_mask_mem = ioremap(INT_PEND_BASE, 0x10);
+#endif
+
+#if defined(CONFIG_MACH_S2PLUS)
+ gpio_request(GPIO_3_TOUCH_EN, "gpio_3_touch_en");
+#endif
+
+ /* enable ldo18 */
+ touchkey_ldo_on(1);
+
+ msleep(50);
+
+ touchkey_enable = 1;
+ data = 1;
+
+ module_version = get_touchkey_module_version();
+ if (module_version < 0) {
+ printk(KERN_ERR "[TouchKey] Probe fail\n");
+ input_unregister_device(input_dev);
+ touchkey_probe = false;
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_TARGET_LOCALE_NA
+ store_module_version = module_version;
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ if (request_irq
+ (IRQ_TOUCH_INT, touchkey_interrupt, IRQF_TRIGGER_FALLING,
+ DEVICE_NAME, NULL)) {
+ printk(KERN_ERR "[TouchKey] %s Can't allocate irq ..\n",
+ __func__);
+ return -EBUSY;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ touchkey_driver->early_suspend.suspend =
+ (void *)sec_touchkey_early_suspend;
+ touchkey_driver->early_suspend.resume =
+ (void *)sec_touchkey_late_resume;
+ register_early_suspend(&touchkey_driver->early_suspend);
+#endif
+
+ touchkey_led_ldo_on(1);
+
+#if defined(CONFIG_MACH_C1_NA_SPR_EPIC2_REV00)\
+ || defined(CONFIG_MACH_Q1_BD) \
+ || defined(CONFIG_MACH_C1_NA_USCC_REV05)
+
+ touchkey_firmware_update();
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+ /*touchkey_firmware_update(); */
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ if (store_module_version >= 8) {
+#endif
+ msleep(100);
+ err = touchkey_autocalibration();
+ if (err < 0) {
+ printk(KERN_ERR
+ "[TouchKey] probe autocalibration fail\n");
+ return err;
+ }
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ }
+#endif /* CONFIG_TARGET_LOCALE_NA */
+#endif
+ set_touchkey_debug('K');
+
+#ifdef CONFIG_TOUCHKEY_BLN
+ err = misc_register( &bln_device );
+ if( err ){
+ printk(KERN_ERR "[BLN] sysfs misc_register failed.\n");
+ }else{
+ if( sysfs_create_group( &bln_device.this_device->kobj, &bln_notification_group) < 0){
+ printk(KERN_ERR "[BLN] sysfs create group failed.\n");
+ }
+ }
+
+ /* BLN early suspend */
+ register_early_suspend(&bln_suspend_data);
+
+ //this miscdevice is for cm9
+ err = misc_register( &led_device );
+ if( err ){
+ printk(KERN_ERR "[LED] sysfs misc_register failed.\n");
+ }else{
+ if( sysfs_create_group( &led_device.this_device->kobj, &led_notification_group) < 0){
+ printk(KERN_ERR "[LED] sysfs create group failed.\n");
+ }
+ }
+
+ /* Setup the timer for the timeouts */
+ setup_timer(&led_timer, handle_led_timeout, 0);
+ setup_timer(&notification_timer, handle_notification_timeout, 0);
+ setup_timer(&breathing_timer, handle_breathe, 0);
+
+ led_timeout = 0;
+ reset_breathing_steps();
+
+ /* wake lock for BLN */
+ wake_lock_init(&bln_wake_lock, WAKE_LOCK_SUSPEND, "bln_wake_lock");
+ /* turn off the LED on probe */
+ status = 2;
+ i2c_touchkey_write((u8 *)&status, 1);
+
+ mxt224_touch_cb = cypress_notify_touch;
+#endif
+
+ return 0;
+}
+
+static void init_hw(void)
+{
+ gpio_direction_output(_3_GPIO_TOUCH_EN, 1);
+ msleep(200);
+ s3c_gpio_setpull(_3_GPIO_TOUCH_INT, S3C_GPIO_PULL_NONE);
+ irq_set_irq_type(IRQ_TOUCH_INT, IRQF_TRIGGER_FALLING);
+ s3c_gpio_cfgpin(_3_GPIO_TOUCH_INT, _3_GPIO_TOUCH_INT_AF);
+}
+
+static int get_touchkey_module_version()
+{
+ char data[3] = { 0, };
+ int ret = 0;
+
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 3);
+ if (ret < 0) {
+ printk(KERN_ERR "[TouchKey] module version read fail\n");
+ return ret;
+ } else {
+ printk(KERN_DEBUG "[TouchKey] Module Version: %d\n", data[2]);
+ return data[2];
+ }
+}
+
+int touchkey_update_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+ssize_t touchkey_update_read(struct file *filp, char *buf, size_t count,
+ loff_t *f_pos)
+{
+ char data[3] = { 0, };
+
+ get_touchkey_firmware(data);
+ put_user(data[1], buf);
+
+ return 1;
+}
+
+int touchkey_update_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static ssize_t touch_version_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char data[3] = { 0, };
+ int count;
+
+ init_hw();
+ i2c_touchkey_read(KEYCODE_REG, data, 3);
+
+ count = sprintf(buf, "0x%x\n", data[1]);
+
+ printk(KERN_DEBUG "[TouchKey] touch_version_read 0x%x\n", data[1]);
+ printk(KERN_DEBUG "[TouchKey] module_version_read 0x%x\n", data[2]);
+
+ return count;
+}
+
+static ssize_t touch_version_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ printk(KERN_DEBUG "[TouchKey] input data --> %s\n", buf);
+
+ return size;
+}
+
+void touchkey_update_func(struct work_struct *p)
+{
+ int retry = 10;
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+ char data[3];
+ i2c_touchkey_read(KEYCODE_REG, data, 3);
+ printk(KERN_DEBUG "[%s] F/W version: 0x%x, Module version:0x%x\n",
+ __func__, data[1], data[2]);
+#endif
+ touchkey_update_status = 1;
+ printk(KERN_DEBUG "[TouchKey] %s start\n", __func__);
+ touchkey_enable = 0;
+ while (retry--) {
+ if (ISSP_main() == 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] touchkey_update succeeded\n");
+ init_hw();
+ enable_irq(IRQ_TOUCH_INT);
+ touchkey_enable = 1;
+#if defined(CONFIG_MACH_Q1_BD)
+ touchkey_autocalibration();
+#else
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ if (store_module_version >= 8)
+ touchkey_autocalibration();
+#endif
+#endif
+ touchkey_update_status = 0;
+ return;
+ }
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+ touchkey_ldo_on(0);
+ msleep(300);
+ init_hw();
+#endif
+ }
+
+ touchkey_update_status = -1;
+ printk(KERN_DEBUG "[TouchKey] touchkey_update failed\n");
+ return;
+}
+
+static ssize_t touch_update_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8) {
+ printk(KERN_DEBUG
+ "[TouchKey] Skipping f/w update : module_version =%d\n",
+ store_module_version);
+ touchkey_update_status = 0;
+ return 1;
+ } else {
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ printk(KERN_DEBUG "[TouchKey] touchkey firmware update\n");
+
+ if (*buf == 'S') {
+ disable_irq(IRQ_TOUCH_INT);
+ INIT_WORK(&touch_update_work, touchkey_update_func);
+ queue_work(touchkey_wq, &touch_update_work);
+ }
+ return size;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ }
+#endif /* CONFIG_TARGET_LOCALE_NA */
+}
+
+static ssize_t touch_update_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+
+ printk(KERN_DEBUG
+ "[TouchKey] touch_update_read: touchkey_update_status %d\n",
+ touchkey_update_status);
+
+ if (touchkey_update_status == 0)
+ count = sprintf(buf, "PASS\n");
+ else if (touchkey_update_status == 1)
+ count = sprintf(buf, "Downloading\n");
+ else if (touchkey_update_status == -1)
+ count = sprintf(buf, "Fail\n");
+
+ return count;
+}
+
+static ssize_t touch_led_control(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ int data;
+ int errnum;
+
+ if (sscanf(buf, "%d\n", &data) == 1) {
+#if defined(CONFIG_MACH_Q1_BD)
+ if (data == 1)
+ data = 0x10;
+ else if (data == 2)
+ data = 0x20;
+#elif defined(CONFIG_TARGET_LOCALE_NA)
+ if (store_module_version >= 8) {
+ if (data == 1)
+ data = 0x10;
+ else if (data == 2)
+ data = 0x20;
+ }
+#endif
+#ifdef CONFIG_TOUCHKEY_BLN
+ printk(KERN_ERR "[TouchKey] system calling LED Notification control\n");
+#endif
+ errnum = i2c_touchkey_write((u8 *) &data, 1);
+ if( data == 1 && led_timeout > 0 )
+ mod_timer(&led_timer, jiffies + msecs_to_jiffies(led_timeout));
+ if (errnum == -ENODEV)
+ touchled_cmd_reversed = 1;
+
+ touchkey_led_status = data;
+ } else {
+ printk(KERN_DEBUG "[TouchKey] touch_led_control Error\n");
+ }
+
+ return size;
+}
+
+static ssize_t touchkey_enable_disable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ return size;
+}
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) || defined(CONFIG_TARGET_LOCALE_NA)
+static ssize_t touchkey_menu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8) {
+ printk(KERN_DEBUG "called %s data[12] =%d,data[13] = %d\n",
+ __func__, data[12], data[13]);
+ menu_sensitivity = ((0x00FF & data[12]) << 8) | data[13];
+ } else {
+ printk(KERN_DEBUG "called %s data[17] =%d\n", __func__,
+ data[17]);
+ menu_sensitivity = data[17];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[10] =%d,data[11] = %d\n", __func__,
+ data[10], data[11]);
+ menu_sensitivity = ((0x00FF & data[10]) << 8) | data[11];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", menu_sensitivity);
+}
+
+static ssize_t touchkey_home_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8) {
+ printk(KERN_DEBUG "called %s data[10] =%d,data[11] = %d\n",
+ __func__, data[10], data[11]);
+ home_sensitivity = ((0x00FF & data[10]) << 8) | data[11];
+ } else {
+ printk(KERN_DEBUG "called %s data[15] =%d\n", __func__,
+ data[15]);
+ home_sensitivity = data[15];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[12] =%d,data[13] = %d\n", __func__,
+ data[12], data[13]);
+ home_sensitivity = ((0x00FF & data[12]) << 8) | data[13];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", home_sensitivity);
+}
+
+static ssize_t touchkey_back_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8) {
+ printk(KERN_DEBUG "called %s data[8] =%d,data[9] = %d\n",
+ __func__, data[8], data[9]);
+ back_sensitivity = ((0x00FF & data[8]) << 8) | data[9];
+ } else {
+ printk(KERN_DEBUG "called %s data[13] =%d\n", __func__,
+ data[13]);
+ back_sensitivity = data[13];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__,
+ data[14], data[15]);
+ back_sensitivity = ((0x00FF & data[14]) << 8) | data[15];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", back_sensitivity);
+}
+
+static ssize_t touchkey_search_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (store_module_version < 8) {
+ printk(KERN_DEBUG "called %s data[6] =%d,data[7] = %d\n",
+ __func__, data[6], data[7]);
+ search_sensitivity = ((0x00FF & data[6]) << 8) | data[7];
+ } else {
+ printk(KERN_DEBUG "called %s data[11] =%d\n", __func__,
+ data[11]);
+ search_sensitivity = data[11];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__,
+ data[16], data[17]);
+ search_sensitivity = ((0x00FF & data[16]) << 8) | data[17];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", search_sensitivity);
+}
+#else
+static ssize_t touchkey_menu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+#if defined(CONFIG_MACH_Q1_BD)
+ u8 data[14] = { 0, };
+ int ret;
+
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 14);
+
+ printk(KERN_DEBUG "called %s data[13] =%d\n", __func__, data[13]);
+ menu_sensitivity = data[13];
+#else
+ u8 data[10];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ menu_sensitivity = data[7];
+#endif
+ return sprintf(buf, "%d\n", menu_sensitivity);
+}
+
+static ssize_t touchkey_back_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+#if defined(CONFIG_MACH_Q1_BD)
+ u8 data[14] = { 0, };
+ int ret;
+
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 14);
+
+ printk(KERN_DEBUG "called %s data[11] =%d\n", __func__, data[11]);
+ back_sensitivity = data[11];
+#else
+ u8 data[10];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 10);
+ back_sensitivity = data[9];
+#endif
+ return sprintf(buf, "%d\n", back_sensitivity);
+}
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+static ssize_t autocalibration_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int data;
+
+ sscanf(buf, "%d\n", &data);
+
+ if (data == 1)
+ touchkey_autocalibration();
+
+ return size;
+}
+
+static ssize_t autocalibration_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[6];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+
+ ret = i2c_touchkey_read(KEYCODE_REG, data, 6);
+ if ((data[5] & 0x80))
+ return sprintf(buf, "Enabled\n");
+ else
+ return sprintf(buf, "Disabled\n");
+
+}
+#endif /* CONFIG_TARGET_LOCALE_NA */
+
+static ssize_t touch_sensitivity_control(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned char data = 0x40;
+ i2c_touchkey_write(&data, 1);
+ return size;
+}
+
+static ssize_t set_touchkey_firm_version_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "0x%x\n", TK_FIRMWARE_VER);
+}
+
+static ssize_t set_touchkey_update_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /* TO DO IT */
+ int count = 0;
+ int retry = 3;
+ touchkey_update_status = 1;
+
+#ifdef TEST_JIG_MODE
+ unsigned char get_touch = 0x40;
+#endif
+
+ while (retry--) {
+ if (ISSP_main() == 0) {
+ printk(KERN_ERR
+ "[TOUCHKEY]Touchkey_update succeeded\n");
+ touchkey_update_status = 0;
+ count = 1;
+ break;
+ }
+ printk(KERN_ERR "touchkey_update failed... retry...\n");
+ }
+ if (retry <= 0) {
+ /* disable ldo11 */
+ touchkey_ldo_on(0);
+ msleep(300);
+ count = 0;
+ printk(KERN_ERR "[TOUCHKEY]Touchkey_update fail\n");
+ touchkey_update_status = -1;
+ return count;
+ }
+
+ init_hw(); /* after update, re initalize. */
+
+#ifdef TEST_JIG_MODE
+ i2c_touchkey_write(&get_touch, 1);
+#endif
+
+ return count;
+
+}
+
+static ssize_t set_touchkey_firm_version_read_show(struct device *dev,
+ struct device_attribute
+ *attr, char *buf)
+{
+ char data[3] = { 0, };
+ int count;
+
+ init_hw();
+ /*if (get_touchkey_firmware(data) != 0) { */
+ i2c_touchkey_read(KEYCODE_REG, data, 3);
+ /*} */
+ count = sprintf(buf, "0x%x\n", data[1]);
+
+ printk(KERN_DEBUG "[TouchKey] touch_version_read 0x%x\n", data[1]);
+ printk(KERN_DEBUG "[TouchKey] module_version_read 0x%x\n", data[2]);
+ return count;
+}
+
+static ssize_t set_touchkey_firm_status_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int count = 0;
+
+ printk(KERN_DEBUG
+ "[TouchKey] touch_update_read: touchkey_update_status %d\n",
+ touchkey_update_status);
+
+ if (touchkey_update_status == 0)
+ count = sprintf(buf, "PASS\n");
+ else if (touchkey_update_status == 1)
+ count = sprintf(buf, "Downloading\n");
+ else if (touchkey_update_status == -1)
+ count = sprintf(buf, "Fail\n");
+
+ return count;
+}
+
+static DEVICE_ATTR(recommended_version, S_IRUGO | S_IWUSR | S_IWGRP,
+ touch_version_read, touch_version_write);
+static DEVICE_ATTR(updated_version, S_IRUGO | S_IWUSR | S_IWGRP,
+ touch_update_read, touch_update_write);
+static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ touch_led_control);
+static DEVICE_ATTR(enable_disable, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ touchkey_enable_disable);
+static DEVICE_ATTR(touchkey_menu, S_IRUGO | S_IWUSR | S_IWGRP,
+ touchkey_menu_show, NULL);
+static DEVICE_ATTR(touchkey_back, S_IRUGO | S_IWUSR | S_IWGRP,
+ touchkey_back_show, NULL);
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_TARGET_LOCALE_NAATT)
+static DEVICE_ATTR(touchkey_home, S_IRUGO, touchkey_home_show, NULL);
+static DEVICE_ATTR(touchkey_search, S_IRUGO, touchkey_search_show, NULL);
+#endif /* CONFIG_TARGET_LOCALE_NA */
+static DEVICE_ATTR(touch_sensitivity, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ touch_sensitivity_control);
+/*20110223N1 firmware sync*/
+static DEVICE_ATTR(touchkey_firm_update, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_update_show, NULL);/* firmware update */
+static DEVICE_ATTR(touchkey_firm_update_status, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_firm_status_show, NULL);/* firmware update status */
+static DEVICE_ATTR(touchkey_firm_version_phone, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_firm_version_show, NULL);/* PHONE */
+static DEVICE_ATTR(touchkey_firm_version_panel, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_firm_version_read_show, NULL);
+/*PART*/
+/*end N1 firmware sync*/
+static DEVICE_ATTR(touchkey_brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ brightness_control);
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+static DEVICE_ATTR(touchkey_autocal_start, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ set_touchkey_autocal_testmode);
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+static DEVICE_ATTR(touchkey_raw_data0, S_IRUGO, touchkey_raw_data0_show, NULL);
+static DEVICE_ATTR(touchkey_raw_data1, S_IRUGO, touchkey_raw_data1_show, NULL);
+static DEVICE_ATTR(touchkey_raw_data2, S_IRUGO, touchkey_raw_data2_show, NULL);
+static DEVICE_ATTR(touchkey_raw_data3, S_IRUGO, touchkey_raw_data3_show, NULL);
+static DEVICE_ATTR(touchkey_idac0, S_IRUGO, touchkey_idac0_show, NULL);
+static DEVICE_ATTR(touchkey_idac1, S_IRUGO, touchkey_idac1_show, NULL);
+static DEVICE_ATTR(touchkey_idac2, S_IRUGO, touchkey_idac2_show, NULL);
+static DEVICE_ATTR(touchkey_idac3, S_IRUGO, touchkey_idac3_show, NULL);
+static DEVICE_ATTR(touchkey_threshold, S_IRUGO, touchkey_threshold_show, NULL);
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+static DEVICE_ATTR(autocal_enable, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ autocalibration_enable);
+static DEVICE_ATTR(autocal_stat, S_IRUGO | S_IWUSR | S_IWGRP,
+ autocalibration_status, NULL);
+#endif /* CONFIG_TARGET_LOCALE_NA */
+static int __init touchkey_init(void)
+{
+ int ret = 0;
+
+#ifdef TEST_JIG_MODE
+ unsigned char get_touch = 0x40;
+#endif
+
+ sec_touchkey = device_create(sec_class, NULL, 0, NULL, "sec_touchkey");
+
+ if (IS_ERR(sec_touchkey))
+ printk(KERN_ERR "Failed to create device(sec_touchkey)!\n");
+
+ if (device_create_file(sec_touchkey, &dev_attr_touchkey_firm_update) <
+ 0) {
+ printk(KERN_ERR "Failed to create device file(%s)!\n",
+ dev_attr_touchkey_firm_update.attr.name);
+ }
+ if (device_create_file
+ (sec_touchkey, &dev_attr_touchkey_firm_update_status) < 0) {
+ printk(KERN_ERR "Failed to create device file(%s)!\n",
+ dev_attr_touchkey_firm_update_status.attr.name);
+ }
+ if (device_create_file
+ (sec_touchkey, &dev_attr_touchkey_firm_version_phone) < 0) {
+ printk(KERN_ERR "Failed to create device file(%s)!\n",
+ dev_attr_touchkey_firm_version_phone.attr.name);
+ }
+ if (device_create_file
+ (sec_touchkey, &dev_attr_touchkey_firm_version_panel) < 0) {
+ printk(KERN_ERR "Failed to create device file(%s)!\n",
+ dev_attr_touchkey_firm_version_panel.attr.name);
+ }
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_brightness) < 0) {
+ printk(KERN_ERR "Failed to create device file(%s)!\n",
+ dev_attr_touchkey_brightness.attr.name);
+ }
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_autocal_start) <
+ 0) {
+ printk(KERN_ERR "Failed to create device file(%s)!\n",
+ dev_attr_touchkey_brightness.attr.name);
+ }
+#endif
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_recommended_version) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_recommended_version.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_updated_version) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_updated_version.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_brightness) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_brightness.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_enable_disable) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_enable_disable.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_menu) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_menu.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_back) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_back.attr.name);
+ }
+#if defined(CONFIG_TARGET_LOCALE_NAATT) \
+|| defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_raw_data0) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_raw_data0.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_raw_data1) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_raw_data1.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_raw_data2) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_raw_data2.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_raw_data3) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_raw_data3.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_idac0) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_idac0.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_idac1) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_idac1.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_idac2) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_idac2.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_idac3) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_idac3.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touchkey_threshold) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_threshold.attr.name);
+ }
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_TARGET_LOCALE_NAATT)
+ if (device_create_file(sec_touchkey, &dev_attr_touchkey_home) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_home.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey, &dev_attr_touchkey_search) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touchkey_search.attr.name);
+ }
+#endif /* CONFIG_TARGET_LOCALE_NA */
+
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)
+ if (device_create_file(sec_touchkey, &dev_attr_autocal_enable) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_autocal_enable.attr.name);
+ }
+
+ if (device_create_file(sec_touchkey, &dev_attr_autocal_stat) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_autocal_stat.attr.name);
+ }
+#endif /* CONFIG_TARGET_LOCALE_NA */
+
+ if (device_create_file(sec_touchkey,
+ &dev_attr_touch_sensitivity) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_touch_sensitivity.attr.name);
+ }
+ touchkey_wq = create_singlethread_workqueue("sec_touchkey_wq");
+ if (!touchkey_wq)
+ return -ENOMEM;
+
+ INIT_WORK(&touchkey_work, touchkey_work_func);
+
+ init_hw();
+
+ ret = i2c_add_driver(&touchkey_i2c_driver);
+
+ if (ret) {
+ printk(KERN_ERR
+ "[TouchKey] registration failed, module not inserted.ret= %d\n",
+ ret);
+ }
+#ifdef TEST_JIG_MODE
+ i2c_touchkey_write(&get_touch, 1);
+#endif
+ return ret;
+
+}
+
+static void __exit touchkey_exit(void)
+{
+ printk(KERN_DEBUG "[TouchKey] %s\n", __func__);
+ i2c_del_driver(&touchkey_i2c_driver);
+
+#ifdef CONFIG_TOUCHKEY_BLN
+ misc_deregister(&bln_device);
+ wake_lock_destroy(&bln_wake_lock);
+ del_timer(&led_timer);
+ del_timer(&notification_timer);
+ del_timer(&breathing_timer);
+#endif
+
+ if (touchkey_wq)
+ destroy_workqueue(touchkey_wq);
+
+#ifndef CONFIG_MACH_Q1_BD
+ gpio_free(_3_TOUCH_SDA_28V);
+ gpio_free(_3_TOUCH_SCL_28V);
+ gpio_free(_3_GPIO_TOUCH_EN);
+#endif
+ gpio_free(_3_GPIO_TOUCH_INT);
+}
+
+late_initcall(touchkey_init);
+module_exit(touchkey_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("@@@");
+MODULE_DESCRIPTION("touch keypad");
diff --git a/drivers/input/keyboard/cypressbln/issp_defs.h b/drivers/input/keyboard/cypressbln/issp_defs.h
new file mode 100644
index 0000000..5878300
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_defs.h
@@ -0,0 +1,101 @@
+// filename: ISSP_Defs.h
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+--------------------------------------------------------------------------*/
+#ifndef INC_ISSP_DEFS
+#define INC_ISSP_DEFS
+
+#include "issp_directives.h"
+
+// Block-Verify Uses 64-Bytes of RAM
+// #define TARGET_DATABUFF_LEN 64
+#define TARGET_DATABUFF_LEN 128 // **** CY8C20x66 Device ****
+
+// The number of Flash blocks in each part is defined here. This is used in
+// main programming loop when programming and verifying the blocks.
+
+#ifdef CY8CTMx30x // **** CY8C20x66 Device ****
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 256
+#define SECURITY_BYTES_PER_BANK 64
+#endif
+
+#ifdef CY8C20x66 // **** CY8C20x66 Device ****
+#ifdef CY8C20246 // **** CY8C20x66 Device ****
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 128
+#define SECURITY_BYTES_PER_BANK 64
+#elif defined(CY8C20236)
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 64
+#define SECURITY_BYTES_PER_BANK 64
+#else
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 256
+#define SECURITY_BYTES_PER_BANK 64
+#endif
+#endif
+#ifdef CY8C21x23
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 64
+#define SECURITY_BYTES_PER_BANK 64
+#endif
+#ifdef CY8C21x34
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 128
+#define SECURITY_BYTES_PER_BANK 64
+#endif
+#ifdef CY8C24x23A
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 64
+#define SECURITY_BYTES_PER_BANK 64
+#endif
+#ifdef CY8C24x94
+#define NUM_BANKS 2
+#define BLOCKS_PER_BANK 128
+#define SECURITY_BYTES_PER_BANK 32
+#endif
+#ifdef CY8C27x43
+#define NUM_BANKS 1
+#define BLOCKS_PER_BANK 256
+#define SECURITY_BYTES_PER_BANK 64
+#endif
+#ifdef CY8C29x66
+#define NUM_BANKS 4
+#define BLOCKS_PER_BANK 128
+#define SECURITY_BYTES_PER_BANK 32
+#endif
+#endif //(INC_ISSP_DEFS)
+#endif //(PROJECT_REV_)
+//end of file ISSP_Defs.h
diff --git a/drivers/input/keyboard/cypressbln/issp_delays.h b/drivers/input/keyboard/cypressbln/issp_delays.h
new file mode 100644
index 0000000..e727310
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_delays.h
@@ -0,0 +1,87 @@
+// filename: ISSP_Delays.h
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+-----------------------------------------------------------------------------*/
+#ifndef INC_ISSP_DELAYS
+#define INC_ISSP_DELAYS
+
+// The Delay() routine, in ISSP_Driver_Routines.c, has a delay of n+3 usec,
+// where n is the value passed to the routine. This is true for the m8c micro-
+// processor in the PSoC when it is running at a CPU clock of 24MHz.
+//
+// PROCESSOR_SPECIFIC
+// If another processor is used, or if the m8c is running at a slower clock
+// speed, then the delay parameters will be different. This file makes changing
+// the delays simpiler when porting the program to other processors.
+
+// DELAY_M is the slope of the Delay = Mx + B equation
+#define DELAY_M 1
+// DELAY_B is the offset of the delay in Delay = Mx + B.
+#define DELAY_B 3
+
+///////////////////////////////////////////////////////////////////////////////
+// CAUTION:
+// For the above parameters the minimum delay value is 3 (this would result in
+// 0 being passed for a minimum delay. A value less than 3 would actually
+// create a negative number, causing a very long delay
+///////////////////////////////////////////////////////////////////////////////
+
+// TRANSITION_TIMEOUT is a loop counter for a 100msec timeout when waiting for
+// a high-to-low transition. This is used in the polling loop of
+// fDetectHiLoTransition(). Each pass through the loop takes approximately 15
+// usec. 100 msec is about 6740 loops. 13480
+#define TRANSITION_TIMEOUT 0x100000 //6740
+
+// XRES_DELAY is the time duration for which XRES is asserted. This defines
+// a 63 usec delay.
+// The minimum Xres time (from the device datasheet) is 10 usec.
+//mhsong #define XRES_CLK_DELAY ((63 - DELAY_B) / DELAY_M)
+#define XRES_CLK_DELAY 63
+
+// POWER_CYCLE_DELAY is the time required when power is cycled to the target
+// device to create a power reset after programming has been completed. The
+// actual time of this delay will vary from system to system depending on the
+// bypass capacitor size. A delay of 150 usec is used here.
+//mhsong #define POWER_CYCLE_DELAY ((150 - DELAY_B) / DELAY_M)
+#define POWER_CYCLE_DELAY 150
+
+// DELAY_100us delays 100 usec. This is used in fXRESInitializeTargetForISSP to
+// time the wait for Vdd to become stable after a power up. A loop runs 10 of
+// these for a total delay of 1 msec.
+//mhsong #define DELAY100us ((100 - DELAY_B) / DELAY_M)
+#define DELAY100us 100
+
+#endif //(INC_ISSP_DELAYS)
+#endif //(PROJECT_REV_)
+//end of file ISSP_Delays.h
diff --git a/drivers/input/keyboard/cypressbln/issp_directives.h b/drivers/input/keyboard/cypressbln/issp_directives.h
new file mode 100644
index 0000000..b6cdddc
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_directives.h
@@ -0,0 +1,474 @@
+// filename: ISSP_Directives.h
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+----------------------------------------------------------------------------*/
+
+// --------------------- Compiler Directives ----------------------------------
+#ifndef INC_ISSP_DIRECTIVES
+#define INC_ISSP_DIRECTIVES
+
+// This directive will enable a Genral Purpose test-point on P1.7
+// It can be toggled as needed to measure timing, execution, etc...
+// A "Test Point" sets a GPIO pin of the host processor high or low. This GPIO
+// pin can be observed with an oscilloscope to verify the timing of key
+// programming steps. TPs have been added in main() that set Port 0, pin 1
+// high during bulk erase, during each block write and during security write.
+// The timing of these programming steps should be verified as correct as part
+// of the validation process of the final program.
+
+//JBA
+//#define USE_TP
+
+// ****************************************************************************
+// ************* USER ATTENTION REQUIRED: TARGET SUPPLY VOLTAGE ***************
+// ****************************************************************************
+// This directive causes the proper Initialization vector #3 to be sent
+// to the Target, based on what the Target Vdd programming voltage will
+// be. Either 5V (if #define enabled) or 3.3V (if #define disabled).
+
+//JBA
+//#define TARGET_VOLTAGE_IS_5V
+
+// ****************************************************************************
+// **************** USER ATTENTION REQUIRED: PROGRAMMING MODE *****************
+// ****************************************************************************
+// This directive selects whether code that uses reset programming mode or code
+// that uses power cycle programming is use. Reset programming mode uses the
+// external reset pin (XRES) to enter programming mode. Power cycle programming
+// mode uses the power-on reset to enter programming mode.
+// Applying signals to various pins on the target device must be done in a
+// deliberate order when using power cycle mode. Otherwise, high signals to GPIO
+// pins on the target will power the PSoC through the protection diodes.
+
+//JBA
+// choose the RESET MODE or POWER MODE
+// #define RESET_MODE
+
+// ****************************************************************************
+// ****************** USER ATTENTION REQUIRED: TARGET PSOC ********************
+// ****************************************************************************
+// The directives below enable support for various PSoC devices. The root part
+// number to be programmed should be un-commented so that its value becomes
+// defined. All other devices should be commented out.
+// Select one device to be supported below:
+
+/*************** CY8CTMA30x, CY8CTMG30x, CY8CTST30x series by KIMC, 2009.08.11 ***********************************/
+//#define CY8CTST300_36 // CY8CTST300_36LQXI // 2009.08.11, not tested.
+//#define CY8CTST300_48 // CY8CTST300_48LTXI // 2009.08.11, not tested.
+//#define CY8CTST300_49 // CY8CTST300_49FNXI // 2009.08.11, not tested.
+//#define CY8CTMA300_36 // CY8CTMA300_36LQXI // 2009.08.11, Test OK.
+//#define CY8CTMA300_48 // CY8CTMA300_48LTXI // 2009.08.11, not tested.
+//#define CY8CTMA300_49 // CY8CTMA300_49FNXI // 2009.08.11, not tested.
+//#define CY8CTMG300_36 // CY8CTMG300_36LQXI // 2009.08.11, not tested.
+//#define CY8CTMG300_48 // CY8CTMG300_48LTXI // 2009.08.11, not tested.
+//#define CY8CTMG300_49 // CY8CTMG300_49FNXI // 2009.08.11, not tested.
+//#define CY8CTMG300B_36 // CY8CTMG300B_36LQXI // 2009.08.11, not tested.
+//#define CY8CTMA300B_36 // CY8CTMA300B_36LQXI // 2009.08.11, not tested.
+//#define CY8CTST300B_36 // CY8CTST300B_36LQXI // 2009.08.11, not tested.
+//#define CY8CTMA301_36 // CY8CTMA301_36LQXI // 2009.08.11, not tested.
+//#define CY8CTMA301_48 // CY8CTMA301_48LTXI // 2009.08.11, not tested.
+//#define CY8CTMA301D_36 // CY8CTMA301D_36LQXI // 2009.08.11, not tested.
+//#define CY8CTMA301D_48 // CY8CTMA301D_48LTXI // 2009.08.11, not tested.
+//#define CY8CTMA300D_36 // CY8CTMA300D_36LQXI // 2009.08.11, not tested.
+//#define CY8CTMA300D_48 // CY8CTMA300D_48LTXI // 2009.08.11, not tested.
+//#define CY8CTMA300D_49 // CY8CTMA300D_49FNXIT // 2009.08.11, not tested.
+/****************************************************************************************************/
+
+/*************** CY8CTMG/TST series modified by KJHW, 2009.08.14 *********************************************/
+//#define CY8CTMG110
+//#define CY8CTST200_24PIN
+//#define CY8CTST200_32PIN
+//#define CY8CTMG200_24PIN
+//#define CY8CTMG200_32PIN
+/***************************************************************************************************/
+
+#define CY8C20236
+// **** CY8C20x66 devices ****
+//#define CY8C20246 /// 2009.03.26. kimc
+//#define CY8C20266
+//#define CY8C20366
+//#define CY8C20466
+//#define CY8C20566
+//#define CY8C20666
+//#define CY8C20066
+//#define CY8C200661
+
+// **** CY8C21x23 devices ****
+//#define CY8C21123
+//#define CY8C21223
+//#define CY8C21323
+//#define CY8C21002
+
+// **** CY8C21x34 devices ****
+//#define CY8C21234
+//#define CY8C21334
+//#define CY8C21434
+//#define CY8C21534
+//#define CY8C21634
+//#define CY8C21001
+
+// **** CY8C24x23A devices ****
+//#define CY8C24123A
+//#define CY8C24223A
+//#define CY8C24423A
+//#define CY8C24000A
+
+// **** CY8C24x94 devices ****
+//#define CY8C24794
+//#define CY8C24894
+//#define CY8C24994
+//#define CY8C24094
+
+// **** CY8C27x34 devices ****
+//#define CY8C27143
+//#define CY8C27243
+//#define CY8C27443
+//#define CY8C27543
+//#define CY8C27643
+//#define CY8C27002
+
+// **** CY8C29x66 devices ****
+//#define CY8C29466
+//#define CY8C29566
+//#define CY8C29666
+//#define CY8C29866
+//#define CY8C29002
+
+//-----------------------------------------------------------------------------
+// This section sets the Family that has been selected. These are used to
+// simplify other conditional compilation blocks.
+//-----------------------------------------------------------------------------
+
+/*************** CY8CTMA30x, CY8CTMG30x, CY8CTST30x series by KIMC, 2009.08.11 ***********************************/
+#ifdef CY8CTST300_36 // CY8CTST300_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTST300_48 // CY8CTST300_48LTXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTST300_49 // CY8CTST300_49FNXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300_36 // CY8CTMA300_36LQXI // 2009.08.11, test OK
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300_48 // CY8CTMA300_48LTXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300_49 // CY8CTMA300_49FNXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMG300_36 // CY8CTMG300_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMG300_48 // CY8CTMG300_48LTXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMG300_49 // CY8CTMG300_49FNXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMG300B_36 // CY8CTMG300B_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300B_36 // CY8CTMA300B_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTST300B_36 // CY8CTST300B_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA301_36 // CY8CTMA301_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA301_48 // CY8CTMA301_48LTXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA301D_36 // CY8CTMA301D_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA301D_48 // CY8CTMA301D_48LTXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300D_36 // CY8CTMA300D_36LQXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300D_48 // CY8CTMA300D_48LTXI // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+#ifdef CY8CTMA300D_49 // CY8CTMA300D_49FNXIT // 2009.08.11, not tested.
+#define CY8CTMx30x
+#define CY8C20x66
+#endif
+/**************************************************/
+
+/*************** CY8CTMG/TST series modified by KJHW, 2009.08.14 *********************************************/
+
+#ifdef CY8CTMG110
+#define CY8C21x34
+#endif
+#ifdef CY8CTST200_24PIN
+#define CY8C20x66
+#endif
+#ifdef CY8CTST200_32PIN
+#define CY8C20x66
+#endif
+#ifdef CY8CTMG200_24PIN
+#define CY8C20x66
+#endif
+#ifdef CY8CTMG200_32PIN
+#define CY8C20x66
+#endif
+
+/***************************************************************************************************/
+#ifdef CY8C20236
+#define CY8C20x66
+#endif
+#ifdef CY8C20246 /// 2009.03.26. kimc
+#define CY8C20x66
+#endif
+#ifdef CY8C20266
+#define CY8C20x66
+#endif
+#ifdef CY8C20366
+#define CY8C20x66
+#endif
+#ifdef CY8C20466
+#define CY8C20x66
+#endif
+#ifdef CY8C20566
+#define CY8C20x66
+#endif
+#ifdef CY8C20666
+#define CY8C20x66
+#endif
+#ifdef CY8C20066
+#define CY8C20x66
+#endif
+#ifdef CY8C200661
+#define CY8C20x66
+#endif
+
+#ifdef CY8C21123
+#define CY8C21x23
+#endif
+#ifdef CY8C21223
+#define CY8C21x23
+#endif
+#ifdef CY8C21323
+#define CY8C21x23
+#endif
+#ifdef CY8C21002
+#define CY8C21x23
+#endif
+#ifdef CY8C21234
+#define CY8C21x34
+#endif
+#ifdef CY8C21334
+#define CY8C21x34
+#endif
+#ifdef CY8C21434
+#define CY8C21x34
+#endif
+#ifdef CY8C21534
+#define CY8C21x34
+#endif
+#ifdef CY8C21634
+#define CY8C21x34
+#endif
+#ifdef CY8C21001
+#define CY8C21x34
+#endif
+#ifdef CY8C24123A
+#define CY8C24x23A
+#endif
+#ifdef CY8C24223A
+#define CY8C24x23A
+#endif
+#ifdef CY8C24423A
+#define CY8C24x23A
+#endif
+#ifdef CY8C24000A
+#define CY8C24x23A
+#endif
+#ifdef CY8C24794
+#define CY8C24x94
+#endif
+#ifdef CY8C24894
+#define CY8C24x94
+#endif
+#ifdef CY8C24994
+#define CY8C24x94
+#endif
+#ifdef CY8C24094
+#define CY8C24x94
+#endif
+#ifdef CY8C27143
+#define CY8C27x43
+#endif
+#ifdef CY8C27243
+#define CY8C27x43
+#endif
+#ifdef CY8C27443
+#define CY8C27x43
+#endif
+#ifdef CY8C27543
+#define CY8C27x43
+#endif
+#ifdef CY8C27643
+#define CY8C27x43
+#endif
+#ifdef CY8C27002
+#define CY8C27x43
+#endif
+#ifdef CY8C29466
+#define CY8C29x66
+#endif
+#ifdef CY8C29566
+#define CY8C29x66
+#endif
+#ifdef CY8C29666
+#define CY8C29x66
+#endif
+#ifdef CY8C29866
+#define CY8C29x66
+#endif
+#ifdef CY8C29002
+#define CY8C29x66
+#endif
+
+//-----------------------------------------------------------------------------
+// The directives below are used for Krypton.
+// See the Krypton programming spec 001-15870 rev *A for more details. (The
+// spec uses "mnemonics" instead of "directives"
+//-----------------------------------------------------------------------------
+#ifdef CY8C20x66
+#define TSYNC
+
+#define ID_SETUP_1 //PTJ: ID_SETUP_1 is similar to init1_v
+#define ID_SETUP_2 //PTJ: ID_SETUP_2 is similar to init2_v
+#define SET_BLOCK_NUM
+#define CHECKSUM_SETUP //PTJ: CHECKSUM_SETUP_20x66 is the same as CHECKSUM-SETUP in 001-15870
+#define READ_CHECKSUM
+#define PROGRAM_AND_VERIFY //PTJ: PROGRAM_BLOCK_20x66 is the same as PROGRAM-AND-VERIFY in 001-15870
+#define ERASE
+#define SECURE
+#define READ_SECURITY
+#define READ_WRITE_SETUP
+#define WRITE_BYTE
+#define VERIFY_SETUP
+#define READ_STATUS
+#define READ_BYTE
+ //READ_ID_WORD //PTJ: 3rd Party Progrmmer will have to write code to handle this directive, we do it out own way in this code, see read_id_v
+#endif
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// The directives below are used to define various sets of vectors that differ
+// for more than one set of PSoC parts.
+//-----------------------------------------------------------------------------
+// **** Select a Checksum Setup Vector ****
+#ifdef CY8C21x23
+#define CHECKSUM_SETUP_21_27
+#endif
+#ifdef CY8C21x34
+#define CHECKSUM_SETUP_21_27
+#endif
+#ifdef CY8C24x23A
+#define CHECKSUM_SETUP_24_24A
+#endif
+#ifdef CY8C24x94
+#define CHECKSUM_SETUP_24_29
+#endif
+#ifdef CY8C27x43
+#define CHECKSUM_SETUP_21_27
+#endif
+#ifdef CY8C29x66
+#define CHECKSUM_SETUP_24_29
+#endif
+
+// **** Select a Program Block Vector ****
+
+#ifdef CY8C21x23
+#define PROGRAM_BLOCK_21_24_29
+#endif
+#ifdef CY8C21x34
+#define PROGRAM_BLOCK_21_24_29
+#endif
+#ifdef CY8C24x23A
+#define PROGRAM_BLOCK_21_24_29
+#endif
+#ifdef CY8C24x94
+#define PROGRAM_BLOCK_21_24_29
+#endif
+#ifdef CY8C27x43
+#define PROGRAM_BLOCK_27
+#endif
+#ifdef CY8C29x66
+#define PROGRAM_BLOCK_21_24_29
+#endif
+
+//-----------------------------------------------------------------------------
+// The directives below are used to control switching banks if the device is
+// has multiple banks of Flash.
+//-----------------------------------------------------------------------------
+// **** Select a Checksum Setup Vector ****
+#ifdef CY8C24x94
+#define MULTI_BANK
+#endif
+#ifdef CY8C29x66
+#define MULTI_BANK
+#endif
+
+// ----------------------------------------------------------------------------
+#endif //(INC_ISSP_DIRECTIVES)
+#endif //(PROJECT_REV_)
+//end of file ISSP_Directives.h
diff --git a/drivers/input/keyboard/cypressbln/issp_driver_routines.c b/drivers/input/keyboard/cypressbln/issp_driver_routines.c
new file mode 100644
index 0000000..a3b4fcf
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_driver_routines.c
@@ -0,0 +1,498 @@
+// filename: ISSP_Driver_Routines.c
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+--------------------------------------------------------------------------*/
+
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <asm/gpio.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/earlysuspend.h>
+#include <asm/io.h>
+#include <linux/hrtimer.h>
+
+//mhsong #include <m8c.h> // part specific constants and macros
+//mhsong #include "PSoCAPI.h" // PSoC API definitions for all User Modules
+#include "issp_defs.h"
+#include "issp_errors.h"
+#include "issp_directives.h"
+#include "u1-cypress-gpio.h"
+
+extern unsigned char bTargetDataPtr;
+extern unsigned char abTargetDataOUT[TARGET_DATABUFF_LEN];
+
+/* enable ldo11 */
+extern int touchkey_ldo_on(bool on);
+
+// ****************************** PORT BIT MASKS ******************************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+#define SDATA_PIN 0x80 // P1.0 -> P1.4
+#define SCLK_PIN 0x40 // P1.1 -> P1.3
+#define XRES_PIN 0x40 // P2.0 -> P1.6
+#define TARGET_VDD 0x08 // P2.1
+
+unsigned int nBlockCount = 1; // test, KIMC
+
+extern unsigned char firmware_data[];
+
+// ((((((((((((((((((((((( DEMO ISSP SUBROUTINE SECTION )))))))))))))))))))))))
+// ((((( Demo Routines can be deleted in final ISSP project if not used )))))
+// ((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))
+
+// ============================================================================
+// InitTargetTestData()
+// !!!!!!!!!!!!!!!!!!FOR TEST!!!!!!!!!!!!!!!!!!!!!!!!!!
+// PROCESSOR_SPECIFIC
+// Loads a 64-Byte array to use as test data to program target. Ultimately,
+// this data should be fed to the Host by some other means, ie: I2C, RS232,
+// etc. Data should be derived from hex file.
+// Global variables affected:
+// bTargetDataPtr
+// abTargetDataOUT
+// ============================================================================
+void InitTargetTestData(unsigned char bBlockNum, unsigned char bBankNum)
+{
+ // create unique data for each block
+ for (bTargetDataPtr = 0; bTargetDataPtr < TARGET_DATABUFF_LEN;
+ bTargetDataPtr++) {
+ abTargetDataOUT[bTargetDataPtr] = nBlockCount;
+ // abTargetDataOUT[bTargetDataPtr] = bTargetDataPtr + bBlockNum + bBankNum;
+ }
+ nBlockCount++;
+}
+
+// ============================================================================
+// LoadArrayWithSecurityData()
+// !!!!!!!!!!!!!!!!!!FOR TEST!!!!!!!!!!!!!!!!!!!!!!!!!!
+// PROCESSOR_SPECIFIC
+// Most likely this data will be fed to the Host by some other means, ie: I2C,
+// RS232, etc., or will be fixed in the host. The security data should come
+// from the hex file.
+// bStart - the starting byte in the array for loading data
+// bLength - the number of byte to write into the array
+// bType - the security data to write over the range defined by bStart and
+// bLength
+// ============================================================================
+void LoadArrayWithSecurityData(unsigned char bStart, unsigned char bLength,
+ unsigned char bType)
+{
+ // Now, write the desired security-bytes for the range specified
+ for (bTargetDataPtr = bStart; bTargetDataPtr < bLength;
+ bTargetDataPtr++) {
+ abTargetDataOUT[bTargetDataPtr] = bType;
+ }
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// Delay()
+// This delay uses a simple "nop" loop. With the CPU running at 24MHz, each
+// pass of the loop is about 1 usec plus an overhead of about 3 usec.
+// total delay = (n + 3) * 1 usec
+// To adjust delays and to adapt delays when porting this application, see the
+// ISSP_Delays.h file.
+// ****************************************************************************
+void Delay(unsigned char n) // by KIMC
+{
+ udelay(n);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// LoadProgramData()
+// The final application should load program data from HEX file generated by
+// PSoC Designer into a 64 byte host ram buffer.
+// 1. Read data from next line in hex file into ram buffer. One record
+// (line) is 64 bytes of data.
+// 2. Check host ram buffer + record data (Address, # of bytes) against hex
+// record checksum at end of record line
+// 3. If error reread data from file or abort
+// 4. Exit this Function and Program block or verify the block.
+// This demo program will, instead, load predetermined data into each block.
+// The demo does it this way because there is no comm link to get data.
+// ****************************************************************************
+void LoadProgramData(unsigned char bBlockNum, unsigned char bBankNum)
+{
+ // >>> The following call is for demo use only. <<<
+ // Function InitTargetTestData fills buffer for demo
+ // InitTargetTestData(bBlockNum, bBankNum);
+ // create unique data for each block
+ int dataNum = 0;
+ for (dataNum = 0; dataNum < TARGET_DATABUFF_LEN; dataNum++) {
+ abTargetDataOUT[dataNum] =
+ firmware_data[bBlockNum * TARGET_DATABUFF_LEN + dataNum];
+ // abTargetDataOUT[bTargetDataPtr] = bTargetDataPtr + bBlockNum + bBankNum;
+ }
+
+ // Note:
+ // Error checking should be added for the final version as noted above.
+ // For demo use this function just returns VOID.
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// fLoadSecurityData()
+// Load security data from hex file into 64 byte host ram buffer. In a fully
+// functional program (not a demo) this routine should do the following:
+// 1. Read data from security record in hex file into ram buffer.
+// 2. Check host ram buffer + record data (Address, # of bytes) against hex
+// record checksum at end of record line
+// 3. If error reread security data from file or abort
+// 4. Exit this Function and Program block
+// In this demo routine, all of the security data is set to unprotected (0x00)
+// and it returns.
+// This function always returns PASS. The flag return is reserving
+// functionality for non-demo versions.
+// ****************************************************************************
+signed char fLoadSecurityData(unsigned char bBankNum)
+{
+ // >>> The following call is for demo use only. <<<
+ // Function LoadArrayWithSecurityData fills buffer for demo
+// LoadArrayWithSecurityData(0,SECURITY_BYTES_PER_BANK, 0x00);
+ LoadArrayWithSecurityData(0, SECURITY_BYTES_PER_BANK, 0xFF); //PTJ: 0x1B (00 01 10 11) is more interesting security data than 0x00 for testing purposes
+
+ // Note:
+ // Error checking should be added for the final version as noted above.
+ // For demo use this function just returns PASS.
+ return (PASS);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// fSDATACheck()
+// Check SDATA pin for high or low logic level and return value to calling
+// routine.
+// Returns:
+// 0 if the pin was low.
+// 1 if the pin was high.
+// ****************************************************************************
+unsigned char fSDATACheck(void)
+{
+ gpio_direction_input(_3_TOUCH_SDA_28V);
+ if (gpio_get_value(_3_TOUCH_SDA_28V))
+ return (1);
+ else
+ return (0);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SCLKHigh()
+// Set the SCLK pin High
+// ****************************************************************************
+void SCLKHigh(void)
+{
+ gpio_direction_output(_3_TOUCH_SCL_28V, 1);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SCLKLow()
+// Make Clock pin Low
+// ****************************************************************************
+void SCLKLow(void)
+{
+ gpio_direction_output(_3_TOUCH_SCL_28V, 0);
+}
+
+#ifndef RESET_MODE // Only needed for power cycle mode
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetSCLKHiZ()
+// Set SCLK pin to HighZ drive mode.
+// ****************************************************************************
+void SetSCLKHiZ(void)
+{
+ gpio_direction_input(_3_TOUCH_SCL_28V);
+}
+#endif
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetSCLKStrong()
+// Set SCLK to an output (Strong drive mode)
+// ****************************************************************************
+void SetSCLKStrong(void)
+{
+ //gpio_direction_output(_3_TOUCH_SCL_28V, 1);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetSDATAHigh()
+// Make SDATA pin High
+// ****************************************************************************
+void SetSDATAHigh(void)
+{
+ gpio_direction_output(_3_TOUCH_SDA_28V, 1);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetSDATALow()
+// Make SDATA pin Low
+// ****************************************************************************
+void SetSDATALow(void)
+{
+ gpio_direction_output(_3_TOUCH_SDA_28V, 0);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetSDATAHiZ()
+// Set SDATA pin to an input (HighZ drive mode).
+// ****************************************************************************
+void SetSDATAHiZ(void)
+{
+ gpio_direction_input(_3_TOUCH_SDA_28V); // ENA-> DIS
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetSDATAStrong()
+// Set SDATA for transmission (Strong drive mode) -- as opposed to being set to
+// High Z for receiving data.
+// ****************************************************************************
+void SetSDATAStrong(void)
+{
+ //gpio_direction_output(_3_TOUCH_SDA_28V, 1);
+}
+
+#ifdef RESET_MODE
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetXRESStrong()
+// Set external reset (XRES) to an output (Strong drive mode).
+// ****************************************************************************
+void SetXRESStrong(void)
+{
+ //gpio_tlmm_config(EXT_TSP_RST);
+ //gpio_out(EXT_TSP_RST, GPIO_HIGH_VALUE);
+ //clk_busy_wait(1000);
+ //clk_busy_wait(1000);
+ //clk_busy_wait(1000);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// AssertXRES()
+// Set XRES pin High
+// ****************************************************************************
+void AssertXRES(void)
+{
+#if 0
+ gpio_tlmm_config(EXT_TSP_RST);
+ gpio_out(EXT_TSP_RST, GPIO_HIGH_VALUE);
+ clk_busy_wait(1000);
+ clk_busy_wait(1000);
+ clk_busy_wait(1000);
+#endif
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// DeassertXRES()
+// Set XRES pin low.
+// ****************************************************************************
+void DeassertXRES(void)
+{
+ //gpio_out(EXT_TSP_RST, GPIO_LOW_VALUE);
+}
+#else
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// SetTargetVDDStrong()
+// Set VDD pin (PWR) to an output (Strong drive mode).
+// ****************************************************************************
+void SetTargetVDDStrong(void)
+{
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// ApplyTargetVDD()
+// Provide power to the target PSoC's Vdd pin through a GPIO.
+// ****************************************************************************
+void ApplyTargetVDD(void)
+{
+ int ret;
+
+ gpio_direction_input(_3_TOUCH_SDA_28V);
+ gpio_direction_input(_3_TOUCH_SCL_28V);
+ gpio_direction_output(_3_GPIO_TOUCH_EN, 1);
+
+ /* enable ldo */
+ ret = touchkey_ldo_on(1);
+ if (ret == 0)
+ printk(KERN_ERR "[Touchkey]regulator get fail!!!\n");
+
+ mdelay(1);
+}
+
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// RemoveTargetVDD()
+// Remove power from the target PSoC's Vdd pin.
+// ****************************************************************************
+void RemoveTargetVDD(void)
+{
+ gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
+
+ touchkey_ldo_on(0);
+}
+#endif
+
+#ifdef USE_TP
+// ********************* LOW-LEVEL ISSP SUBROUTINE SECTION ********************
+// ****************************************************************************
+// **** PROCESSOR SPECIFIC ****
+// ****************************************************************************
+// **** USER ATTENTION REQUIRED ****
+// ****************************************************************************
+// A "Test Point" sets a GPIO pin of the host processor high or low.
+// This GPIO pin can be observed with an oscilloscope to verify the timing of
+// key programming steps. TPs have been added in main() that set Port 0, pin 1
+// high during bulk erase, during each block write and during security write.
+// The timing of these programming steps should be verified as correct as part
+// of the validation process of the final program.
+// ****************************************************************************
+void InitTP(void)
+{
+}
+
+void SetTPHigh(void)
+{
+}
+
+void SetTPLow(void)
+{
+}
+
+void ToggleTP(void)
+{
+}
+#endif
+#endif //(PROJECT_REV_)
+//end of file ISSP_Drive_Routines.c
diff --git a/drivers/input/keyboard/cypressbln/issp_errors.h b/drivers/input/keyboard/cypressbln/issp_errors.h
new file mode 100644
index 0000000..e6f0673
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_errors.h
@@ -0,0 +1,65 @@
+// filename: ISSP_Errors.h
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+--------------------------------------------------------------------------*/
+#ifndef INC_ISSP_ERRORS
+#define INC_ISSP_ERRORS
+
+// The following are defines for error messages from the ISSP program.
+#define PASS 0
+// PASS is used to indicate that a function completed successfully.
+#define ERROR -1
+// ERROR is a generic failure used within lower level functions before the
+// error is reported. This should not be seen as an error that is reported
+// from main.
+#define INIT_ERROR 1
+// INIT_ERROR means a step in chip initialization failed.
+#define SiID_ERROR 2
+// SiID_ERROR means that the Silicon ID check failed. This happens if the
+// target part does not match the device type that the ISSP program is
+// configured for.
+#define ERASE_ERROR 3
+// ERASE_ERROR means that the bulk erase step failed.
+#define BLOCK_ERROR 4
+// BLOCK_ERROR means that a step in programming a Flash block or the verify
+// of the block failed.
+#define VERIFY_ERROR 5
+// VERIFY_ERROR means that the checksum verification failed.
+#define SECURITY_ERROR 6
+// SECURITY_ERROR means that the write of the security information failed.
+#define STATUS_ERROR 7
+
+#endif //(INC_ISSP_ERRORS)
+#endif //(PROJECT_REV_)
+//end of file ISSP_Errors.h
diff --git a/drivers/input/keyboard/cypressbln/issp_extern.h b/drivers/input/keyboard/cypressbln/issp_extern.h
new file mode 100644
index 0000000..fad9122
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_extern.h
@@ -0,0 +1,99 @@
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+*/
+
+#ifndef INC_ISSP_EXTERN
+#define INC_ISSP_EXTERN
+
+#include "issp_directives.h"
+
+extern signed char fXRESInitializeTargetForISSP(void);
+extern signed char fPowerCycleInitializeTargetForISSP(void);
+extern signed char fEraseTarget(void);
+extern unsigned int iLoadTarget(void);
+extern void ReStartTarget(void);
+extern signed char fVerifySiliconID(void);
+extern signed char fAccTargetBankChecksum(unsigned int *);
+extern void SetBankNumber(unsigned char);
+extern signed char fProgramTargetBlock(unsigned char, unsigned char);
+extern signed char fVerifyTargetBlock(unsigned char, unsigned char);
+extern signed char fVerifySetup(unsigned char, unsigned char);
+extern signed char fReadByteLoop(void); /*PTJ: read bytes after VERIFY-SETUP*/
+extern signed char fSecureTargetFlash(void);
+
+extern signed char fReadStatus(void); /*PTJ: READ-STATUS*/
+extern signed char fReadCalRegisters(void);
+extern signed char fReadWriteSetup(void); /*PTJ: READ-WRITE-SETUP*/
+extern signed char fReadSecurity(void); /*PTJ: READ-SECURITY*/
+
+extern signed char fSyncDisable(void); /*PTJ: SYNC-DISABLE rev 307*/
+extern signed char fSyncEnable(void); /*PTJ: SYNC-ENABLE rev 307*/
+
+extern void InitTargetTestData(void);
+extern void LoadArrayWithSecurityData(unsigned char, unsigned char,
+ unsigned char);
+
+extern void LoadProgramData(unsigned char, unsigned char);
+extern signed char fLoadSecurityData(unsigned char);
+extern void Delay(unsigned char);
+extern unsigned char fSDATACheck(void);
+extern void SCLKHigh(void);
+extern void SCLKLow(void);
+#ifndef RESET_MODE /*only needed when power cycle mode*/
+extern void SetSCLKHiZ(void);
+#endif
+extern void SetSCLKStrong(void);
+extern void SetSDATAHigh(void);
+extern void SetSDATALow(void);
+extern void SetSDATAHiZ(void);
+extern void SetSDATAStrong(void);
+extern void AssertXRES(void);
+extern void DeassertXRES(void);
+extern void SetXRESStrong(void);
+extern void ApplyTargetVDD(void);
+extern void RemoveTargetVDD(void);
+extern void SetTargetVDDStrong(void);
+
+extern unsigned char fIsError;
+
+#ifdef USE_TP
+extern void InitTP(void);
+extern void SetTPHigh(void);
+extern void SetTPLow(void);
+extern void ToggleTP(void);
+#endif
+
+extern int ISSP_main(void);
+
+#endif /*(INC_ISSP_EXTERN)*/
+#endif /*(PROJECT_REV_)*/
diff --git a/drivers/input/keyboard/cypressbln/issp_main.c b/drivers/input/keyboard/cypressbln/issp_main.c
new file mode 100644
index 0000000..a799e3b
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_main.c
@@ -0,0 +1,931 @@
+// filename: main.c
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress��?product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+---------------------------------------------------------------------------*/
+
+/* ############################################################################
+ ################### CRITICAL PROJECT CONSTRAINTS ########################
+ ############################################################################
+
+ ISSP programming can only occur within a temperature range of 5C to 50C.
+ - This project is written without temperature compensation and using
+ programming pulse-widths that match those used by programmers such as the
+ Mini-Prog and the ISSP Programmer.
+ This means that the die temperature of the PSoC device cannot be outside
+ of the above temperature range.
+ If a wider temperature range is required, contact your Cypress Semi-
+ conductor FAE or sales person for assistance.
+
+ The project can be configured to program devices at 5V or at 3.3V.
+ - Initialization of the device is different for different voltages. The
+ initialization is hardcoded and can only be set for one voltage range.
+ The supported voltages ranges are 3.3V (3.0V to 3.6V) and 5V (4.75V to
+ 5.25V). See the device datasheet for more details. If varying voltage
+ ranges must be supported, contact your Cypress Semiconductor FAE or sales
+ person for assistance.
+ - ISSP programming for the 2.7V range (2.7V to 3.0V) is not supported.
+
+ This program does not support programming all PSoC Devices
+ - It does not support obsoleted PSoC devices. A list of devices that are
+ not supported is shown here:
+ CY8C22x13 - not supported
+ CY8C24x23 - not supported (CY8C24x23A is supported)
+ CY8C25x43 - not supported
+ CY8C26x43 - not supported
+ - It does not suport devices that have not been released for sale at the
+ time this version was created. If you need to ISSP program a newly released
+ device, please contact Cypress Semiconductor Applications, your FAE or
+ sales person for assistance.
+ The CY8C20x23 devices are not supported at the time of this release.
+
+ ############################################################################
+ ##########################################################################*/
+
+/* This program uses information found in Cypress Semiconductor application
+// notes "Programming - In-System Serial Programming Protocol", AN2026. The
+// version of this application note that applies to the specific PSoC that is
+// being In-System Serial Programmed should be read and and understood when
+// using this program. (http://www.cypress.com)
+
+// This project is included with releases of PSoC Programmer software. It is
+// important to confirm that the latest revision of this software is used when
+// it is used. The revision of this copy can be found in the Project History
+// table below.
+*/
+
+/*/////////////////////////////////////////////////////////////////////////////
+// PROJECT HISTORY
+// date revision author description
+// -------- -------- ------ -----------------------------------------------
+// 7/23/08 3.04 ptj 1. CPU clock speed set to to 12MHz (default) after
+// TSYNC is disabled. Previously, it was being set
+// to 3MHz on accident. This affects the following
+// mnemonics:
+// ID_SETUP_1,
+// VERIFY_SETUP,
+// ERASE,
+// SECURE,
+// CHECKSUM_SETUP,
+// PROGRAM_AND_VERIFY,
+// ID_SETUP_2,
+// SYNC_DISABLE
+//
+// 6/06/08 3.03 ptj 1. The Verify_Setup section can tell when flash
+// is fully protected. bTargetStatus[0] shows a
+// 01h when flash is "W" Full Protection
+// 7/23/08 2. READ-ID-WORD updated to read Revision ID from
+// Accumulator A and X, registers T,F0h and T,F3h
+//
+// 5/30/08 3.02 ptj 1. All vectors work.
+// 2. Main function will execute the
+// following programming sequence:
+// . id setup 1
+// . id setup 2
+// . erase
+// . program and verify
+// . verify (although not necessary)
+// . secure flash
+// . read security
+// . checksum
+//
+// 05/28/08 3.01 ptj TEST CODE - NOT COMPLETE
+// 1. The sequence surrounding PROGRAM-AND-VERIFY was
+// improved and works according to spec.
+// 2. The sequence surroudning VERIFY-SETUP was devel-
+// oped and improved.
+// 3. TSYNC Enable is used to in a limited way
+// 4. Working Vectors: ID-SETUP-1, ID-SETUP-2, ERASE,
+// PROGRAM-AND-VERIFY, SECURE, VERIFY-SETUP,
+// CHECKSUM-SETUP
+// 5. Un-tested Vectors: READ-SECURITY
+//
+// 05/23/08 3.00 ptj TEST CODE - NOT COMPLETE
+// 1. This code is a test platform for the development
+// of the Krypton (cy8c20x66) Programming Sequence.
+// See 001-15870 rev *A. This code works on "rev B"
+// silicon.
+// 2. Host is Hydra 29000, Target is Krypton "rev B"
+// 3. Added Krypton device support
+// 4. TYSNC Enable/Disable is not used.
+// 5. Working Vectors: ID-SETUP-1, ID-SETUP-2, ERASE,
+// PROGRAM-AND-VERIFY, SECURE
+// 6. Non-working Vectors: CHECKSUM-SETUP
+// 7. Un-tested Vectors: READ-SECURITY, VERIFY-SETUP
+// 8. Other minor (non-SROM) vectors not listed.
+//
+// 09/23/07 2.11 dkn 1. Added searchable comments for the HSSP app note.
+// 2. Added new device vectors.
+// 3. Verified write and erase pulsewidths.
+// 4. Modified some functions for easier porting to
+// other processors.
+//
+// 09/23/06 2.10 mwl 1. Added #define SECURITY_BYTES_PER_BANK to
+// file issp_defs.h. Modified function
+// fSecureTargetFlashMain() in issp_routines.c
+// to use new #define. Modified function
+// fLoadSecurityData() in issp_driver_routines.c
+// to accept a bank number. Modified the secure
+// data loop in main.c to program multiple banks.
+//
+// 2. Created function fAccTargetBankChecksum to
+// read and add the target bank checksum to the
+// referenced accumulator. This allows the
+// checksum loop in main.c to function at the
+// same level of abstraction as the other
+// programming steps. Accordingly, modified the
+// checksum loop in main.c. Deleted previous
+// function fVerifyTargetChecksum().
+//
+// 09/08/06 2.00 mwl 1. Array variable abTargetDataOUT was not
+// getting intialized anywhere and compiled as a
+// one-byte array. Modified issp_driver_routines.c
+// line 44 to initialize with TARGET_DATABUFF_LEN.
+//
+// 2. Function void LoadProgramData(unsigned char
+// bBlockNum) in issp_driver_routines.c had only
+// one parameter bBlockNum but was being called
+// from function main() with two parameters,
+// LoadProgramData(bBankCounter, (unsigned char)
+// iBlockCounter). Modified function
+// LoadProgramData() to accept both parameters,
+// and in turn modified InitTargetTestData() to
+// accept and use both as well.
+//
+// 3. Corrected byte set_bank_number[1]
+// inissp_vectors.h. Was 0xF2, correct value is
+// 0xE2.
+//
+// 4. Corrected the logic to send the SET_BANK_NUM
+// vectors per the AN2026B flow chart.The previous
+// code version was sending once per block, but
+// should have been once per bank. Removed the
+// conditionally-compiled bank setting code blocks
+// from the top of fProgramTargetBlock() and
+// fVerifyTargetBlock() int issp_routines.c and
+// created a conditionally-compiled subroutine in
+// that same file called SetBankNumber(). Two
+// conditionally-compiled calls to SetBankNumber()
+// were added to main.c().
+//
+// 5. Corrected CY8C29x66 NUM_BANKS and
+// BLOCKS_PER_BANK definitions in ISSP_Defs.h.
+// Was 2 and 256 respectively, correct values are
+// 4 and 128.
+//
+// 6. Modified function fVerifyTargetChecksum()
+// in issp_routines.c to read and accumulate multiple
+// banks of checksums as required for targets
+// CY8C24x94 and CY8C29x66. Would have kept same
+// level of abstraction as other multi-bank functions
+// in main.c, but this implementation impacted the
+// code the least.
+//
+// 7. Corrected byte checksum_v[26] of
+// CHECKSUM_SETUP_24_29 in issp_vectors.h. Was 0x02,
+// correct value is 0x04.
+//
+// 06/30/06 1.10 jvy Added support for 24x94 and 29x66 devices.
+// 06/09/06 1.00 jvy Changed CPU Clk to 12MHz (from 24MHz) so the
+// host can run from 3.3V.
+// Simplified init of security data.
+// 06/05/06 0.06 jvy Version #ifdef added to each file to make sure
+// all of the file are from the same revision.
+// Added flags to prevent multiple includes of H
+// files.
+// Changed pre-determined data for demo to be
+// unique for each block.
+// Changed block verify to check all blocks after
+// block programming has been completed.
+// Added SetSCLKHiZ to explicitly set the Clk to
+// HighZ before power cycle acquire.
+// Fixed wrong vectors in setting Security.
+// Fixed wrong vectors in Block program.
+// Added support for pods
+// 06/05/06 0.05 jvy Comments from code review. First copy checked
+// into perforce. Code has been updated enough to
+// compile, by implementing some comments and
+// fixing others.
+// 06/04/06 0.04 jvy made code more efficient in bReceiveByte(), and
+// SendVector() by re-arranging so that local vars
+// could be eliminated.
+// added defines for the delays used in the code.
+// 06/02/06 0.03 jvy added number of Flash block adjustment to
+// programming. added power cycle programming
+// mode support. This is the version initially
+// sent out for peer review.
+// 06/02/06 0.02 jvy added framework for multiple chip support from
+// one source code set using compiler directives.
+// added timeout to high-low trasition detection.
+// added multiple error message to allow tracking
+// of failures.
+// 05/30/06 0.01 jvy initial version,
+// created from DBD's issp_27xxx_v3 program.
+/////////////////////////////////////////////////////////////////////////////*/
+
+/* (((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))
+ PSoC In-System Serial Programming (ISSP) Template
+ This PSoC Project is designed to be used as a template for designs that
+ require PSoC ISSP Functions.
+
+ This project is based on the AN2026 series of Application Notes. That app
+ note should be referenced before any modifications to this project are made.
+
+ The subroutines and files were created in such a way as to allow easy cut &
+ paste as needed. There are no customer-specific functions in this project.
+ This demo of the code utilizes a PSoC as the Host.
+
+ Some of the subroutines could be merged, or otherwise reduced, but they have
+ been written as independently as possible so that the specific steps involved
+ within each function can easily be seen. By merging things, some code-space
+ savings could be realized.
+
+ As is, and with all features enabled, the project consumes approximately 3500
+ bytes of code space, and 19-Bytes of RAM (not including stack usage). The
+ Block-Verify requires a 64-Byte buffer for read-back verification. This same
+ buffer could be used to hold the (actual) incoming program data.
+
+ Please refer to the compiler-directives file "directives.h" to see the various
+ features.
+
+ The pin used in this project are assigned as shown below. The HOST pins are
+ arbitrary and any 3 pins could be used (the masks used to control the pins
+ must be changed). The TARGET pins cannot be changed, these are fixed function
+ pins on the PSoC.
+ The PWR pin is used to provide power to the target device if power cycle
+ programming mode is used. The compiler directive RESET_MODE in ISSP_directives.h
+ is used to select the programming mode. This pin could control the enable on
+ a voltage regulator, or could control the gate of a FET that is used to turn
+ the power to the PSoC on.
+ The TP pin is a Test Point pin that can be used signal from the host processor
+ that the program has completed certain tasks. Predefined test points are
+ included that can be used to observe the timing for bulk erasing, block
+ programming and security programming.
+
+ SIGNAL HOST TARGET
+ ---------------------
+ SDATA P1.7 P1.0
+ SCLK P1.6 P1.1
+ XRES P2.0 XRES
+ PWR P2.3 Vdd
+ TP P0.7 n/a
+
+ For test & demonstration, this project generates the program data internally.
+ It does not take-in the data from an external source such as I2C, UART, SPI,
+ etc. However, the program was written in such a way to be portable into such
+ designs. The spirit of this project was to keep it stripped to the minimum
+ functions required to do the ISSP functions only, thereby making a portable
+ framework for integration with other projects.
+
+ The high-level functions have been written in C in order to be portable to
+ other processors. The low-level functions that are processor dependent, such
+ as toggling pins and implementing specific delays, are all found in the file
+ ISSP_Drive_Routines.c. These functions must be converted to equivalent
+ functions for the HOST processor. Care must be taken to meet the timing
+ requirements when converting to a new processor. ISSP timing information can
+ be found in Application Note AN2026. All of the sections of this program
+ that need to be modified for the host processor have "PROCESSOR_SPECIFIC" in
+ the comments. By performing a "Find in files" using "PROCESSOR_SPECIFIC" these
+ sections can easily be identified.
+
+ The variables in this project use Hungarian notation. Hungarian prepends a
+ lower case letter to each variable that identifies the variable type. The
+ prefixes used in this program are defined below:
+ b = byte length variable, signed char and unsigned char
+ i = 2-byte length variable, signed int and unsigned int
+ f = byte length variable used as a flag (TRUE = 0, FALSE != 0)
+ ab = an array of byte length variables
+
+ After this program has been ported to the desired host processor the timing
+ of the signals must be confirmed. The maximum SCLK frequency must be checked
+ as well as the timing of the bulk erase, block write and security write
+ pulses.
+
+ The maximum SCLK frequency for the target device can be found in the device
+ datasheet under AC Programming Specifications with a Symbol of "Fsclk".
+ An oscilloscope should be used to make sure that no half-cycles (the high
+ time or the low time) are shorter than the half-period of the maximum
+ freqency. In other words, if the maximum SCLK frequency is 8MHz, there can be
+ no high or low pulses shorter than 1/(2*8MHz), or 62.5 nsec.
+
+ The test point (TP) functions, enabled by the define USE_TP, provide an output
+ from the host processor that brackets the timing of the internal bulk erase,
+ block write and security write programming pulses. An oscilloscope, along with
+ break points in the PSoC ICE Debugger should be used to verify the timing of
+ the programming. The Application Note, "Host-Sourced Serial Programming"
+ explains how to do these measurements and should be consulted for the expected
+ timing of the erase and program pulses.
+
+ ############################################################################
+ ############################################################################
+
+(((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))) */
+
+/*----------------------------------------------------------------------------
+// C main line
+//----------------------------------------------------------------------------
+*/
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <asm/gpio.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+//#include <m8c.h> // part specific constants and macros
+//#include "PSoCAPI.h" // PSoC API definitions for all User Modules
+// ------ Declarations Associated with ISSP Files & Routines -------
+// Add these to your project as needed.
+#include "issp_extern.h"
+#include "issp_directives.h"
+#include "issp_defs.h"
+#include "issp_errors.h"
+#include "u1-cypress-gpio.h"
+/* ------------------------------------------------------------------------- */
+
+/* enable ldo11 */
+extern int touchkey_ldo_on(bool on);
+
+unsigned char bBankCounter;
+unsigned int iBlockCounter;
+unsigned int iChecksumData;
+unsigned int iChecksumTarget;
+
+//update version "eclair/vendor/samsung/apps/Lcdtest/src/com/sec/android/app/lcdtest/touch_firmware.java"
+#if defined(CONFIG_MACH_Q1_BD)
+#include "touchkey_fw_Q1.h"
+#elif defined(CONFIG_ARIES_NTT)
+#include "touchkey_fw_NTT.h"
+#elif defined(CONFIG_TARGET_LOCALE_NA)
+#include "touchkey_fw_NA.h"
+#elif defined(CONFIG_TARGET_LOCALE_NAATT)
+#include "touchkey_fw_NAATT.h"
+#else
+#include "touchkey_fw_U1.h"
+#endif
+
+//////I2C
+
+#define EXT_I2C_SCL_HIGH \
+ do { \
+ int delay_count; \
+ gpio_direction_output(_3_TOUCH_SCL_28V, 1); \
+ gpio_direction_input(_3_TOUCH_SCL_28V); \
+ delay_count = 100000; \
+ while(delay_count--) \
+ { \
+ if(gpio_get_value(_3_TOUCH_SCL_28V)) \
+ break; \
+ udelay(1); \
+ } \
+ } while(0);
+#define EXT_I2C_SCL_LOW gpio_direction_output(_3_TOUCH_SCL_28V, 0);
+#define EXT_I2C_SDA_HIGH gpio_direction_output(_3_TOUCH_SDA_28V, 1);
+#define EXT_I2C_SDA_LOW gpio_direction_output(_3_TOUCH_SDA_28V, 0);
+#define TRUE 1
+#define FALSE 0
+
+static void EXT_I2C_LOW(u32 delay)
+{
+ EXT_I2C_SDA_LOW;
+ //udelay(delay);
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ EXT_I2C_SCL_LOW;
+ //udelay(delay);
+}
+
+static void EXT_I2C_HIGH(u32 delay)
+{
+ EXT_I2C_SDA_HIGH;
+ //udelay(delay);
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ EXT_I2C_SCL_LOW;
+ //udelay(delay);
+}
+
+static void EXT_I2C_START(u32 delay)
+{
+ EXT_I2C_SDA_HIGH;
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ EXT_I2C_SDA_LOW;
+ //udelay(delay);
+ EXT_I2C_SCL_LOW;
+ //udelay(delay);
+
+}
+
+static void EXT_I2C_END(u32 delay)
+{
+ EXT_I2C_SDA_LOW;
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ EXT_I2C_SDA_HIGH;
+}
+
+static int EXT_I2C_ACK(u32 delay)
+{
+ u32 ack;
+
+ /* SDA -> Input */
+ gpio_direction_input(_3_TOUCH_SDA_28V);
+
+ udelay(delay);
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ ack = gpio_get_value(_3_TOUCH_SDA_28V);
+ EXT_I2C_SCL_LOW;
+ //udelay(delay);
+ if (ack)
+ printk("EXT_I2C No ACK\n");
+
+ return ack;
+}
+
+static void EXT_I2C_NACK(u32 delay)
+{
+ EXT_I2C_SDA_HIGH;
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ EXT_I2C_SCL_LOW;
+ //udelay(delay);
+}
+
+static void EXT_I2C_SEND_ACK(u32 delay)
+{
+ gpio_direction_output(_3_TOUCH_SDA_28V, 0);
+ EXT_I2C_SCL_HIGH;
+ //udelay(delay);
+ EXT_I2C_SCL_LOW;
+ //udelay(delay);
+
+}
+
+#define EXT_I2C_DELAY 1
+//============================================================
+//
+// Porting section 6. I2C function calling
+//
+// Connect baseband i2c function
+//
+// Warning 1. !!!! Burst mode is not supported. Transfer 1 byte Only.
+//
+// Every i2c packet has to
+// " START > Slave address > One byte > STOP " at download mode.
+//
+// Warning 2. !!!! Check return value of i2c function.
+//
+// _i2c_read_(), _i2c_write_() must return
+// TRUE (1) if success,
+// FALSE(0) if failed.
+//
+// If baseband i2c function returns different value, convert return value.
+// ex> baseband_return = baseband_i2c_read( slave_addr, pData, cLength );
+// return ( baseband_return == BASEBAND_RETURN_VALUE_SUCCESS );
+//
+//
+// Warning 3. !!!! Check Slave address
+//
+// Slave address is '0x7F' at download mode. ( Diffrent with Normal touch working mode )
+// '0x7F' is original address,
+// If shift << 1 bit, It becomes '0xFE'
+//
+//============================================================
+
+static int
+_i2c_read_(unsigned char SlaveAddr, unsigned char *pData, unsigned char cLength)
+{
+ unsigned int i;
+ int delay_count = 10000;
+
+ EXT_I2C_START(EXT_I2C_DELAY);
+
+ SlaveAddr = SlaveAddr << 1;
+ for (i = 8; i > 1; i--) {
+ if ((SlaveAddr >> (i - 1)) & 0x1)
+ EXT_I2C_HIGH(EXT_I2C_DELAY);
+ else
+ EXT_I2C_LOW(EXT_I2C_DELAY);
+ }
+
+ EXT_I2C_HIGH(EXT_I2C_DELAY); //readwrite
+
+ if (EXT_I2C_ACK(EXT_I2C_DELAY)) {
+ EXT_I2C_END(EXT_I2C_DELAY);
+ return FALSE;
+ }
+
+ udelay(10);
+ gpio_direction_input(_3_TOUCH_SCL_28V);
+ delay_count = 100000;
+ while (delay_count--) {
+ if (gpio_get_value(_3_TOUCH_SCL_28V))
+ break;
+ udelay(1);
+ }
+ while (cLength--) {
+ *pData = 0;
+ for (i = 8; i > 0; i--) {
+ //udelay(EXT_I2C_DELAY);
+ EXT_I2C_SCL_HIGH;
+ //udelay(EXT_I2C_DELAY);
+ *pData |=
+ (!!(gpio_get_value(_3_TOUCH_SDA_28V)) << (i - 1));
+ //udelay(EXT_I2C_DELAY);
+ EXT_I2C_SCL_LOW;
+ //udelay(EXT_I2C_DELAY);
+ }
+
+ if (cLength) {
+ EXT_I2C_SEND_ACK(EXT_I2C_DELAY);
+ udelay(10);
+ pData++;
+ gpio_direction_input(_3_TOUCH_SDA_28V);
+ gpio_direction_input(_3_TOUCH_SCL_28V);
+ delay_count = 100000;
+ while (delay_count--) {
+ if (gpio_get_value(_3_TOUCH_SCL_28V))
+ break;
+ udelay(1);
+ }
+ } else
+ EXT_I2C_NACK(EXT_I2C_DELAY);
+ }
+
+ EXT_I2C_END(EXT_I2C_DELAY);
+
+ return (TRUE);
+
+}
+
+#define TOUCHKEY_ADDRESS 0x20
+
+int get_touchkey_firmware(char *version)
+{
+ int retry = 3;
+ while (retry--) {
+ if (_i2c_read_(TOUCHKEY_ADDRESS, version, 3))
+ return 0;
+
+ }
+ return (-1);
+ //printk("%s F/W version: 0x%x, Module version:0x%x\n",__FUNCTION__, version[1],version[2]);
+}
+
+/* ========================================================================= */
+// ErrorTrap()
+// Return is not valid from main for PSOC, so this ErrorTrap routine is used.
+// For some systems returning an error code will work best. For those, the
+// calls to ErrorTrap() should be replaced with a return(bErrorNumber). For
+// other systems another method of reporting an error could be added to this
+// function -- such as reporting over a communcations port.
+/* ========================================================================= */
+void ErrorTrap(unsigned char bErrorNumber)
+{
+#ifndef RESET_MODE
+ // Set all pins to highZ to avoid back powering the PSoC through the GPIO
+ // protection diodes.
+ SetSCLKHiZ();
+ SetSDATAHiZ();
+ // If Power Cycle programming, turn off the target
+ RemoveTargetVDD();
+#endif
+ printk("\r\nErrorTrap: errorNumber: %d\n", bErrorNumber);
+
+ // TODO: write retry code or some processing.
+ return;
+// while (1);
+}
+
+/* ========================================================================= */
+/* MAIN LOOP */
+/* Based on the diagram in the AN2026 */
+/* ========================================================================= */
+
+int ISSP_main(void)
+{
+ unsigned long flags;
+
+ // -- This example section of commands show the high-level calls to -------
+ // -- perform Target Initialization, SilcionID Test, Bulk-Erase, Target ---
+ // -- RAM Load, FLASH-Block Program, and Target Checksum Verification. ----
+
+ // >>>> ISSP Programming Starts Here <<<<
+ // Acquire the device through reset or power cycle
+ s3c_gpio_setpull(_3_TOUCH_SCL_28V, S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(_3_TOUCH_SDA_28V, S3C_GPIO_PULL_NONE);
+ gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
+ /* disable ldo11 */
+ touchkey_ldo_on(0);
+ msleep(1);
+#ifdef RESET_MODE
+ gpio_tlmm_config(LED_26V_EN);
+ gpio_tlmm_config(EXT_TSP_SCL);
+ gpio_tlmm_config(EXT_TSP_SDA);
+ gpio_tlmm_config(LED_RST);
+
+ gpio_out(LED_RST, GPIO_LOW_VALUE);
+ clk_busy_wait(10);
+
+ gpio_out(LED_26V_EN, GPIO_HIGH_VALUE);
+ for (temp = 0; temp < 16; temp++) {
+ clk_busy_wait(1000);
+ dog_kick();
+ }
+
+ // Initialize the Host & Target for ISSP operations
+ printk("fXRESInitializeTargetForISSP Start\n");
+
+ //INTLOCK();
+ local_save_flags(flags);
+ local_irq_disable();
+ if (fIsError = fXRESInitializeTargetForISSP()) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ //INTFREE();
+#else
+ //INTLOCK();
+ local_irq_save(flags);
+ // Initialize the Host & Target for ISSP operations
+ if ((fIsError = fPowerCycleInitializeTargetForISSP())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ //INTFREE();
+#endif /* RESET_MODE */
+
+#if 0 // issp_test_2010 block
+ printk("fXRESInitializeTargetForISSP END\n");
+
+ // Run the SiliconID Verification, and proceed according to result.
+ printk("fVerifySiliconID START\n");
+#endif
+
+ //INTLOCK();
+ fVerifySiliconID(); // .. error // issp_test_20100709 unblock
+#if 0
+ if (fIsError = fVerifySiliconID()) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#endif
+
+ //INTFREE();
+ local_irq_restore(flags);
+ //printk("fVerifySiliconID END\n"); // issp_test_2010 block
+
+ // Bulk-Erase the Device.
+ //printk("fEraseTarget START\n"); // issp_test_2010 block
+ //INTLOCK();
+ local_irq_save(flags);
+ if ((fIsError = fEraseTarget())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ //INTFREE();
+ local_irq_restore(flags);
+ //printk("fEraseTarget END\n"); // issp_test_2010 block
+
+ //==============================================================//
+ // Program Flash blocks with predetermined data. In the final application
+ // this data should come from the HEX output of PSoC Designer.
+ //printk("Program Flash Blocks Start\n");
+
+ iChecksumData = 0; // Calculte the device checksum as you go
+ for (bBankCounter = 0; bBankCounter < NUM_BANKS; bBankCounter++) //PTJ: NUM_BANKS should be 1 for Krypton
+ {
+ local_irq_save(flags);
+ for (iBlockCounter = 0; iBlockCounter < BLOCKS_PER_BANK;
+ iBlockCounter++) {
+ //printk("Program Loop : iBlockCounter %d \n",iBlockCounter);
+ //INTLOCK();
+ // local_irq_save(flags);
+
+ //PTJ: READ-WRITE-SETUP used here to select SRAM Bank 1, and TSYNC Enable
+#ifdef CY8C20x66
+ if ((fIsError = fSyncEnable())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ if ((fIsError = fReadWriteSetup())) { // send write command - swanhan
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#endif
+ //firmware read.
+ //LoadProgramData(bBankCounter, (unsigned char)iBlockCounter); //PTJ: this loads the Hydra with test data, not the krypton
+ LoadProgramData((unsigned char)iBlockCounter, bBankCounter); //PTJ: this loads the Hydra with test data, not the krypton
+ iChecksumData += iLoadTarget(); //PTJ: this loads the Krypton
+
+ //dog_kick();
+ if ((fIsError =
+ fProgramTargetBlock(bBankCounter,
+ (unsigned char)iBlockCounter))) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#ifdef CY8C20x66 //PTJ: READ-STATUS after PROGRAM-AND-VERIFY
+ if ((fIsError = fReadStatus())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#endif
+ //INTFREE();
+ //local_irq_restore(flags);
+ }
+ local_irq_restore(flags);
+ }
+
+ //printk("\r\n Program Flash Blocks End\n");
+
+#if 0 // verify check pass or check.
+ printk("\r\n Verify Start", 0, 0, 0);
+ //=======================================================//
+ //PTJ: Doing Verify
+ //PTJ: this code isnt needed in the program flow because we use PROGRAM-AND-VERIFY (ProgramAndVerify SROM Func)
+ //PTJ: which has Verify built into it.
+ // Verify included for completeness in case host desires to do a stand-alone verify at a later date.
+ for (bBankCounter = 0; bBankCounter < NUM_BANKS; bBankCounter++) {
+ for (iBlockCounter = 0; iBlockCounter < BLOCKS_PER_BANK;
+ iBlockCounter++) {
+ printk("Verify Loop: iBlockCounter %d", iBlockCounter,
+ 0, 0);
+ INTLOCK();
+ LoadProgramData(bBankCounter,
+ (unsigned char)iBlockCounter);
+
+ //PTJ: READ-WRITE-SETUP used here to select SRAM Bank 1, and TSYNC Enable
+#ifdef CY8C20x66
+ if (fIsError = fReadWriteSetup()) {
+ ErrorTrap(fIsError);
+ }
+#endif
+
+ dog_kick();
+
+ if (fIsError =
+ fVerifySetup(bBankCounter,
+ (unsigned char)iBlockCounter)) {
+ ErrorTrap(fIsError);
+ }
+#ifdef CY8C20x66 //PTJ: READ-STATUS after VERIFY-SETUP
+ if (fIsError = fSyncEnable()) { //PTJ: 307, added for tsync enable testing
+ ErrorTrap(fIsError);
+ }
+ if (fIsError = fReadStatus()) {
+ ErrorTrap(fIsError);
+ }
+ //PTJ: READ-WRITE-SETUP used here to select SRAM Bank 1, and TSYNC Enable
+ if (fIsError = fReadWriteSetup()) {
+ ErrorTrap(fIsError);
+ }
+ if (fIsError = fSyncDisable()) { //PTJ: 307, added for tsync enable testing
+ ErrorTrap(fIsError);
+ }
+#endif
+ INTFREE();
+ }
+ }
+ printk("Verify End", 0, 0, 0);
+#endif /* #if 1 */
+#if 1 /* security start */
+ //=======================================================//
+ // Program security data into target PSoC. In the final application this
+ // data should come from the HEX output of PSoC Designer.
+ //printk("Program security data START\n");
+ //INTLOCK();
+ local_irq_save(flags);
+ for (bBankCounter = 0; bBankCounter < NUM_BANKS; bBankCounter++) {
+ //PTJ: READ-WRITE-SETUP used here to select SRAM Bank 1
+#ifdef CY8C20x66
+ if ((fIsError = fSyncEnable())) { //PTJ: 307, added for tsync enable testing.
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ if ((fIsError = fReadWriteSetup())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#endif
+ // Load one bank of security data from hex file into buffer
+ if ((fIsError = fLoadSecurityData(bBankCounter))) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ // Secure one bank of the target flash
+ if ((fIsError = fSecureTargetFlash())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ }
+ //INTFREE();
+ local_irq_restore(flags);
+
+ //printk("Program security data END\n");
+
+ //==============================================================//
+ //PTJ: Do READ-SECURITY after SECURE
+
+ //Load one bank of security data from hex file into buffer
+ //loads abTargetDataOUT[] with security data that was used in secure bit stream
+ //INTLOCK();
+ local_irq_save(flags);
+ if ((fIsError = fLoadSecurityData(bBankCounter))) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#ifdef CY8C20x66
+ if ((fIsError = fReadSecurity())) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+#endif
+ //INTFREE();
+ local_irq_restore(flags);
+ //printk("Load security data END\n");
+#endif /* security end */
+
+ //=======================================================//
+ //PTJ: Doing Checksum after READ-SECURITY
+ //INTLOCK();
+ local_irq_save(flags);
+ iChecksumTarget = 0;
+ for (bBankCounter = 0; bBankCounter < NUM_BANKS; bBankCounter++) {
+ if ((fIsError = fAccTargetBankChecksum(&iChecksumTarget))) {
+ ErrorTrap(fIsError);
+ return fIsError;
+ }
+ }
+
+ //INTFREE();
+ local_irq_restore(flags);
+
+ //printk("Checksum : iChecksumTarget (0x%X)\n", (unsigned char)iChecksumTarget);
+ //printk ("Checksum : iChecksumData (0x%X)\n", (unsigned char)iChecksumData);
+
+ if ((unsigned short)(iChecksumTarget & 0xffff) !=
+ (unsigned short)(iChecksumData & 0xffff)) {
+ ErrorTrap(VERIFY_ERROR);
+ return fIsError;
+ }
+ //printk("Doing Checksum END\n");
+
+ // *** SUCCESS ***
+ // At this point, the Target has been successfully Initialize, ID-Checked,
+ // Bulk-Erased, Block-Loaded, Block-Programmed, Block-Verified, and Device-
+ // Checksum Verified.
+
+ // You may want to restart Your Target PSoC Here.
+ ReStartTarget(); //Touch IC Reset.
+
+ //printk("ReStartTarget\n");
+
+ return 0;
+}
+
+// end of main()
+
+#endif //(PROJECT_REV_) end of file main.c
diff --git a/drivers/input/keyboard/cypressbln/issp_revision.h b/drivers/input/keyboard/cypressbln/issp_revision.h
new file mode 100644
index 0000000..ca1990c
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_revision.h
@@ -0,0 +1,65 @@
+/* filename: ISSP_Revision.h
+ Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+--------------------------------------------------------------------------*/
+#ifndef INC_ISSP_REVISION
+#define INC_ISSP_REVISION
+// The PROJECT_REV_xyz is used to make sure that the files in the project
+// are all from the same revision of the program. Each file starts with an
+// ifdef that will prevent the file from being compiled if it is not the
+// correct revision
+// Set the revision to 3.04
+#define PROJECT_REV_304
+
+#endif //(INC_ISSP_REVISION)
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <asm/gpio.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/earlysuspend.h>
+#include <asm/io.h>
+//end of file ISSP_Revision.h
diff --git a/drivers/input/keyboard/cypressbln/issp_routines.c b/drivers/input/keyboard/cypressbln/issp_routines.c
new file mode 100644
index 0000000..0186e2b
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_routines.c
@@ -0,0 +1,1044 @@
+// filename: ISSP_Routines.c
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypressï¿?product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+--------------------------------------------------------------------------*/
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <asm/gpio.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/earlysuspend.h>
+#include <asm/io.h>
+#include <linux/hrtimer.h>
+//mhsong #include <m8c.h> // part specific constants and macros
+//mhsong #include "PSoCAPI.h" // PSoC API definitions for all User Modules
+#include "issp_defs.h"
+#include "issp_vectors.h"
+#include "issp_extern.h"
+#include "issp_errors.h"
+#include "issp_directives.h"
+#include "issp_delays.h"
+
+unsigned char bTargetDataIN;
+unsigned char abTargetDataOUT[TARGET_DATABUFF_LEN];
+
+unsigned char bTargetAddress;
+unsigned char bTargetDataPtr = 0;
+unsigned char bTargetID[10];
+unsigned char bTargetStatus[10]; //PTJ: created to support READ-STATUS in fReadStatus()
+
+unsigned char fIsError;
+
+/* ((((((((((((((((((((( LOW-LEVEL ISSP SUBROUTINE SECTION ))))))))))))))))))))
+ (( The subroutines in this section use functions from the C file ))
+ (( ISSP_Drive_Routines.c. The functions in that file interface to the ))
+ (( processor specific hardware. So, these functions should work as is, if ))
+ (( the routines in ISSP_Drive_Routines.c are correctly converted. ))
+ (((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))*/
+
+// ============================================================================
+// RunClock()
+// Description:
+// Run Clock without sending/receiving bits. Use this when transitioning from
+// write to read and read to write "num_cycles" is number of SCLK cycles, not
+// number of counter cycles.
+//
+// SCLK cannot run faster than the specified maximum frequency of 8MHz. Some
+// processors may need to have delays added after setting SCLK low and setting
+// SCLK high in order to not exceed this specification. The maximum frequency
+// of SCLK should be measured as part of validation of the final program
+//
+// ============================================================================
+void RunClock(unsigned int iNumCycles)
+{
+ int i;
+
+ for (i = 0; i < iNumCycles; i++) {
+ SCLKLow();
+ SCLKHigh();
+ }
+ // function exits with CLK high.
+}
+
+// ============================================================================
+// bReceiveBit()
+// Clocks the SCLK pin (high-low-high) and reads the status of the SDATA pin
+// after the rising edge.
+//
+// SCLK cannot run faster than the specified maximum frequency of 8MHz. Some
+// processors may need to have delays added after setting SCLK low and setting
+// SCLK high in order to not exceed this specification. The maximum frequency
+// of SCLK should be measured as part of validation of the final program
+//
+// Returns:
+// 0 if SDATA was low
+// 1 if SDATA was high
+// ============================================================================
+unsigned char bReceiveBit(void)
+{
+ SCLKLow();
+ SCLKHigh();
+ if (fSDATACheck()) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+// ============================================================================
+// bReceiveByte()
+// Calls ReceiveBit 8 times to receive one byte.
+// Returns:
+// The 8-bit values recieved.
+// ============================================================================
+unsigned char bReceiveByte(void)
+{
+ unsigned char b;
+ unsigned char bCurrByte = 0x00;
+
+ for (b = 0; b < 8; b++) {
+ bCurrByte = (bCurrByte << 1) + bReceiveBit();
+ }
+ return (bCurrByte);
+}
+
+// ============================================================================
+// SendByte()
+// This routine sends up to one byte of a vector, one bit at a time.
+// bCurrByte the byte that contains the bits to be sent.
+// bSize the number of bits to be sent. Valid values are 1 to 8.
+//
+// SCLK cannot run faster than the specified maximum frequency of 8MHz. Some
+// processors may need to have delays added after setting SCLK low and setting
+// SCLK high in order to not exceed this specification. The maximum frequency
+// of SCLK should be measured as part of validation of the final program
+//
+// There is no returned value.
+// ============================================================================
+void SendByte(unsigned char bCurrByte, unsigned char bSize)
+{
+ unsigned char b = 0;
+
+ for (b = 0; b < bSize; b++) {
+ if (bCurrByte & 0x80) {
+ // Send a '1'
+ SetSDATAHigh();
+ SCLKHigh();
+ SCLKLow();
+ } else {
+ // Send a '0'
+ SetSDATALow();
+ SCLKHigh();
+ SCLKLow();
+ }
+ bCurrByte = bCurrByte << 1;
+ }
+}
+
+// ============================================================================
+// SendVector()
+// This routine sends the vector specifed. All vectors constant strings found
+// in ISSP_Vectors.h. The data line is returned to HiZ after the vector is
+// sent.
+// bVect a pointer to the vector to be sent.
+// nNumBits the number of bits to be sent.
+// bCurrByte scratch var to keep the byte to be sent.
+//
+// There is no returned value.
+// ============================================================================
+void SendVector(const unsigned char *bVect, unsigned int iNumBits)
+{
+ SetSDATAStrong();
+ while (iNumBits > 0) {
+ if (iNumBits >= 8) {
+ SendByte(*(bVect), 8);
+ iNumBits -= 8;
+ bVect++;
+ } else {
+ SendByte(*(bVect), iNumBits);
+ iNumBits = 0;
+ }
+ }
+ SetSDATALow(); // issp_test_20100709 add
+ SetSDATAHiZ();
+}
+
+// ============================================================================
+// fDetectHiLoTransition()
+// Waits for transition from SDATA = 1 to SDATA = 0. Has a 100 msec timeout.
+// TRANSITION_TIMEOUT is a loop counter for a 100msec timeout when waiting for
+// a high-to-low transition. This is used in the polling loop of
+// fDetectHiLoTransition(). The timing of the while(1) loops can be calculated
+// and the number of loops is counted, using iTimer, to determine when 100
+// msec has passed.
+//
+//// SCLK cannot run faster than the specified maximum frequency of 8MHz. Some
+// processors may need to have delays added after setting SCLK low and setting
+// SCLK high in order to not exceed this specification. The maximum frequency
+// of SCLK should be measured as part of validation of the final program
+//
+// Returns:
+// 0 if successful
+// -1 if timed out.
+// ============================================================================
+signed char fDetectHiLoTransition(void)
+{
+ // nTimer breaks out of the while loops if the wait in the two loops totals
+ // more than 100 msec. Making this static makes the loop run a faster.
+ // This is really a processor/compiler dependency and it not needed.
+ static unsigned int iTimer;
+
+ // NOTE:
+ // These loops look unconventional, but it is necessary to check SDATA_PIN
+ // as shown because the transition can be missed otherwise, due to the
+ // length of the SDATA Low-High-Low after certain commands.
+
+ // Generate clocks for the target to pull SDATA High
+ //dog_kick();
+ iTimer = TRANSITION_TIMEOUT;
+ printk(KERN_DEBUG
+ "Generate clocks for the target to pull SDATA High\n");
+ while (1) {
+ SCLKLow();
+ if (fSDATACheck()) // exit once SDATA goes HI
+ break;
+ SCLKHigh();
+ // If the wait is too long then timeout
+ if (iTimer-- == 0) {
+ return (ERROR);
+ }
+ }
+ //dog_kick();
+ // Generate Clocks and wait for Target to pull SDATA Low again
+ iTimer = TRANSITION_TIMEOUT; // reset the timeout counter
+ printk(KERN_DEBUG
+ "Generate Clocks and wait for Target to pull SDATA Low again\n");
+ while (1) {
+ SCLKLow(); //issp_test_20100709 unblock
+ if (!fSDATACheck()) { // exit once SDATA returns LOW
+ break;
+ }
+ SCLKHigh(); //issp_test_20100709 unblock
+ // If the wait is too long then timeout
+ if (iTimer-- == 0) {
+ return (ERROR);
+ }
+ }
+ printk("fDetectHiLoTransition OUT!!!!\n");
+ return (PASS);
+}
+
+/* ((((((((((((((((((((( HIGH-LEVEL ISSP ROUTINE SECTION ))))))))))))))))))))))
+ (( These functions are mostly made of calls to the low level routines ))
+ (( above. This should isolate the processor-specific changes so that ))
+ (( these routines do not need to be modified. ))
+ (((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))*/
+
+#ifdef RESET_MODE
+// ============================================================================
+// fXRESInitializeTargetForISSP()
+// Implements the intialization vectors for the device.
+// Returns:
+// 0 if successful
+// INIT_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fXRESInitializeTargetForISSP(void)
+{
+ // Configure the pins for initialization
+ SetSDATAHiZ();
+ SetSCLKStrong();
+ SCLKLow();
+ // Cycle reset and put the device in programming mode when it exits reset
+ AssertXRES();
+ DeassertXRES();
+ // !!! NOTE:
+ // The timing spec that requires that the first Init-Vector happen within
+ // 1 msec after the reset/power up. For this reason, it is not advisable
+ // to separate the above RESET_MODE or POWER_CYCLE_MODE code from the
+ // Init-Vector instructions below. Doing so could introduce excess delay
+ // and cause the target device to exit ISSP Mode.
+
+ //PTJ: Send id_setup_1 instead of init1_v
+ //PTJ: both send CA Test Key and do a Calibrate1 SROM function
+ SendVector(id_setup_1, num_bits_id_setup_1);
+ if (fIsError = fDetectHiLoTransition()) {
+// TX8SW_CPutString("\r\n fDetectHiLoTransition Error");
+ printk("\r\n fDetectHiLoTransition Error\n");
+ return (INIT_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ // NOTE: DO NOT not wait for HiLo on SDATA after vector Init-3
+ // it does not occur (per spec).
+ return (PASS);
+}
+#else //else = the part is power cycle programmed
+
+// ============================================================================
+// fPowerCycleInitializeTargetForISSP()
+// Implements the intialization vectors for the device.
+// The first time fDetectHiLoTransition is called the Clk pin is highZ because
+// the clock is not needed during acquire.
+// Returns:
+// 0 if successful
+// INIT_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fPowerCycleInitializeTargetForISSP(void)
+{
+ // unsigned char n;
+
+ // Set all pins to highZ to avoid back powering the PSoC through the GPIO
+ // protection diodes.
+ SetSCLKHiZ();
+ SetSDATAHiZ();
+
+ // Turn on power to the target device before other signals
+ SetTargetVDDStrong();
+ ApplyTargetVDD();
+ // wait 1msec for the power to stabilize
+#if 0
+ for (n = 0; n < 10; n++) {
+ Delay(DELAY100us);
+ }
+#endif
+ // Set SCLK to high Z so there is no clock and wait for a high to low
+ // transition on SDAT. SCLK is not needed this time.
+ SetSCLKHiZ();
+// printk(KERN_DEBUG "fDetectHiLoTransition\n");
+ if ((fIsError = fDetectHiLoTransition())) {
+ return (INIT_ERROR);
+ }
+ // Configure the pins for initialization
+// SetSDATAHiZ(); // issp_test_20100709 block
+ SetSCLKStrong();
+ SCLKLow(); //PTJ: DO NOT SET A BREAKPOINT HERE AND EXPECT SILICON ID TO PASS!
+
+ // !!! NOTE:
+ // The timing spec that requires that the first Init-Vector happen within
+ // 1 msec after the reset/power up. For this reason, it is not advisable
+ // to separate the above RESET_MODE or POWER_CYCLE_MODE code from the
+ // Init-Vector instructions below. Doing so could introduce excess delay
+ // and cause the target device to exit ISSP Mode.
+
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end); //PTJ: rev308, added to match spec
+// printk("SendVector(id_setup_1)\n",0,0,0);
+ SendVector(id_setup_1, num_bits_id_setup_1);
+ if ((fIsError = fDetectHiLoTransition())) {
+ return (INIT_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ // NOTE: DO NOT not wait for HiLo on SDATA after vector Init-3
+ // it does not occur (per spec).
+ return (PASS);
+}
+#endif
+
+// ============================================================================
+// fVerifySiliconID()
+// Returns:
+// 0 if successful
+// Si_ID_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fVerifySiliconID(void)
+{
+ SendVector(id_setup_2, num_bits_id_setup_2);
+ printk("fVerifySiliconID: SendVector id_stup2 END\n");
+
+ if ((fIsError = fDetectHiLoTransition())) {
+ printk("fVerifySiliconID(): fDetectHiLoTransition Error\n");
+ return (SiID_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+ SendVector(tsync_enable, num_bits_tsync_enable);
+ printk
+ ("fVerifySiliconID: SendVector(wait_and_poll_end) (tsync_enable) END\n");
+
+ //Send Read ID vector and get Target ID
+ SendVector(read_id_v, 11); // Read-MSB Vector is the first 11-Bits
+ RunClock(2); // Two SCLK cycles between write & read
+ bTargetID[0] = bReceiveByte();
+ RunClock(1);
+ SendVector(read_id_v + 2, 12); // 1+11 bits starting from the 3rd byte
+
+ RunClock(2); // Read-LSB Command
+ bTargetID[1] = bReceiveByte();
+
+ RunClock(1);
+ SendVector(read_id_v + 4, 1); // 1 bit starting from the 5th byte
+
+ //read Revision ID from Accumulator A and Accumulator X
+ SendVector(read_id_v + 5, 11); //11 bits starting from the 6th byte
+ RunClock(2);
+ bTargetID[2] = bReceiveByte(); //Read from Acc.X
+ RunClock(1);
+ SendVector(read_id_v + 7, 12); //1+11 bits starting from the 8th byte
+
+ RunClock(2);
+ bTargetID[3] = bReceiveByte(); //Read from Acc.A
+
+ RunClock(1);
+ SendVector(read_id_v + 4, 1); //1bit starting from the 5th byte,
+
+ SendVector(tsync_disable, num_bits_tsync_disable);
+
+ // Print READ-ID
+ /*
+ TX8SW_CPutString("\r\n Silicon-ID : ");
+ TX8SW_PutChar(' ');
+ TX8SW_PutSHexByte(bTargetID[0]);
+ TX8SW_PutChar(' ');
+ TX8SW_PutSHexByte(bTargetID[1]);
+ TX8SW_PutChar(' ');
+ TX8SW_PutSHexByte(bTargetID[2]);
+ TX8SW_PutChar(' ');
+ TX8SW_PutSHexByte(bTargetID[3]);
+ TX8SW_PutChar(' ');
+ */
+#if 0 // issp_test_20100709 block
+ printk("issp_routines.c: ID0:0x%X, ID1:0x%X, ID2: 0x%X, ID2: 0x%X\n",
+ bTargetID[0], bTargetID[1], bTargetID[2], bTargetID[3]);
+
+ if ((bTargetID[0] != target_id_v[0]) || (bTargetID[1] != target_id_v[1])
+ || (bTargetID[2] != target_id_v[2])
+ || (bTargetID[3] != target_id_v[3])) {
+ return (SiID_ERROR);
+ } else {
+ return (PASS);
+ }
+#else
+ return (PASS);
+
+#endif
+}
+
+// PTJ: =======================================================================
+// fReadStatus()
+// Returns:
+// 0 if successful
+// _____ if timed out on handshake to the device.
+// ============================================================================
+signed char fReadStatus(void)
+{
+ SendVector(tsync_enable, num_bits_tsync_enable); //PTJ:
+
+ //Send Read ID vector and get Target ID
+ SendVector(read_id_v, 11); // Read-MSB Vector is the first 11-Bits
+ RunClock(2); // Two SCLK cycles between write & read
+ bTargetStatus[0] = bReceiveByte();
+ RunClock(1);
+ //SendVector(read_id_v+2, 12); // 12 bits starting from the 3rd character
+
+ //RunClock(2); // Read-LSB Command
+ //bTargetStatus[1] = bReceiveByte();
+
+ //RunClock(1);
+ SendVector(read_id_v + 4, 1); // 1 bit starting from the 5th character
+
+ SendVector(tsync_disable, num_bits_tsync_disable);
+
+ if (bTargetStatus[0] == target_status00_v) {
+ return (PASS); //PTJ: Status = 00 means Success, the SROM function did what it was supposed to
+ }
+ if (bTargetStatus[0] == target_status01_v) {
+ return (STATUS_ERROR); //PTJ: Status = 01 means that function is not allowed because of block level protection, for test with verify_setup (VERIFY-SETUP)
+ }
+ if (bTargetStatus[0] == target_status03_v) {
+ return (STATUS_ERROR); //PTJ: Status = 03 is fatal error, SROM halted
+ }
+ if (bTargetStatus[0] == target_status04_v) {
+ return (STATUS_ERROR); //PTJ: Status = 04 means there was a checksum faliure with either the smart write code checksum, or the smart write paramters checksum, for test with PROGRAM-AND-VERIFY
+ }
+ if (bTargetStatus[0] == target_status06_v) {
+ return (STATUS_ERROR); //PTJ: Status = 06 means that Calibrate1 failed, for test with id_setup_1 (ID-SETUP-1)
+ } else {
+ return (STATUS_ERROR);
+ }
+}
+
+// PTJ: =======================================================================
+// fReadCalRegisters()
+// PTJ: use this to read some cal registers that should be loaded by Calibrate1 in id_setup_1
+// Returns:
+// 0 if successful
+// _____ if timed out on handshake to the device.
+// ============================================================================
+signed char fReadCalRegisters(void)
+{
+ SendVector(tsync_enable, num_bits_tsync_enable);
+
+ SendVector(Switch_Bank1, 22);
+
+ SendVector(read_IMOtrim, 11); // Read-MSB Vector is the first 11-Bits
+ RunClock(2); // Two SCLK cycles between write & read
+ bTargetStatus[0] = bReceiveByte();
+ RunClock(1);
+ // Set SDATA to Strong Drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(read_reg_end, 1);
+
+ SendVector(read_SPCtrim, 11); // Read-MSB Vector is the first 11-Bits
+ RunClock(2); // Two SCLK cycles between write & read
+ bTargetStatus[1] = bReceiveByte();
+ RunClock(1);
+ // Set SDATA to Strong Drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(read_reg_end, 1);
+
+ SendVector(read_VBGfinetrim, 11); // Read-MSB Vector is the first 11-Bits
+ RunClock(2); // Two SCLK cycles between write & read
+ bTargetStatus[2] = bReceiveByte();
+ RunClock(1);
+ // Set SDATA to Strong Drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(read_reg_end, 1);
+
+ SendVector(Switch_Bank0, 22);
+
+ SendVector(tsync_disable, num_bits_tsync_disable);
+
+ if (bTargetStatus[0] == target_status00_v) {
+ return (PASS); //PTJ: Status = 00 means Success, the SROM function did what it was supposed to
+ }
+ return PASS;
+}
+
+// PTJ: =======================================================================
+// fReadWriteSetup()
+// PTJ: The READ-WRITE-SETUP vector will enable TSYNC and switches the device
+// to SRAM bank1 for PROGRAM-AND-VERIFY, SECURE and VERIFY-SETUP.
+// Returns:
+// 0 if successful
+// _____ if timed out on handshake to the device.
+// ============================================================================
+signed char fReadWriteSetup(void)
+{
+ SendVector(read_write_setup, num_bits_read_write_setup);
+ return (PASS); //PTJ: is there anything else that should be done?
+}
+
+// PTJ: =======================================================================
+// fSyncEnable()
+// PTJ: The SYNC-ENABLE vector will enable TSYNC
+//
+// Returns:
+// 0 if successful
+// _____ if timed out on handshake to the device.
+// ============================================================================
+signed char fSyncEnable(void)
+{
+ SendVector(tsync_enable, num_bits_tsync_enable); //PTJ: 307 for tsync enable testing
+ return (PASS); //PTJ: is there anything else that should be done?
+}
+
+// PTJ: =======================================================================
+// fSyncDisable()
+// PTJ: The SYNC-ENABLE vector will enable TSYNC
+//
+// Returns:
+// 0 if successful
+// _____ if timed out on handshake to the device.
+// ============================================================================
+signed char fSyncDisable(void)
+{
+ SendVector(tsync_disable, num_bits_tsync_disable); //PTJ: 307 for tsync enable testing
+ return (PASS);
+}
+
+// ============================================================================
+// fEraseTarget()
+// Perform a bulk erase of the target device.
+// Returns:
+// 0 if successful
+// ERASE_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fEraseTarget(void)
+{
+ SendVector(erase, num_bits_erase);
+ if ((fIsError = fDetectHiLoTransition())) {
+// TX8SW_CPutString("\r\n fDetectHiLoTransition");
+ //printk("\r\n fDetectHiLoTransition\n"); // issp_test_2010 block
+ return (ERASE_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+ return (PASS);
+}
+
+extern unsigned int iBlockCounter;
+// ============================================================================
+// LoadTarget()
+// Transfers data from array in Host to RAM buffer in the target.
+// Returns the checksum of the data.
+// ============================================================================
+unsigned int iLoadTarget(void)
+{
+ unsigned char bTemp;
+ unsigned int iChecksumData = 0;
+
+ // Set SDATA to Strong Drive here because SendByte() does not
+ SetSDATAStrong();
+
+ // Transfer the temporary RAM array into the target.
+ // In this section, a 128-Byte array was specified by #define, so the entire
+ // 128-Bytes are written in this loop.
+ bTargetAddress = 0x00;
+ bTargetDataPtr = 0x00;
+
+ while (bTargetDataPtr < TARGET_DATABUFF_LEN) {
+ bTemp = abTargetDataOUT[bTargetDataPtr];
+ iChecksumData += bTemp;
+
+ SendByte(write_byte_start, 4); //PTJ: we need to be able to write 128 bytes from address 0x80 to 0xFF
+ SendByte(bTargetAddress, 7); //PTJ: we need to be able to write 128 bytes from address 0x80 to 0xFF
+ SendByte(bTemp, 8);
+ SendByte(write_byte_end, 3);
+
+ // !!!NOTE:
+ // SendByte() uses MSbits, so inc by '2' to put the 0..128 address into
+ // the seven MSBit locations.
+ //
+ // This can be confusing, but check the logic:
+ // The address is only 7-Bits long. The SendByte() subroutine will
+ // send however-many bits, BUT...always reads them bits from left-to-
+ // right. So in order to pass a value of 0..128 as the address using
+ // SendByte(), we have to left justify the address by 1-Bit.
+ // This can be done easily by incrementing the address each time by
+ // '2' rather than by '1'.
+
+ bTargetAddress += 2; //PTJ: inc by 2 in order to support a 128 byte address space, MSB~1 for address
+ bTargetDataPtr++;
+ }
+
+ return (iChecksumData);
+}
+
+#ifdef MULTI_BANK
+// ============================================================================
+// SetBankNumber()
+// Set the bank number in the target device.
+// Returns:
+// none
+// ============================================================================
+void SetBankNumber(unsigned char bBankNumber)
+{
+ // Send the bank-select vector.
+ SendVector(set_bank_number, 33);
+
+ // Set the drive here because SendByte() does not.
+ SetSDATAStrong();
+ SendByte(bBankNumber, 8);
+ SendVector(set_bank_number_end, 25);
+}
+#endif
+
+// ============================================================================
+// fProgramTargetBlock()
+// Program one block with data that has been loaded into a RAM buffer in the
+// target device.
+// Returns:
+// 0 if successful
+// BLOCK_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fProgramTargetBlock(unsigned char bBankNumber,
+ unsigned char bBlockNumber)
+{
+
+ SendVector(tsync_enable, num_bits_tsync_enable);
+
+ SendVector(set_block_num, num_bits_set_block_num);
+
+ // Set the drive here because SendByte() does not.
+ SetSDATAStrong();
+ SendByte(bBlockNumber, 8);
+ SendByte(set_block_num_end, 3);
+
+ SendVector(tsync_disable, num_bits_tsync_disable); //PTJ:
+
+ // Send the program-block vector.
+ SendVector(program_and_verify, num_bits_program_and_verify); //PTJ: PROGRAM-AND-VERIFY
+ // wait for acknowledge from target.
+ if ((fIsError = fDetectHiLoTransition())) {
+ return (BLOCK_ERROR);
+ }
+ // Send the Wait-For-Poll-End vector
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+ return (PASS);
+
+ //PTJ: Don't do READ-STATUS here because that will
+ //PTJ: require that we return multiple error values, if error occurs
+}
+
+// ============================================================================
+// fAddTargetBankChecksum()
+// Reads and adds the target bank checksum to the referenced accumulator.
+// Returns:
+// 0 if successful
+// VERIFY_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fAccTargetBankChecksum(unsigned int *pAcc)
+{
+ unsigned int wCheckSumData;
+
+ SendVector(checksum_setup, num_bits_checksum_setup); //PTJ:CHECKSUM-SETUP, it is taking 100ms > time > 200ms to complete the checksum
+ if ((fIsError = fDetectHiLoTransition())) { //100ms is default
+ return (VERIFY_ERROR);
+ }
+
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ SendVector(tsync_enable, num_bits_tsync_enable);
+
+ //Send Read Checksum vector and get Target Checksum
+ SendVector(read_checksum_v, 11); // first 11-bits is ReadCKSum-MSB
+ RunClock(2); // Two SCLKs between write & read
+ bTargetDataIN = bReceiveByte();
+ wCheckSumData = bTargetDataIN << 8;
+
+ RunClock(1); // See Fig. 6
+ SendVector(read_checksum_v + 2, 12); // 12 bits starting from 3rd character
+ RunClock(2); // Read-LSB Command
+ bTargetDataIN = bReceiveByte();
+ wCheckSumData |= (bTargetDataIN & 0xFF);
+ RunClock(1);
+ SendVector(read_checksum_v + 3, 1); // Send the final bit of the command //PTJ: read_checksum_v may have to change if TSYNC needs to be enabled
+
+ SendVector(tsync_disable, num_bits_tsync_disable);
+
+ *pAcc = wCheckSumData;
+
+ return (PASS);
+}
+
+// ============================================================================
+// ReStartTarget()
+// After programming, the target PSoC must be reset to take it out of
+// programming mode. This routine performs a reset.
+// ============================================================================
+void ReStartTarget(void)
+{
+#ifdef RESET_MODE
+ // Assert XRES, then release, then disable XRES-Enable
+ AssertXRES();
+ Delay(XRES_CLK_DELAY);
+ DeassertXRES();
+#else
+ // Set all pins to highZ to avoid back powering the PSoC through the GPIO
+ // protection diodes.
+ SetSCLKHiZ();
+ SetSDATAHiZ();
+ // Cycle power on the target to cause a reset
+ RemoveTargetVDD();
+ mdelay(300);
+ ApplyTargetVDD();
+#endif
+}
+
+// ============================================================================
+// fVerifySetup()
+// Verify the block just written to. This can be done byte-by-byte before the
+// protection bits are set.
+// Returns:
+// 0 if successful
+// BLOCK_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fVerifySetup(unsigned char bBankNumber, unsigned char bBlockNumber)
+{
+ SendVector(tsync_enable, num_bits_tsync_enable);
+
+ SendVector(set_block_num, num_bits_set_block_num);
+
+ //Set the drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(bBlockNumber, 8);
+ SendByte(set_block_num_end, 3); //PTJ:
+
+ SendVector(tsync_disable, num_bits_tsync_disable); //PTJ:
+
+ SendVector(verify_setup, num_bits_my_verify_setup); //PTJ:
+ if ((fIsError = fDetectHiLoTransition())) {
+ return (BLOCK_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ return (PASS);
+}
+
+// ============================================================================
+// fReadByteLoop()
+// Reads the data back from Target SRAM and compares it to expected data in
+// Host SRAM
+// Returns:
+// 0 if successful
+// BLOCK_ERROR if timed out on handshake to the device.
+// ============================================================================
+
+signed char fReadByteLoop(void)
+{
+ bTargetAddress = 0;
+ bTargetDataPtr = 0;
+
+ while (bTargetDataPtr < TARGET_DATABUFF_LEN) {
+ //Send Read Byte vector and then get a byte from Target
+ SendVector(read_byte_v, 4);
+ // Set the drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(bTargetAddress, 7);
+
+ RunClock(2); // Run two SCLK cycles between writing and reading
+ SetSDATAHiZ(); // Set to HiZ so Target can drive SDATA
+ bTargetDataIN = bReceiveByte();
+
+ RunClock(1);
+ SendVector(read_byte_v + 1, 1); // Send the ReadByte Vector End
+
+ // Test the Byte that was read from the Target against the original
+ // value (already in the 128-Byte array "abTargetDataOUT[]"). If it
+ // matches, then bump the address & pointer,loop-back and continue.
+ // If it does NOT match abort the loop and return and error.
+ if (bTargetDataIN != abTargetDataOUT[bTargetDataPtr]) {
+#ifdef TX_ON
+ UART_PutCRLF();
+ UART_CPutString("bTargetDataIN : ");
+ UART_PutHexByte(bTargetDataIN);
+ UART_CPutString(" abTargetDataOUT : ");
+ UART_PutHexByte(abTargetDataOUT[bTargetDataPtr]);
+#endif
+ return (BLOCK_ERROR);
+ }
+
+ bTargetDataPtr++;
+ // Increment the address by 2 to accomodate 7-Bit addressing
+ // (puts the 7-bit address into MSBit locations for "SendByte()").
+ bTargetAddress += 2;
+
+ }
+
+ return (PASS);
+}
+
+// ============================================================================
+// fVerifyTargetBlock()
+// Verify the block just written to. This can be done byte-by-byte before the
+// protection bits are set.
+// Returns:
+// 0 if successful
+// BLOCK_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fVerifyTargetBlock(unsigned char bBankNumber,
+ unsigned char bBlockNumber)
+{
+ SendVector(set_block_number, 11);
+
+ //Set the drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(bBlockNumber, 8);
+ SendByte(set_block_number_end, 3);
+
+ SendVector(verify_setup_v, num_bits_verify_setup);
+ if ((fIsError = fDetectHiLoTransition())) {
+ return (BLOCK_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ bTargetAddress = 0;
+ bTargetDataPtr = 0;
+
+ while (bTargetDataPtr < TARGET_DATABUFF_LEN) {
+ //Send Read Byte vector and then get a byte from Target
+ SendVector(read_byte_v, 4); //PTJ 308: this was changed from sending the first 5 bits to sending the first 4
+ // Set the drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(bTargetAddress, 6);
+
+ RunClock(2); // Run two SCLK cycles between writing and reading
+ SetSDATAHiZ(); // Set to HiZ so Target can drive SDATA
+ bTargetDataIN = bReceiveByte();
+
+ RunClock(1);
+ SendVector(read_byte_v + 1, 1); // Send the ReadByte Vector End
+
+ // Test the Byte that was read from the Target against the original
+ // value (already in the 128-Byte array "abTargetDataOUT[]"). If it
+ // matches, then bump the address & pointer,loop-back and continue.
+ // If it does NOT match abort the loop and return an error.
+ if (bTargetDataIN != abTargetDataOUT[bTargetDataPtr])
+ return (BLOCK_ERROR);
+
+ bTargetDataPtr++;
+ // Increment the address by four to accomodate 6-Bit addressing
+ // (puts the 6-bit address into MSBit locations for "SendByte()").
+ bTargetAddress += 4;
+ }
+ return (PASS);
+}
+
+// ============================================================================
+// fSecureTargetFlash()
+// Before calling, load the array, abTargetDataOUT, with the desired security
+// settings using LoadArrayWithSecurityData(StartAddress,Length,SecurityType).
+// The can be called multiple times with different SecurityTypes as needed for
+// particular Flash Blocks. Or set them all the same using the call below:
+// LoadArrayWithSecurityData(0,SECURITY_BYTES_PER_BANK, 0);
+// Returns:
+// 0 if successful
+// SECURITY_ERROR if timed out on handshake to the device.
+// ============================================================================
+signed char fSecureTargetFlash(void)
+{
+ unsigned char bTemp;
+
+ // Transfer the temporary RAM array into the target
+ bTargetAddress = 0x00;
+ bTargetDataPtr = 0x00;
+
+ SetSDATAStrong();
+ while (bTargetDataPtr < SECURITY_BYTES_PER_BANK) {
+ bTemp = abTargetDataOUT[bTargetDataPtr];
+ SendByte(write_byte_start, 4);
+ SendByte(bTargetAddress, 7);
+ SendByte(bTemp, 8);
+ SendByte(write_byte_end, 3);
+
+ // SendBytes() uses MSBits, so increment the address by '2' to put
+ // the 0..n address into the seven MSBit locations
+ bTargetAddress += 2; //PTJ: inc by 2 in order to support a 128 byte address space
+ bTargetDataPtr++;
+ }
+
+ SendVector(secure, num_bits_secure); //PTJ:
+ if ((fIsError = fDetectHiLoTransition())) {
+ return (SECURITY_ERROR);
+ }
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+ return (PASS);
+}
+
+// ============================================================================
+// PTJ: fReadSecurity()
+// This reads from SM0 with Read Supervisory SPC command.
+// Need to have SPC Test Mode enabled before using these commands?
+// Returns:
+// 0 if successful
+// __________ if timed out on handshake to the device.
+// ============================================================================
+signed char fReadSecurity(void)
+{
+ SendVector(ReadSecuritySetup, num_bits_ReadSecuritySetup);
+// SendVector(SPCTestMode_enable, num_bits_SPCTestMode_enable);
+
+ bTargetAddress = 0x00;
+ while (bTargetAddress < (SECURITY_BYTES_PER_BANK * 2)) { //PTJ: we do SECURITY_BYTES_PER_BANK * 2 because we bTargetAddress += 2
+
+ //PTJ: TSYNC Enable
+ SendVector(tsync_enable, num_bits_tsync_enable);
+
+ SendVector(read_security_pt1, num_bits_read_security_pt1); //PTJ:
+ // Set the drive here because SendByte() does not.
+ SetSDATAStrong();
+ SendByte(bTargetAddress, 7); //PTJ: hardcode MSb of address as 0 in bit stream
+ SendVector(read_security_pt1_end,
+ num_bits_read_security_pt1_end);
+
+ //PTJ: TSYNC Disable
+ SendVector(tsync_disable, num_bits_tsync_disable);
+
+ SendVector(read_security_pt2, num_bits_read_security_pt2);
+
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ SendVector(read_security_pt3, num_bits_read_security_pt3);
+
+ SetSDATAStrong();
+ SendByte(bTargetAddress, 7);
+
+ SendVector(read_security_pt3_end,
+ num_bits_read_security_pt3_end);
+
+ SendVector(wait_and_poll_end, num_bits_wait_and_poll_end);
+
+ bTargetAddress += 2;
+ }
+
+ bTargetAddress = 0x00;
+ bTargetDataPtr = 0x00;
+
+ SendVector(tsync_enable, num_bits_tsync_enable); //PTJ: 307, added for tsync testing
+ while (bTargetAddress < (SECURITY_BYTES_PER_BANK * 2)) { //PTJ: we do SECURITY_BYTES_PER_BANK * 2 because we bTargetAddress += 2
+
+ //Send Read Byte vector and then get a byte from Target
+ SendVector(read_byte_v, 4);
+ // Set the drive here because SendByte() does not
+ SetSDATAStrong();
+ SendByte(bTargetAddress, 7);
+
+ RunClock(2); // Run two SCLK cycles between writing and reading
+ SetSDATAHiZ(); // Set to HiZ so Target can drive SDATA
+ bTargetDataIN = bReceiveByte();
+
+ RunClock(1);
+ SendVector(read_byte_v + 1, 1); // Send the ReadByte Vector End
+
+ // Test the Byte that was read from the Target against the original
+ // value (already in the 128-Byte array "abTargetDataOUT[]"). If it
+ // matches, then bump the address & pointer,loop-back and continue.
+ // If it does NOT match abort the loop and return and error.
+ if (bTargetDataIN != abTargetDataOUT[bTargetDataPtr])
+// return(BLOCK_ERROR);
+
+ // Increment the address by two to accomodate 7-Bit addressing
+ // (puts the 7-bit address into MSBit locations for "SendByte()").
+ bTargetDataPtr++;
+ bTargetAddress += 2;
+ }
+
+ SendVector(tsync_disable, num_bits_tsync_disable); //PTJ: 307, added for tsync testing
+ return (PASS);
+}
+
+#endif //(PROJECT_REV_)
+// end of file ISSP_Routines.c
diff --git a/drivers/input/keyboard/cypressbln/issp_vectors.h b/drivers/input/keyboard/cypressbln/issp_vectors.h
new file mode 100644
index 0000000..35d5ef1
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/issp_vectors.h
@@ -0,0 +1,1146 @@
+// filename: ISSP_Vectors.h
+#include "issp_revision.h"
+#ifdef PROJECT_REV_304
+/* Copyright 2006-2007, Cypress Semiconductor Corporation.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONRTACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
+ WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ Cypress reserves the right to make changes without further notice to the
+ materials described herein. Cypress does not assume any liability arising
+ out of the application or use of any product or circuit described herein.
+ Cypress does not authorize its products for use as critical components in
+ life-support systems where a malfunction or failure may reasonably be
+ expected to result in significant injury to the user. The inclusion of
+ Cypress� product in a life-support systems application implies that the
+ manufacturer assumes all risk of such use and in doing so indemnifies
+ Cypress against all charges.
+
+ Use may be limited by and subject to the applicable Cypress software
+ license agreement.
+
+-----------------------------------------------------------------------------*/
+#ifndef INC_ISSP_VECTORS
+#define INC_ISSP_VECTORS
+
+#include "issp_directives.h"
+
+#define HEX_DEFINE
+// ------------------------- PSoC CY8C20x66 Devices ---------------------------
+
+#ifdef CY8C20236 /// 2009.03.26. kimc
+unsigned char target_id_v[] = { 0x00, 0xb3, 0x52, 0x21 }; //ID for CY8C20236
+#endif
+#ifdef CY8C20246 /// 2009.03.26. kimc
+unsigned char target_id_v[] = { 0x00, 0xAA, 0x52, 0x21 }; //ID for CY8C20246
+#endif
+#ifdef CY8C20266
+unsigned char target_id_v[] = { 0x00, 0x96, 0x52, 0x21 }; //ID for CY8C20266
+#endif
+#ifdef CY8C20366
+unsigned char target_id_v[] = { 0x00, 0x97, 0x52, 0x21 }; //ID for CY8C20366
+#endif
+#ifdef CY8C20466
+unsigned char target_id_v[] = { 0x00, 0x98, 0x52, 0x21 }; //ID for CY8C20466
+#endif
+#ifdef CY8C20566
+unsigned char target_id_v[] = { 0x00, 0x99, 0x52, 0x21 }; //ID for CY8C20566
+#endif
+#ifdef CY8C20666
+unsigned char target_id_v[] = { 0x00, 0x9c, 0x52, 0x21 }; //ID for CY8C20666
+#endif
+#ifdef CY8C20066
+unsigned char target_id_v[] = { 0x00, 0x9a, 0x52, 0x21 }; //ID for CY8C20066
+#endif
+#ifdef CY8C200661
+unsigned char target_id_v[] = { 0x00, 0x9b, 0x52, 0x21 }; //ID for CY8C200661
+#endif
+
+#ifdef CY8C20x66
+unsigned char target_status00_v = 0x00; //PTJ: Status = 00 means Success, the SROM function did what it was supposed to
+unsigned char target_status01_v = 0x01; //PTJ: Status = 01 means that function is not allowed because of block level protection, for test with verify_setup (VERIFY-SETUP)
+unsigned char target_status03_v = 0x03; //PTJ: Status = 03 is fatal error, SROM halted
+unsigned char target_status04_v = 0x04; //PTJ: Status = 04 means that ___ for test with ___ (PROGRAM-AND-VERIFY)
+unsigned char target_status06_v = 0x06; //PTJ: Status = 06 means that Calibrate1 failed, for test with id_setup_1 (ID-SETUP-1)
+#endif
+
+/*************** CY8CTMA30x, CY8CTMG30x, CY8CTST30x series by KIMC, 2009.08.11 ***********************************/
+// ------------------------- PSoC CY8CTMA30x, CY8CTMG30x, CY8CTST30x Devices ---------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8CTST300_36 // CY8CTST300_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x06, 0x71, 0x70, 0x11 };
+#endif
+#ifdef CY8CTST300_48 // CY8CTST300_48LTXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x06, 0x72, 0x70, 0x11 };
+#endif
+#ifdef CY8CTST300_49 // CY8CTST300_49FNXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x06, 0x73, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300_36 // CY8CTMA300_36LQXI // 2009.08.11, Test OK.
+unsigned char target_id_v[] = { 0x05, 0x71, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300_48 // CY8CTMA300_48LTXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x72, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300_49 // CY8CTMA300_49FNXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x73, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMG300_36 // CY8CTMG300_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x07, 0x71, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMG300_48 // CY8CTMG300_48LTXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x07, 0x72, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMG300_49 // CY8CTMG300_49FNXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x07, 0x73, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMG300B_36 // CY8CTMG300B_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x07, 0x75, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300B_36 // CY8CTMA300B_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x74, 0x70, 0x11 };
+#endif
+#ifdef CY8CTST300B_36 // CY8CTST300B_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x06, 0x74, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA301_36 // CY8CTMA301_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x75, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA301_48 // CY8CTMA301_48LTXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x76, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA301D_36 // CY8CTMA301D_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x77, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA301D_48 // CY8CTMA301D_48LTXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x78, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300D_36 // CY8CTMA300D_36LQXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x79, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300D_48 // CY8CTMA300D_48LTXI // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x80, 0x70, 0x11 };
+#endif
+#ifdef CY8CTMA300D_49 // CY8CTMA300D_49FNXIT // 2009.08.11, not tested.
+unsigned char target_id_v[] = { 0x05, 0x81, 0x70, 0x11 };
+#endif
+/********************************************************************************************************/
+
+/*************** CY8CTMG/TST series modified by KJHW, 2009.08.14 ***********************************/
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8CTMG110
+unsigned char target_id_v[] = { 0x07, 0x38 }; //ID for CY8CTMG110
+
+unsigned char target_status00_v = 0x00; //PTJ: Status = 00 means Success, the SROM function did what it was supposed to
+unsigned char target_status01_v = 0x01; //PTJ: Status = 01 means that function is not allowed because of block level protection, for test with verify_setup (VERIFY-SETUP)
+unsigned char target_status03_v = 0x03; //PTJ: Status = 03 is fatal error, SROM halted
+unsigned char target_status04_v = 0x04; //PTJ: Status = 04 means that ___ for test with ___ (PROGRAM-AND-VERIFY)
+unsigned char target_status06_v = 0x06; //PTJ: Status = 06 means that Calibrate1 failed, for test with id_setup_1 (ID-SETUP-1)
+#endif
+
+#ifdef CY8CTST200_24PIN
+unsigned char target_id_v[] = { 0x06, 0x6D, 0x52, 0x21 }; //ID for CY8CTST200
+#endif
+#ifdef CY8CTST200_32PIN
+unsigned char target_id_v[] = { 0x06, 0x6E, 0x52, 0x21 }; //ID for CY8CTST200
+#endif
+#ifdef CY8CTMG200_24PIN
+unsigned char target_id_v[] = { 0x07, 0x6D, 0x52, 0x21 }; //ID for CY8CTMG200
+#endif
+#ifdef CY8CTMG200_32PIN
+unsigned char target_id_v[] = { 0x07, 0x6E, 0x52, 0x21 }; //ID for CY8CTMG200
+#endif
+
+/********************************************************************************************************/
+
+// ------------------------- PSoC CY8C21x23 Devices ---------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8C21123
+unsigned char target_id_v[] = { 0x00, 0x17 }; //ID for CY8C21123
+#endif
+#ifdef CY8C21223
+unsigned char target_id_v[] = { 0x00, 0x18 }; //ID for CY8C21223
+#endif
+#ifdef CY8C21323
+unsigned char target_id_v[] = { 0x00, 0x19 }; //ID for CY8C2132
+#endif
+#ifdef CY8C21002
+unsigned char target_id_v[] = { 0x00, 0x3F }; //ID for CY8C21x23 ICE pod
+#endif
+
+// ------------------------- PSoC CY8C21x34 Devices ---------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8C21234
+unsigned char target_id_v[] = { 0x00, 0x36 }; //ID for CY8C21234
+#endif
+#ifdef CY8C21334
+unsigned char target_id_v[] = { 0x00, 0x37 }; //ID for CY8C21334
+#endif
+#ifdef CY8C21434
+unsigned char target_id_v[] = { 0x00, 0x38 }; //ID for CY8C21434
+#endif
+#ifdef CY8C21534
+unsigned char target_id_v[] = { 0x00, 0x40 }; //ID for CY8C21534
+#endif
+#ifdef CY8C21634
+unsigned char target_id_v[] = { 0x00, 0x49 }; //ID for CY8C21634
+#endif
+#ifdef CY8C21001
+unsigned char target_id_v[] = { 0x00, 0x39 }; //ID for CY8C21x34 ICE pod
+#endif
+
+// ------------------------- PSoC CY8C24x23A Devices --------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8C24123A
+unsigned char target_id_v[] = { 0x00, 0x32 }; //ID for CY8C24123A
+#endif
+#ifdef CY8C24223A
+unsigned char target_id_v[] = { 0x00, 0x33 }; //ID for CY8C24223A
+#endif
+#ifdef CY8C24423A
+unsigned char target_id_v[] = { 0x00, 0x34 }; //ID for CY8C24423A
+#endif
+#ifdef CY8C24000A
+unsigned char target_id_v[] = { 0x00, 0x35 }; //ID for CY8C24x23A ICE pod
+#endif
+
+// ------------------------- PSoC CY8C24x94 Devices ---------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8C24794
+unsigned char target_id_v[] = { 0x00, 0x1D }; //ID for CY8C24794
+#endif
+#ifdef CY8C24894
+unsigned char target_id_v[] = { 0x00, 0x1F }; //ID for CY8C24894
+#endif
+#ifdef CY8C24994
+unsigned char target_id_v[] = { 0x00, 0x59 }; //ID for CY8C24994
+#endif
+#ifdef CY8C24094
+unsigned char target_id_v[] = { 0x00, 0x1B }; //ID for CY8C24094
+#endif
+
+// ------------------------- PSoC CY8C27x43 Devices ---------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8C27143
+unsigned char target_id_v[] = { 0x00, 0x09 }; //ID for CY8C27143
+#endif
+#ifdef CY8C27243
+unsigned char target_id_v[] = { 0x00, 0x0A }; //ID for CY8C27243
+#endif
+#ifdef CY8C27443
+unsigned char target_id_v[] = { 0x00, 0x0B }; //ID for CY8C27443
+#endif
+#ifdef CY8C27543
+unsigned char target_id_v[] = { 0x00, 0x0C }; //ID for CY8C27543
+#endif
+#ifdef CY8C27643
+unsigned char target_id_v[] = { 0x00, 0x0D }; //ID for CY8C27643
+#endif
+#ifdef CY8C27002
+unsigned char target_id_v[] = { 0x00, 0x0E }; //ID for CY8C27x43 ICE pod
+#endif
+
+// ------------------------- PSoC CY8C29x66 Devices ---------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CY8C29466
+unsigned char target_id_v[] = { 0x00, 0x2A }; //ID for CY8C29466
+#endif
+#ifdef CY8C29566
+unsigned char target_id_v[] = { 0x00, 0x2B }; //ID for CY8C29566
+#endif
+#ifdef CY8C29666
+unsigned char target_id_v[] = { 0x00, 0x2C }; //ID for CY8C29666
+#endif
+#ifdef CY8C29866
+unsigned char target_id_v[] = { 0x00, 0x2D }; //ID for CY8C29866
+#endif
+#ifdef CY8C29002
+unsigned char target_id_v[] = { 0x00, 0x2E }; //ID for CY8C29002
+#endif
+
+// --------- CY8C20x66 Vectors ------------------------------------------------
+// ----------------------------------------------------------------------------
+#ifdef TSYNC
+const unsigned int num_bits_tsync_enable = 110;
+const unsigned char tsync_enable[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE2, 0x1F, 0x7F, 0x02, 0x7D, 0xC4, 0x09,
+ 0xF7, 0x00, 0x1F, 0xDE, 0xE0, 0x1C
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b11011110, 0 b11100000,
+ 0 b00011100
+#endif
+};
+
+const unsigned int num_bits_tsync_disable = 110;
+const unsigned char tsync_disable[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE2, 0x1F, 0x71, 0x00, 0x7D, 0xFC, 0x01,
+ 0xF7, 0x00, 0x1F, 0xDE, 0xE0, 0x1C
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01110001, 0 b00000000,
+ 0 b01111101, 0 b11111100, 0 b00000001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b11011110, 0 b11100000,
+ 0 b00011100
+#endif
+};
+#endif
+
+#ifdef CY8CTMx30x
+#ifdef ID_SETUP_1
+const unsigned int num_bits_id_setup_1 = 616; //KIMC, 2009.08.11, PTJ: id_setup_1 with TSYNC enabled for MW and disabled for IOW
+const unsigned char id_setup_1[] = {
+ 0 b11001010, 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00001101, 0 b11101110, 0 b00100001, 0 b11110111, 0 b11110000,
+ 0 b00100111, 0 b11011100, 0 b01000000,
+ 0 b10011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00000001, 0 b11100111, 0 b11000001,
+ 0 b11010111, 0 b10011111, 0 b00100000, 0 b01111110, 0 b00111111,
+ 0 b10011101, 0 b01111000, 0 b11110110,
+ 0 b00100001, 0 b11110111, 0 b10111000, 0 b10000111, 0 b11011111,
+ 0 b11000000, 0 b00011111, 0 b01110001,
+ 0 b00000000, 0 b01111101, 0 b11000000, 0 b00000111, 0 b11110111,
+ 0 b10111000, 0 b00000111, 0 b11011110,
+ 0 b10000000, 0 b01111111, 0 b01111010, 0 b10000000, 0 b01111101,
+ 0 b11101100, 0 b00000001, 0 b11110111,
+ 0 b10000000, 0 b01001111, 0 b11011111, 0 b00000000, 0 b00011111,
+ 0 b01111100, 0 b10100000, 0 b01111101,
+ 0 b11110100, 0 b01100001, 0 b11110111, 0 b11111000, 0 b10010111
+};
+#endif
+#else
+#ifdef ID_SETUP_1
+const unsigned int num_bits_id_setup_1 = 594; //PTJ: id_setup_1 with TSYNC enabled for MW and disabled for IOW
+const unsigned char id_setup_1[] = {
+#ifdef HEX_DEFINE
+ 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0D, 0xEE, 0x21, 0xF7, 0xF0, 0x27, 0xDC, 0x40,
+ 0x9F, 0x70, 0x01, 0xFD, 0xEE, 0x01, /*0x21, */ 0xE7, 0xC1,
+ 0xD7, 0x9F, 0x20, 0x7E, 0x7D, 0x88, 0x7D, 0xEE,
+ 0x21, 0xF7, 0xF0, 0x07, 0xDC, 0x40, 0x1F, 0x70,
+ 0x01, 0xFD, 0xEE, 0x01, 0xF7, 0xA0, 0x1F, 0xDE,
+ 0xA0, 0x1F, 0x7B, 0x00, 0x7D, 0xE0, 0x13, 0xF7,
+ 0xC0, 0x07, 0xDF, 0x28, 0x1F, 0x7D, 0x18, 0x7D,
+ 0xFE, 0x25, 0xC0
+#else
+ 0 b11001010, 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00001101, 0 b11101110, 0 b00100001, 0 b11110111, 0 b11110000,
+ 0 b00100111, 0 b11011100, 0 b01000000,
+ 0 b10011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00100001, 0 b11100111, 0 b11000001,
+ 0 b11010111, 0 b10011111, 0 b00100000, 0 b01111110, 0 b01111101,
+ 0 b10001000, 0 b01111101, 0 b11101110,
+ 0 b00100001, 0 b11110111, 0 b11110000, 0 b00000111, 0 b11011100,
+ 0 b01000000, 0 b00011111, 0 b01110000,
+ 0 b00000001, 0 b11111101, 0 b11101110, 0 b00000001, 0 b11110111,
+ 0 b10100000, 0 b00011111, 0 b11011110,
+ 0 b10100000, 0 b00011111, 0 b01111011, 0 b00000000, 0 b01111101,
+ 0 b11100000, 0 b00010011, 0 b11110111,
+ 0 b11000000, 0 b00000111, 0 b11011111, 0 b00101000, 0 b00011111,
+ 0 b01111101, 0 b00011000, 0 b01111101,
+ 0 b11111110, 0 b00100101, 0 b11000000
+#endif
+};
+#endif
+#endif
+
+#ifdef SET_BLOCK_NUM
+const unsigned int num_bits_set_block_num = 11; //PTJ:
+const unsigned char set_block_num[] = {
+#ifdef HEX_DEFINE
+ 0x9f, 0x40, 0x1c
+#else
+ 0 b11011110, 0 b11100000, 0 b00011110, 0 b01111101, 0 b00000000,
+ 0 b01110000
+#endif
+};
+
+const unsigned int num_bits_set_block_num_end = 3; //PTJ: this selects the first three bits of set_block_num_end
+const unsigned char set_block_num_end = 0xE0;
+#endif
+
+#ifdef READ_WRITE_SETUP
+const unsigned int num_bits_read_write_setup = 66; //PTJ:
+const unsigned char read_write_setup[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xf0, 0x1f, 0x78, 0x00, 0x7d, 0xa0, 0x03,
+ 0xc0
+#else
+ 0 b11011110, 0 b11110000, 0 b00011111, 0 b01111000, 0 b00000000,
+ 0 b01111101, 0 b10100000, 0 b00000011,
+ 0 b11000000
+#endif
+};
+#endif
+
+#ifdef VERIFY_SETUP
+const unsigned int num_bits_my_verify_setup = 440;
+const unsigned char verify_setup[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0xfc, 0x81,
+ 0xf9, 0xf7, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf6, 0xa8,
+ 0x0f, 0xde, 0x80, 0x7f, 0x7a, 0x80, 0x7d, 0xec,
+ 0x01, 0xf7, 0x80, 0x0f, 0xdf, 0x00, 0x1f, 0x7c,
+ 0xa0, 0xfd, 0xf4, 0x61, 0xf7, 0xf8, 0x97
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11110000,
+ 0 b00000111, 0 b11011100, 0 b01000000,
+ 0 b00011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00000001, 0 b11110110, 0 b10101000,
+ 0 b00001111, 0 b11011110, 0 b10000000, 0 b01111111, 0 b01111010,
+ 0 b10000000, 0 b01111101, 0 b11101100,
+ 0 b00000001, 0 b11110111, 0 b10000000, 0 b00001111, 0 b11011111,
+ 0 b00000000, 0 b00011111, 0 b01111100,
+ 0 b10100000, 0 b01111101, 0 b11110100, 0 b01100001, 0 b11110111,
+ 0 b11111000, 0 b10010111
+#endif
+};
+#endif
+
+#ifdef ERASE
+const unsigned int num_bits_erase = 396; //PTJ: erase with TSYNC Enable and Disable
+const unsigned char erase[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x85,
+ 0xfd, 0xfc, 0x01, 0xf7, 0x10, 0x07, 0xdc, 0x00,
+ 0x7f, 0x7b, 0x80, 0x7d, 0xe0, 0x0b, 0xf7, 0xa0,
+ 0x1f, 0xd7, 0xa0, 0x1f, 0x7b, 0x04, 0x7d, 0xf0,
+ 0x01, 0xf7, 0xc9, 0x87, 0xdf, 0x48, 0x1f, 0x7f,
+ 0x89, 0x70
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000101,
+ 0 b11111101, 0 b11111100, 0 b00000001, 0 b11110111, 0 b00010000,
+ 0 b00000111, 0 b11011100, 0 b00000000,
+ 0 b01111111, 0 b01111011, 0 b10000000, 0 b01111101, 0 b11100000,
+ 0 b00001011, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b11011110, 0 b10100000, 0 b00011111, 0 b01111011,
+ 0 b00000100, 0 b01111101, 0 b11110000,
+ 0 b00000001, 0 b11110111, 0 b11001001, 0 b10000111, 0 b11011111,
+ 0 b01001000, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000
+#endif
+};
+#endif
+
+#ifdef SECURE
+const unsigned int num_bits_secure = 440; //PTJ: secure with TSYNC Enable and Disable
+const unsigned char secure[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf7, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf6, 0xa0,
+ 0x0f, 0xde, 0x80, 0x7f, 0x7a, 0x80, 0x7d, 0xec,
+ 0x01, 0xf7, 0x80, 0x27, 0xdf, 0x00, 0x1f, 0x7c,
+ 0xa0, 0x7d, 0xf4, 0x61, 0xf7, 0xf8, 0x97
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11110000,
+ 0 b00000111, 0 b11011100, 0 b01000000,
+ 0 b00011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00000001, 0 b11110110, 0 b10100000,
+ 0 b00001111, 0 b11011110, 0 b10000000, 0 b01111111, 0 b01111010,
+ 0 b10000000, 0 b01111101, 0 b11101100,
+ 0 b00000001, 0 b11110111, 0 b10000000, 0 b00100111, 0 b11011111,
+ 0 b00000000, 0 b00011111, 0 b01111100,
+ 0 b10100000, 0 b01111101, 0 b11110100, 0 b01100001, 0 b11110111,
+ 0 b11111000, 0 b10010111
+#endif
+};
+#endif
+
+#ifdef READ_SECURITY
+const unsigned int num_bits_ReadSecuritySetup = 88; //PTJ: READ-SECURITY-SETUP
+const unsigned char ReadSecuritySetup[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x60, 0x88, 0x7d, 0x84, 0x21,
+ 0xf7, 0xb8, 0x07
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01100000, 0 b10001000,
+ 0 b01111101, 0 b10000100, 0 b00100001,
+ 0 b11110111, 0 b10111000, 0 b00000111
+#endif
+};
+
+const unsigned int num_bits_read_security_pt1 = 78; //PTJ: This sends the beginning of the Read Supervisory command
+const unsigned char read_security_pt1[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x72, 0x87, 0x7d, 0xca, 0x01,
+ 0xf7, 0x28
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01110010, 0 b10000111,
+ 0 b01111101, 0 b11001010, 0 b00000001,
+ 0 b11110111, 0 b00101000
+#endif
+};
+
+const unsigned int num_bits_read_security_pt1_end = 25; //PTJ: this finishes the Address Low command and sends the Address High command
+const unsigned char read_security_pt1_end[] = {
+#ifdef HEX_DEFINE
+ 0xfb, 0x94, 0x03, 0x80
+#else
+ 0 b11111011, 0 b10010100, 0 b00000011, 0 b10000000
+#endif
+};
+
+const unsigned int num_bits_read_security_pt2 = 198; //PTJ: load the test queue with the op code for MOV 1,E5h register into Accumulator A
+const unsigned char read_security_pt2[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe0, 0x1f, 0x7a, 0x01, 0xfd, 0xea, 0x01,
+ 0xf7, 0xb0, 0x07, 0xdf, 0x0b, 0xbf, 0x7c, 0xf2,
+ 0xfd, 0xf4, 0x61, 0xf7, 0xb8, 0x87, 0xdf, 0xe2,
+ 0x5c
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111101, 0 b11101010, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b11011111, 0 b00001011,
+ 0 b10111111, 0 b01111100, 0 b11110010,
+ 0 b11111101, 0 b11110100, 0 b01100001, 0 b11110111, 0 b10111000,
+ 0 b10000111, 0 b11011111, 0 b11100010,
+ 0 b01011100
+#endif
+};
+
+const unsigned int num_bits_read_security_pt3 = 122; //PTJ:
+const unsigned char read_security_pt3[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe0, 0x1f, 0x7a, 0x01, 0xfd, 0xea, 0x01,
+ 0xf7, 0xb0, 0x07, 0xdf, 0x0a, 0x7f, 0x7c, 0xc0
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111101, 0 b11101010, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b11011111, 0 b00001010,
+ 0 b01111111, 0 b01111100, 0 b11000000
+#endif
+};
+
+const unsigned int num_bits_read_security_pt3_end = 47; //PTJ:
+const unsigned char read_security_pt3_end[] = {
+#ifdef HEX_DEFINE
+ 0xfb, 0xe8, 0xc3, 0xef, 0xf1, 0x2e
+#else
+ 0 b11111011, 0 b11101000, 0 b11000011, 0 b11101111, 0 b11110001,
+ 0 b00101110
+#endif
+};
+
+#endif
+
+// --------- CY8C20x66 Checksum Setup Vector ----------------------------------
+// ----------------------------------------------------------------------------
+#ifdef CHECKSUM_SETUP
+const unsigned int num_bits_checksum_setup = 418; //PTJ: Checksum with TSYNC Enable and Disable
+const unsigned char checksum_setup[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf4, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf7, 0xa0,
+ 0x1f, 0xde, 0xa0, 0x1f, 0x7b, 0x00, 0x7d, 0xe0,
+ 0x0f, 0xf7, 0xc0, 0x07, 0xdf, 0x28, 0x1f, 0x7d,
+ 0x18, 0x7d, 0xfe, 0x25, 0xc0
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111001, 0 b11110100, 0 b00000001, 0 b11110111, 0 b11110000,
+ 0 b00000111, 0 b11011100, 0 b01000000,
+ 0 b00011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b11011110, 0 b10100000, 0 b00011111, 0 b01111011,
+ 0 b00000000, 0 b01111101, 0 b11100000,
+ 0 b00001111, 0 b11110111, 0 b11000000, 0 b00000111, 0 b11011111,
+ 0 b00101000, 0 b00011111, 0 b01111101,
+ 0 b00011000, 0 b01111101, 0 b11111110, 0 b00100101, 0 b11000000
+#endif
+};
+#endif
+
+// --------- CY8C21x23, CY8C21x34 & CY8C27x43 Checksum Setup Vectors ----------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CHECKSUM_SETUP_21_27
+const unsigned int num_bits_checksum = 286;
+const unsigned char checksum_v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7B, 0x00, 0x79, 0xF0, 0x75,
+ 0xE7, 0xC8, 0x1F, 0xDE, 0xA0, 0x1F, 0x7A, 0x01,
+ 0xF9, 0xF7, 0x01, 0xF7, 0xC9, 0x87, 0xDF, 0x48,
+ 0x1E, 0x7D, 0x00, 0x7D, 0xE0, 0x0F, 0xF7, 0xC0,
+ 0x07, 0xDF, 0xE2, 0x5C
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111011, 0 b00000000,
+ 0 b01111001, 0 b11110000, 0 b01110101,
+ 0 b11100111, 0 b11001000, 0 b00011111, 0 b11011110, 0 b10100000,
+ 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11001001,
+ 0 b10000111, 0 b11011111, 0 b01001000,
+ 0 b00011110, 0 b01111101, 0 b00000000, 0 b01111101, 0 b11100000,
+ 0 b00001111, 0 b11110111, 0 b11000000,
+ 0 b00000111, 0 b11011111, 0 b11100010, 0 b01011100
+#endif
+};
+#endif
+
+// -------------- CY8C24x23 & CY8C24x23A Checksum Setup Vectors ---------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CHECKSUM_SETUP_24_24A
+const unsigned int num_bits_checksum = 286;
+const unsigned char checksum_v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7B, 0x00, 0x79, 0xF0, 0x75,
+ 0xE7, 0xC8, 0x1F, 0xDE, 0xA0, 0x1F, 0x7A, 0x01,
+ 0xF9, 0xF7, 0x01, 0xF7, 0xC9, 0x87, 0xDF, 0x48,
+ 0x1E, 0x7D, 0x20, 0x7D, 0xE0, 0x0F, 0xF7, 0xC0,
+ 0x07, 0xDF, 0xE2, 0x5C
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111011, 0 b00000000,
+ 0 b01111001, 0 b11110000, 0 b01110101,
+ 0 b11100111, 0 b11001000, 0 b00011111, 0 b11011110, 0 b10100000,
+ 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11001001,
+ 0 b10000111, 0 b11011111, 0 b01001000,
+ 0 b00011110, 0 b01111101, 0 b00100000, 0 b01111101, 0 b11100000,
+ 0 b00001111, 0 b11110111, 0 b11000000,
+ 0 b00000111, 0 b11011111, 0 b11100010, 0 b01011100
+#endif
+};
+#endif
+
+// -------------- CY8C24x94 & CY8C29x66 Checksum Setup Vectors ----------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef CHECKSUM_SETUP_24_29
+const unsigned int num_bits_checksum = 286;
+const unsigned char checksum_v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7B, 0x00, 0x79, 0xF0, 0x75,
+ 0xE7, 0xC8, 0x1F, 0xDE, 0xA0, 0x1F, 0x7A, 0x01,
+ 0xF9, 0xF6, 0x01, 0xF7, 0xC9, 0x87, 0xDF, 0x48,
+ 0x1E, 0x7D, 0x40, 0x7D, 0xE0, 0x0F, 0xF7, 0xC0,
+ 0x07, 0xDF, 0xE2, 0x5C
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111011, 0 b00000000,
+ 0 b01111001, 0 b11110000, 0 b01110101,
+ 0 b11100111, 0 b11001000, 0 b00011111, 0 b11011110, 0 b10100000,
+ 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111001, 0 b11110110, 0 b00000001, 0 b11110111, 0 b11001001,
+ 0 b10000111, 0 b11011111, 0 b01001000,
+ 0 b00011110, 0 b01111101, 0 b00100000, 0 b01111101, 0 b11100000,
+ 0 b00001111, 0 b11110111, 0 b11000000,
+ 0 b00000111, 0 b11011111, 0 b11100010, 0 b01011100
+#endif
+};
+#endif
+
+// ---- CY8C20x66 Program Block Vector ----------------------------------------
+//
+// ----------------------------------------------------------------------------
+#ifdef PROGRAM_AND_VERIFY
+const unsigned int num_bits_program_and_verify = 440; //KIMC, PTJ: length of program_block[], not including zero padding at end
+const unsigned char program_and_verify[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf7, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf6, 0xa0,
+ 0x0f, 0xde, 0x80, 0x7f, 0x7a, 0x80, 0x7d, 0xec,
+ 0x01, 0xf7, 0x80, 0x57, 0xdf, 0x00, 0x1f, 0x7c,
+ 0xa0, 0x7d, 0xf4, 0x61, 0xf7, 0xf8, 0x97
+#else
+ 0 b00011011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b00011110111, 0 b00000000, 0 b00011111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b00011111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11110000,
+ 0 b00000111, 0 b11011100, 0 b01000000,
+ 0 b00000011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00000001, 0 b11110110, 0 b10100000,
+ 0 b00000001111, 0 b11011110, 0 b10000000, 0 b01111111, 0 b01111010,
+ 0 b10000000, 0 b01111101, 0 b11101100,
+ 0 b00000000001, 0 b11110111, 0 b10000000, 0 b01010111, 0 b11011111,
+ 0 b00000000, 0 b00011111, 0 b01111100,
+ 0 b00010100000, 0 b01111101, 0 b11110100, 0 b01100001, 0 b11110111,
+ 0 b11111000, 0 b10010111
+#endif
+};
+#endif
+
+// ---- CY8C21xxx, CY8C24x23A, CY8C24x94 & CY8C29x66 Program Block Vectors ----
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef PROGRAM_BLOCK_21_24_29
+const unsigned int num_bits_program_block = 308;
+const unsigned char program_block[] = {
+#ifdef HEX_DEFINE
+ 0x9F, 0x8A, 0x9E, 0x7F, 0x2B, 0x7D, 0xEE, 0x01,
+ 0xF7, 0xB0, 0x07, 0x9F, 0x07, 0x5E, 0x7C, 0x81,
+ 0xFD, 0xEA, 0x01, 0xF7, 0xA0, 0x1F, 0x9F, 0x70,
+ 0x1F, 0x7C, 0x98, 0x7D, 0xF4, 0x81, 0xF7, 0x80,
+ 0x17, 0xDF, 0x00, 0x1F, 0x7F, 0x89, 0x70
+#else
+ 0 b10011111, 0 b10001010, 0 b10011110, 0 b01111111, 0 b00101011,
+ 0 b01111101, 0 b11101110, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111101, 0 b11101010, 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b10011111, 0 b01110000,
+ 0 b00011111, 0 b01111100, 0 b10011000, 0 b01111101, 0 b11110100,
+ 0 b10000001, 0 b11110111, 0 b10000000,
+ 0 b00010111, 0 b11011111, 0 b00000000, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000
+#endif
+};
+#endif
+
+// --------------------- CY8C27x43 Program Block Vectors-----------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+#ifdef PROGRAM_BLOCK_27
+const unsigned int num_bits_program_block = 308;
+
+const unsigned char program_block[] = {
+#ifdef HEX_DEFINE
+ 0x9F, 0x82, 0xBE, 0x7F, 0x2B, 0x7D, 0xEE, 0x01,
+ 0xF7, 0xB0, 0x07, 0x9F, 0x07, 0x5E, 0x7C, 0x81,
+ 0xFD, 0xEA, 0x01, 0xF7, 0xA0, 0x1F, 0x9F, 0x70,
+ 0x1F, 0x7C, 0x98, 0x7D, 0xF4, 0x81, 0xF7, 0x80,
+ 0x17, 0xDF, 0x00, 0x1F, 0x7F, 0x89, 0x70
+#else
+ 0 b10011111, 0 b10000010, 0 b10111110, 0 b01111111, 0 b00101011,
+ 0 b01111101, 0 b11101110, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111101, 0 b11101010, 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b10011111, 0 b01110000,
+ 0 b00011111, 0 b01111100, 0 b10011000, 0 b01111101, 0 b11110100,
+ 0 b10000001, 0 b11110111, 0 b10000000,
+ 0 b00010111, 0 b11011111, 0 b00000000, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000
+#endif
+};
+#endif
+
+// ----------------------------- General PSoC Vectors--------------------------
+// Modifying these tables is NOT recommendended. Doing so will all but
+// guarantee an ISSP error, unless updated vectors have been recommended or
+// provided by Cypress Semiconductor.
+// ----------------------------------------------------------------------------
+const unsigned int num_bits_init1 = 396;
+const unsigned char init1_v[] = {
+#ifdef HEX_DEFINE
+ 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0D, 0xEE, 0x01, 0xF7, 0xB0, 0x07, 0x9F, 0x07,
+ 0x5E, 0x7C, 0x81, 0xFD, 0xEA, 0x01, 0xF7, 0xA0,
+ 0x1F, 0x9F, 0x70, 0x1F, 0x7C, 0x98, 0x7D, 0xF4,
+ 0x81, 0xF7, 0x80, 0x4F, 0xDF, 0x00, 0x1F, 0x7F,
+ 0x89, 0x70
+#else
+ 0 b11001010, 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00000000, 0 b00000000, 0 b00000000,
+ 0 b00001101, 0 b11101110, 0 b00000001, 0 b11110111, 0 b10110000,
+ 0 b00000111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001, 0 b11111101, 0 b11101010,
+ 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b10011111, 0 b01110000, 0 b00011111, 0 b01111100,
+ 0 b10011000, 0 b01111101, 0 b11110100,
+ 0 b10000001, 0 b11110111, 0 b10000000, 0 b01001111, 0 b11011111,
+ 0 b00000000, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000
+#endif
+};
+
+const unsigned int num_bits_init2 = 286;
+const unsigned char init2_v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7B, 0x00, 0x79, 0xF0, 0x75,
+ 0xE7, 0xC8, 0x1F, 0xDE, 0xA0, 0x1F, 0x7A, 0x01,
+ 0xF9, 0xF7, 0x01, 0xF7, 0xC9, 0x87, 0xDF, 0x48,
+ 0x1E, 0x7D, 0x00, 0xFD, 0xE0, 0x0D, 0xF7, 0xC0,
+ 0x07, 0xDF, 0xE2, 0x5C
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111011, 0 b00000000,
+ 0 b01111001, 0 b11110000, 0 b01110101,
+ 0 b11100111, 0 b11001000, 0 b00011111, 0 b11011110, 0 b10100000,
+ 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11001001,
+ 0 b10000111, 0 b11011111, 0 b01001000,
+ 0 b00011110, 0 b01111101, 0 b00000000, 0 b11111101, 0 b11100000,
+ 0 b00001101, 0 b11110111, 0 b11000000,
+ 0 b00000111, 0 b11011111, 0 b11100010, 0 b01011100
+#endif
+};
+
+const unsigned int num_bits_init3_5v = 836;
+const unsigned char init3_5v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7A, 0x01, 0xFD, 0xEA, 0x01,
+ 0xF7, 0xB0, 0x47, 0xDF, 0x0A, 0x3F, 0x7C, 0xFE,
+ 0x7D, 0xF4, 0x61, 0xF7, 0xF8, 0x97, 0x00, 0x00,
+ 0x03, 0x7B, 0x80, 0x7D, 0xE8, 0x07, 0xF7, 0xA8,
+ 0x07, 0xDE, 0xC1, 0x1F, 0x7C, 0x30, 0x7D, 0xF3,
+ 0xD5, 0xF7, 0xD1, 0x87, 0xDE, 0xE2, 0x1F, 0x7F,
+ 0x89, 0x70, 0x00, 0x00, 0x37, 0xB8, 0x07, 0xDE,
+ 0x80, 0x7F, 0x7A, 0x80, 0x7D, 0xEC, 0x11, 0xF7,
+ 0xC2, 0x8F, 0xDF, 0x3F, 0xBF, 0x7D, 0x18, 0x7D,
+ 0xFE, 0x25, 0xC0, 0x00, 0x00, 0xDE, 0xE0, 0x1F,
+ 0x7A, 0x01, 0xFD, 0xEA, 0x01, 0xF7, 0xB0, 0x47,
+ 0xDF, 0x0C, 0x1F, 0x7C, 0xF4, 0x7D, 0xF4, 0x61,
+ 0xF7, 0xB8, 0x87, 0xDF, 0xE2, 0x5C, 0x00, 0x00,
+ 0x00
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111101, 0 b11101010, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b01000111, 0 b11011111, 0 b00001010,
+ 0 b00111111, 0 b01111100, 0 b11111110,
+ 0 b01111101, 0 b11110100, 0 b01100001, 0 b11110111, 0 b11111000,
+ 0 b10010111, 0 b00000000, 0 b00000000,
+ 0 b00000011, 0 b01111011, 0 b10000000, 0 b01111101, 0 b11101000,
+ 0 b00000111, 0 b11110111, 0 b10101000,
+ 0 b00000111, 0 b11011110, 0 b11000001, 0 b00011111, 0 b01111100,
+ 0 b00110000, 0 b01111101, 0 b11110011,
+ 0 b11010101, 0 b11110111, 0 b11010001, 0 b10000111, 0 b11011110,
+ 0 b11100010, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000, 0 b00000000, 0 b00000000, 0 b00110111,
+ 0 b10111000, 0 b00000111, 0 b11011110,
+ 0 b10000000, 0 b01111111, 0 b01111010, 0 b10000000, 0 b01111101,
+ 0 b11101100, 0 b00010001, 0 b11110111,
+ 0 b11000010, 0 b10001111, 0 b11011111, 0 b00111111, 0 b10111111,
+ 0 b01111101, 0 b00011000, 0 b01111101,
+ 0 b11111110, 0 b00100101, 0 b11000000, 0 b00000000, 0 b00000000,
+ 0 b11011110, 0 b11100000, 0 b00011111,
+ 0 b01111010, 0 b00000001, 0 b11111101, 0 b11101010, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b01000111,
+ 0 b11011111, 0 b00001100, 0 b00011111, 0 b01111100, 0 b11110100,
+ 0 b01111101, 0 b11110100, 0 b01100001,
+ 0 b11110111, 0 b10111000, 0 b10000111, 0 b11011111, 0 b11100010,
+ 0 b01011100, 0 b00000000, 0 b00000000,
+ 0 b00000000
+#endif
+};
+
+const unsigned int num_bits_init3_3v = 836;
+const unsigned char init3_3v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7A, 0x01, 0xFD, 0xEA, 0x01,
+ 0xF7, 0xB0, 0x47, 0xDF, 0x0A, 0x3F, 0x7C, 0xFC,
+ 0x7D, 0xF4, 0x61, 0xF7, 0xF8, 0x97, 0x00, 0x00,
+ 0x03, 0x7B, 0x80, 0x7D, 0xE8, 0x07, 0xF7, 0xA8,
+ 0x07, 0xDE, 0xC1, 0x1F, 0x7C, 0x30, 0x7D, 0xF3,
+ 0xD5, 0xF7, 0xD1, 0x87, 0xDE, 0xE2, 0x1F, 0x7F,
+ 0x89, 0x70, 0x00, 0x00, 0x37, 0xB8, 0x07, 0xDE,
+ 0x80, 0x7F, 0x7A, 0x80, 0x7D, 0xEC, 0x11, 0xF7,
+ 0xC2, 0x8F, 0xDF, 0x3F, 0x3F, 0x7D, 0x18, 0x7D,
+ 0xFE, 0x25, 0xC0, 0x00, 0x00, 0xDE, 0xE0, 0x1F,
+ 0x7A, 0x01, 0xFD, 0xEA, 0x01, 0xF7, 0xB0, 0x47,
+ 0xDF, 0x0C, 0x1F, 0x7C, 0xF4, 0x7D, 0xF4, 0x61,
+ 0xF7, 0xB8, 0x87, 0xDF, 0xE2, 0x5C, 0x00, 0x00,
+ 0x00
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111101, 0 b11101010, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b01000111, 0 b11011111, 0 b00001010,
+ 0 b00111111, 0 b01111100, 0 b11111100,
+ 0 b01111101, 0 b11110100, 0 b01100001, 0 b11110111, 0 b11111000,
+ 0 b10010111, 0 b00000000, 0 b00000000,
+ 0 b00000011, 0 b01111011, 0 b10000000, 0 b01111101, 0 b11101000,
+ 0 b00000111, 0 b11110111, 0 b10101000,
+ 0 b00000111, 0 b11011110, 0 b11000001, 0 b00011111, 0 b01111100,
+ 0 b00110000, 0 b01111101, 0 b11110011,
+ 0 b11010101, 0 b11110111, 0 b11010001, 0 b10000111, 0 b11011110,
+ 0 b11100010, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000, 0 b00000000, 0 b00000000, 0 b00110111,
+ 0 b10111000, 0 b00000111, 0 b11011110,
+ 0 b10000000, 0 b01111111, 0 b01111010, 0 b10000000, 0 b01111101,
+ 0 b11101100, 0 b00010001, 0 b11110111,
+ 0 b11000010, 0 b10001111, 0 b11011111, 0 b00111111, 0 b00111111,
+ 0 b01111101, 0 b00011000, 0 b01111101,
+ 0 b11111110, 0 b00100101, 0 b11000000, 0 b00000000, 0 b00000000,
+ 0 b11011110, 0 b11100000, 0 b00011111,
+ 0 b01111010, 0 b00000001, 0 b11111101, 0 b11101010, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b01000111,
+ 0 b11011111, 0 b00001100, 0 b00011111, 0 b01111100, 0 b11110100,
+ 0 b01111101, 0 b11110100, 0 b01100001,
+ 0 b11110111, 0 b10111000, 0 b10000111, 0 b11011111, 0 b11100010,
+ 0 b01011100, 0 b00000000, 0 b00000000,
+ 0 b00000000
+#endif
+};
+
+#if 0 //
+const unsigned int num_bits_id_setup = 330;
+const unsigned char id_setup_v[] = {
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01110000, 0 b00000001,
+ 0 b01111101, 0 b11101110, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111101, 0 b11101010, 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b10011111, 0 b01110000,
+ 0 b00011111, 0 b01111100, 0 b10011000, 0 b01111101, 0 b11110100,
+ 0 b10000001, 0 b11100111, 0 b11010000,
+ 0 b00000111, 0 b11011110, 0 b00000000, 0 b11011111, 0 b01111100,
+ 0 b00000000, 0 b01111101, 0 b11111110,
+ 0 b00100101, 0 b11000000
+};
+#endif
+#ifdef ID_SETUP_2
+const unsigned int num_bits_id_setup_2 = 418; //PTJ: id_setup_2 with TSYNC Disable (TSYNC enabled before with SendVector(tsync_enable....)
+const unsigned char id_setup_2[] = {
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf4, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf7, 0xa0,
+ 0x1f, 0xde, 0xa0, 0x1f, 0x7b, 0x00, 0x7d, 0xe0,
+ 0x0d, 0xf7, 0xc0, 0x07, 0xdf, 0x28, 0x1f, 0x7d,
+ 0x18, 0x7d, 0xfe, 0x25, 0xc0
+#else
+ 0 b11011110, 0 b11100010, 0 b00011111, 0 b01111111, 0 b00000010,
+ 0 b01111101, 0 b11000100, 0 b00001001,
+ 0 b11110111, 0 b00000000, 0 b00011111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111001, 0 b11110100, 0 b00000001, 0 b11110111, 0 b11110000,
+ 0 b00000111, 0 b11011100, 0 b01000000,
+ 0 b00011111, 0 b01110000, 0 b00000001, 0 b11111101, 0 b11101110,
+ 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b11011110, 0 b10100000, 0 b00011111, 0 b01111011,
+ 0 b00000000, 0 b01111101, 0 b11100000,
+ 0 b00001101, 0 b11110111, 0 b11000000, 0 b00000111, 0 b11011111,
+ 0 b00101000, 0 b00011111, 0 b01111101,
+ 0 b00011000, 0 b01111101, 0 b11111110, 0 b00100101, 0 b11000000
+#endif
+};
+#endif
+
+const unsigned int num_bits_erase_all = 308;
+const unsigned char erase_all_v[] = {
+#ifdef HEX_DEFINE
+ 0x9F, 0x82, 0xBE, 0x7F, 0x2B, 0x7D, 0xEE, 0x01,
+ 0xF7, 0xB0, 0x07, 0x9F, 0x07, 0x5E, 0x7C, 0x81,
+ 0xFD, 0xEA, 0x01, 0xF7, 0xA0, 0x1F, 0x9F, 0x70,
+ 0x1F, 0x7C, 0x98, 0x7D, 0xF4, 0x81, 0xF7, 0x80,
+ 0x2F, 0xDF, 0x00, 0x1F, 0x7F, 0x89, 0x70
+#else
+ 0 b10011111, 0 b10000010, 0 b10111110, 0 b01111111, 0 b00101011,
+ 0 b01111101, 0 b11101110, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111101, 0 b11101010, 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b10011111, 0 b01110000,
+ 0 b00011111, 0 b01111100, 0 b10011000, 0 b01111101, 0 b11110100,
+ 0 b10000001, 0 b11110111, 0 b10000000,
+ 0 b00101111, 0 b11011111, 0 b00000000, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000
+#endif
+};
+
+const unsigned char read_id_v[] = {
+#ifdef HEX_DEFINE
+ 0xBF, 0x00, 0xDF, 0x90, 0x00, 0xFE, 0x60, 0xFF, 0x00
+#else
+ 0 b10111111, 0 b00000000, 0 b11011111, 0 b10010000, 0 b00000000,
+ 0 b11111110, 0 b0110000, 0 b11111111, 0 b00000000
+#endif
+};
+
+const unsigned char Switch_Bank1[] = //PTJ: use this to switch between register banks
+{
+#ifdef HEX_DEFINE
+ 0xde, 0xe2, 0x1c
+#else
+ 0 b11011110, 0 b11100010, 0 b00011100
+#endif
+};
+
+const unsigned char Switch_Bank0[] = //PTJ: use this to switch between register banks
+{
+#ifdef HEX_DEFINE
+ 0xde, 0xe0, 0x1c
+#else
+ 0 b11011110, 0 b11100000, 0 b00011100
+#endif
+};
+
+const unsigned char read_IMOtrim[] = //PTJ: read the 1,E8h register after id__setup_1 to see if the cal data was loaded properly.
+{
+#ifdef HEX_DEFINE
+ 0xfd, 0x00, 0x10
+#else
+ 0 b11111101, 0 b00000000, 0 b00010000
+#endif
+};
+
+const unsigned char read_SPCtrim[] = //PTJ: read the 1,E7h register after id__setup_1 to see if the cal data was loaded properly.
+{
+#ifdef HEX_DEFINE
+ 0xfc, 0xe0, 0x10
+#else
+ 0 b11111100, 0 b11100000, 0 b00010000
+#endif
+};
+
+const unsigned char read_VBGfinetrim[] = //PTJ: read the 1,D7h register after id__setup_1 to see if the cal data was loaded properly.
+{
+#ifdef HEX_DEFINE
+ 0xfa, 0xe0, 0x08
+#else
+ 0 b11111010, 0 b11100000, 0 b0001000
+#endif
+};
+
+const unsigned char read_reg_end = 0x80; //PTJ: this is the final '1' after a MR command
+
+const unsigned char write_byte_start = 0x90; //PTJ: this is set to SRAM 0x80
+const unsigned char write_byte_end = 0xE0;
+
+const unsigned char set_block_number[] = { 0x9F, 0x40, 0xE0 };
+
+const unsigned char set_block_number_end = 0xE0;
+#ifdef MULTI_BANK
+const unsigned char set_bank_number[] = { 0xDE, 0xE2, 0x1F, 0x7D, 0x00 };
+const unsigned char set_bank_number_end[] = { 0xFB, 0xDC, 0x03, 0x80 };
+#endif
+
+// const unsigned char num_bits_wait_and_poll_end = 40; //PTJ 308: commented out
+const unsigned char num_bits_wait_and_poll_end = 30; //PTJ 308: added to match spec
+const unsigned char wait_and_poll_end[] = {
+// 0x00, 0x00, 0x00, 0x00, 0x00 //PTJ 308: commented out
+ 0x00, 0x00, 0x00, 0x00 //PTJ 308: added to match spec
+}; // forty '0's per the spec
+
+const unsigned char read_checksum_v[] = {
+#ifdef HEX_DEFINE
+ 0xBF, 0x20, 0xDF, 0x80, 0x80
+#else
+ 0 b10111111, 0 b00100000, 0 b11011111, 0 b10000000, 0 b10000000
+#endif
+};
+
+const unsigned char read_byte_v[] = {
+#ifdef HEX_DEFINE
+ 0xB0, 0x80
+#else
+ 0 b10110000, 0 b10000000
+#endif
+};
+
+const unsigned int num_bits_verify_setup = 264;
+const unsigned char verify_setup_v[] = {
+#ifdef HEX_DEFINE
+ 0xDE, 0xE0, 0x1F, 0x7B, 0x00, 0x79, 0xF0, 0x75,
+ 0xE7, 0xC8, 0x1F, 0xDE, 0xA0, 0x1F, 0x7A, 0x01,
+ 0xF9, 0xF7, 0x01, 0xF7, 0xC9, 0x87, 0xDF, 0x48,
+ 0x1F, 0x78, 0x00, 0xFD, 0xF0, 0x01, 0xF7, 0xF8,
+ 0x97
+#else
+ 0 b11011110, 0 b11100000, 0 b00011111, 0 b01111011, 0 b00000000,
+ 0 b01111001, 0 b11110000, 0 b01110101,
+ 0 b11100111, 0 b11001000, 0 b00011111, 0 b11011110, 0 b10100000,
+ 0 b00011111, 0 b01111010, 0 b00000001,
+ 0 b11111001, 0 b11110111, 0 b00000001, 0 b11110111, 0 b11001001,
+ 0 b10000111, 0 b11011111, 0 b01001000,
+ 0 b00011111, 0 b01111000, 0 b00000000, 0 b11111101, 0 b11110000,
+ 0 b00000001, 0 b11110111, 0 b11111000,
+ 0 b10010111
+#endif
+};
+
+const unsigned int num_bits_security = 308;
+const unsigned char security_v[] = {
+#ifdef HEX_DEFINE
+ 0x9F, 0x8A, 0x9E, 0x7F, 0x2B, 0x7D, 0xEE, 0x01,
+ 0xF7, 0xB0, 0x07, 0x9F, 0x07, 0x5E, 0x7C, 0x81,
+ 0xFD, 0xEA, 0x01, 0xF7, 0xA0, 0x1F, 0x9F, 0x70,
+ 0x1F, 0x7C, 0x98, 0x7D, 0xF4, 0x81, 0xF7, 0x80,
+ 0x27, 0xDF, 0x00, 0x1F, 0x7F, 0x89, 0x70
+#else
+ 0 b10011111, 0 b10001010, 0 b10011110, 0 b01111111, 0 b00101011,
+ 0 b01111101, 0 b11101110, 0 b00000001,
+ 0 b11110111, 0 b10110000, 0 b00000111, 0 b10011111, 0 b00000111,
+ 0 b01011110, 0 b01111100, 0 b10000001,
+ 0 b11111101, 0 b11101010, 0 b00000001, 0 b11110111, 0 b10100000,
+ 0 b00011111, 0 b10011111, 0 b01110000,
+ 0 b00011111, 0 b01111100, 0 b10011000, 0 b01111101, 0 b11110100,
+ 0 b10000001, 0 b11110111, 0 b10000000,
+ 0 b00100111, 0 b11011111, 0 b00000000, 0 b00011111, 0 b01111111,
+ 0 b10001001, 0 b01110000
+#endif
+};
+
+#endif //(INC_ISSP_VECTORS)
+#endif //(PROJECT_REV_)
+//end of file ISSP_Vectors.h
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_M0.h b/drivers/input/keyboard/cypressbln/touchkey_fw_M0.h
new file mode 100644
index 0000000..c712b5e
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_M0.h
@@ -0,0 +1,747 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x00, 0x68,
+ 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x04, 0xce, 0x7e, 0x7e, 0x30,
+ 0x30, 0x30, 0x7d, 0x06, 0x1b, 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30,
+ 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x40, 0x71, 0x10, 0x62, 0xe3, 0x06, 0x70,
+ 0xef, 0x62, 0xe3, 0x38, 0x50, 0x80, 0x4e, 0x62, 0xe3, 0x38, 0x5d,
+ 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55, 0xfa, 0x01, 0x40, 0x4f, 0x5b,
+ 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a, 0x50, 0x06, 0x00, 0x40,
+ 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8, 0x70, 0xef, 0x18, 0x60,
+ 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00, 0x71, 0x10, 0x62, 0xe0,
+ 0x1a, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x71, 0x10, 0x41, 0xe1, 0xfe,
+ 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1, 0x03, 0x50, 0x80, 0x4e,
+ 0x62, 0xd3, 0x03, 0x62, 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4,
+ 0x00, 0x71, 0xc0, 0x7c, 0x03, 0x3b, 0x62, 0xd0, 0x00, 0x50, 0x01,
+ 0x57, 0xe2, 0x08, 0x28, 0x53, 0x58, 0x18, 0x75, 0x09, 0x00, 0x28,
+ 0x4b, 0x51, 0x58, 0x80, 0x04, 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00,
+ 0x08, 0x28, 0x60, 0xd5, 0x74, 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00,
+ 0x08, 0x28, 0x53, 0x58, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xa0,
+ 0x1c, 0x53, 0x57, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x3f, 0x58,
+ 0x47, 0x58, 0xff, 0xb0, 0x06, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x18,
+ 0x7a, 0x57, 0xbf, 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09, 0x00, 0x08,
+ 0x28, 0x53, 0x57, 0x50, 0x00, 0x3f, 0x58, 0x47, 0x58, 0xff, 0xb0,
+ 0x08, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x57, 0xbf,
+ 0xef, 0x18, 0x8f, 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71,
+ 0x10, 0x62, 0xe0, 0x1a, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x18,
+ 0x88, 0x8f, 0xff, 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x01, 0x99, 0x03, 0x33, 0x06,
+ 0x66, 0x0c, 0xcc, 0x19, 0x99, 0x33, 0x33, 0x66, 0x66, 0xcc, 0xcc,
+ 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, 0x0b, 0xff, 0x18, 0x00, 0x2f,
+ 0xff, 0x5f, 0xff, 0xbf, 0xff, 0x01, 0x66, 0x02, 0xcc, 0x05, 0x99,
+ 0x0b, 0x32, 0x16, 0x66, 0x2c, 0xcc, 0x59, 0x98, 0xb3, 0x32, 0x01,
+ 0x4d, 0x02, 0x9a, 0x05, 0x33, 0x0a, 0x66, 0x14, 0xcd, 0x29, 0x99,
+ 0x53, 0x33, 0xa6, 0x66, 0x01, 0x33, 0x02, 0x66, 0x04, 0xcc, 0x09,
+ 0x99, 0x13, 0x33, 0x26, 0x65, 0x4c, 0xcc, 0x99, 0x99, 0x01, 0x19,
+ 0x02, 0x33, 0x04, 0x66, 0x08, 0xcc, 0x11, 0x99, 0x25, 0x26, 0x46,
+ 0x65, 0x8c, 0xcc, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00,
+ 0x0f, 0xff, 0x20, 0x00, 0x3f, 0xff, 0x7f, 0xff, 0x1a, 0xf5, 0x70,
+ 0xef, 0x62, 0x61, 0x00, 0x62, 0xfd, 0x00, 0x62, 0xcd, 0x00, 0x62,
+ 0xce, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x62, 0xa0, 0x00,
+ 0x62, 0xa1, 0x80, 0x62, 0xa2, 0xc0, 0x62, 0xa3, 0x0c, 0x62, 0xa8,
+ 0x00, 0x62, 0xa6, 0x00, 0x62, 0xa7, 0x00, 0x62, 0x7c, 0x33, 0x62,
+ 0x7a, 0x00, 0x62, 0x7b, 0x00, 0x62, 0x79, 0x00, 0x62, 0x36, 0x00,
+ 0x62, 0x37, 0x00, 0x62, 0x38, 0x00, 0x62, 0x39, 0x00, 0x62, 0x3a,
+ 0x00, 0x62, 0x3b, 0x00, 0x62, 0x3c, 0x00, 0x62, 0x3d, 0x00, 0x62,
+ 0x3e, 0x00, 0x62, 0x3f, 0x00, 0x62, 0x40, 0x00, 0x62, 0x41, 0x00,
+ 0x62, 0x42, 0x00, 0x62, 0x43, 0x00, 0x62, 0x44, 0x00, 0x62, 0x45,
+ 0x00, 0x62, 0x46, 0x00, 0x62, 0x47, 0x00, 0x62, 0x48, 0x00, 0x62,
+ 0x49, 0x00, 0x62, 0x4a, 0x00, 0x62, 0x4b, 0x00, 0x62, 0x4c, 0x00,
+ 0x62, 0x4d, 0x00, 0x62, 0x4e, 0x00, 0x62, 0x4f, 0x00, 0x62, 0xca,
+ 0x20, 0x62, 0xd6, 0x44, 0x62, 0xcf, 0x00, 0x62, 0xcb, 0x00, 0x62,
+ 0xc8, 0x00, 0x62, 0xcc, 0x00, 0x62, 0xc9, 0x00, 0x62, 0xd7, 0x00,
+ 0x62, 0xa9, 0x00, 0x62, 0x2b, 0x00, 0x62, 0xb0, 0x00, 0x62, 0xb3,
+ 0x02, 0x62, 0xb6, 0x00, 0x62, 0xb2, 0x00, 0x62, 0xb5, 0x00, 0x62,
+ 0xb8, 0x00, 0x62, 0xb1, 0x00, 0x62, 0xb4, 0x00, 0x62, 0xb7, 0x00,
+ 0x62, 0x33, 0x00, 0x62, 0x34, 0x00, 0x62, 0x35, 0x00, 0x71, 0x10,
+ 0x62, 0x54, 0x00, 0x62, 0x55, 0x00, 0x62, 0x56, 0x00, 0x62, 0x57,
+ 0x00, 0x62, 0x58, 0x00, 0x62, 0x59, 0x00, 0x62, 0x5a, 0x00, 0x62,
+ 0x5b, 0x00, 0x62, 0xdc, 0x00, 0x62, 0xe2, 0x00, 0x62, 0xdd, 0x00,
+ 0x62, 0xd8, 0x02, 0x62, 0xd9, 0x00, 0x62, 0xda, 0x00, 0x62, 0xdb,
+ 0x00, 0x62, 0xdf, 0x00, 0x62, 0x29, 0x00, 0x62, 0x30, 0x00, 0x62,
+ 0xbd, 0x00, 0x70, 0xef, 0x70, 0xef, 0x62, 0x00, 0x08, 0x71, 0x10,
+ 0x62, 0x00, 0x08, 0x62, 0x01, 0x92, 0x70, 0xef, 0x62, 0x04, 0x17,
+ 0x71, 0x10, 0x62, 0x04, 0x14, 0x62, 0x05, 0xbc, 0x70, 0xef, 0x62,
+ 0x08, 0x00, 0x71, 0x10, 0x62, 0x08, 0x00, 0x62, 0x09, 0x28, 0x70,
+ 0xef, 0x62, 0x0c, 0x00, 0x71, 0x10, 0x62, 0x0c, 0x00, 0x62, 0x0d,
+ 0x00, 0x70, 0xef, 0x62, 0x10, 0x00, 0x71, 0x10, 0x62, 0x10, 0x00,
+ 0x62, 0x11, 0x00, 0x70, 0xef, 0x62, 0x01, 0x00, 0x62, 0x05, 0x00,
+ 0x62, 0x09, 0x00, 0x62, 0x0d, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef,
+ 0x7f, 0x55, 0x02, 0x08, 0x55, 0x03, 0x17, 0x55, 0x04, 0x00, 0x7c,
+ 0x03, 0x48, 0x7f, 0x7c, 0x01, 0xe4, 0x70, 0xef, 0x7f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x62, 0xd0, 0x00, 0x53, 0x00, 0x71, 0x10, 0x5d,
+ 0xe0, 0x08, 0x21, 0xf8, 0x29, 0x00, 0x70, 0xfe, 0x60, 0xe0, 0x70,
+ 0xef, 0x4b, 0x4b, 0x4b, 0x4b, 0x51, 0x02, 0x21, 0xf7, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80,
+ 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21,
+ 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00,
+ 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60,
+ 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08,
+ 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80,
+ 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05,
+ 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e,
+ 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01,
+ 0x60, 0x00, 0x47, 0x00, 0x00, 0x49, 0x01, 0x00, 0x29, 0x08, 0x60,
+ 0x00, 0x57, 0x01, 0x79, 0xbf, 0xfe, 0x18, 0x71, 0x10, 0x60, 0xe0,
+ 0x70, 0xef, 0x71, 0x01, 0x7f, 0x08, 0x67, 0x67, 0x67, 0x67, 0x21,
+ 0x0f, 0xff, 0x40, 0x9f, 0x4e, 0x18, 0x21, 0x0f, 0xff, 0x39, 0x9f,
+ 0x47, 0x7f, 0x08, 0x10, 0x28, 0xa0, 0x0b, 0x9f, 0x3f, 0x20, 0x18,
+ 0x75, 0xdf, 0xf5, 0x74, 0x8f, 0xf2, 0x38, 0xfe, 0x7f, 0x52, 0x00,
+ 0xa0, 0x08, 0x10, 0x9f, 0x2d, 0x20, 0x75, 0x8f, 0xf6, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x50, 0x0d, 0x9f, 0x20, 0x50, 0x0a, 0x9f, 0x1c,
+ 0x7f, 0x70, 0xbf, 0x62, 0xd3, 0x03, 0x4f, 0x52, 0xfb, 0xa0, 0x15,
+ 0x7b, 0xfb, 0x52, 0xfc, 0x59, 0xfd, 0x60, 0xd3, 0x52, 0x00, 0x9f,
+ 0x05, 0x4f, 0x62, 0xd3, 0x03, 0x77, 0xfd, 0x8f, 0xe9, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x3d, 0xfa, 0x00, 0xb0, 0x06, 0x3d, 0xfb, 0x00,
+ 0xa0, 0x18, 0x10, 0x52, 0xfc, 0x59, 0xfd, 0x28, 0x9e, 0xe6, 0x20,
+ 0x07, 0xfd, 0x01, 0x0f, 0xfc, 0x00, 0x17, 0xfb, 0x01, 0x1f, 0xfa,
+ 0x00, 0x8f, 0xe0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62,
+ 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xfb, 0x80, 0x04,
+ 0x2e, 0x03, 0x04, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f, 0x71, 0xc0,
+ 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50,
+ 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xef,
+ 0x80, 0x04, 0x2e, 0x03, 0x10, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x10, 0x70,
+ 0x3f, 0x71, 0x80, 0x5d, 0xd3, 0x08, 0x5d, 0xd0, 0x08, 0x62, 0xd0,
+ 0x00, 0x51, 0x08, 0x60, 0xd3, 0x2e, 0x05, 0x80, 0x49, 0xd7, 0x08,
+ 0xa0, 0x09, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x00, 0x80, 0x08, 0x49,
+ 0xd7, 0x20, 0xa0, 0x03, 0x80, 0xa6, 0x51, 0x05, 0x21, 0x0e, 0xe0,
+ 0x01, 0x80, 0x11, 0x80, 0x67, 0x80, 0x79, 0x80, 0x47, 0x80, 0x96,
+ 0x80, 0x94, 0x80, 0x92, 0x80, 0x90, 0x80, 0x97, 0x5d, 0xd8, 0x21,
+ 0xfe, 0x39, 0x40, 0xa0, 0x06, 0x62, 0xd7, 0x00, 0x80, 0x8a, 0x49,
+ 0xd8, 0x01, 0xb0, 0x0f, 0x55, 0x0c, 0x02, 0x26, 0x05, 0xf0, 0x2e,
+ 0x05, 0x02, 0x62, 0xd7, 0x10, 0x80, 0x77, 0x55, 0x0c, 0x01, 0x26,
+ 0x05, 0xf0, 0x2e, 0x05, 0x06, 0x5f, 0x07, 0x06, 0x51, 0x09, 0x02,
+ 0x07, 0x5c, 0x52, 0x00, 0x60, 0xd8, 0x76, 0x07, 0x62, 0xd7, 0x14,
+ 0x80, 0x5b, 0x51, 0x0a, 0x78, 0x3a, 0x07, 0xc0, 0x0f, 0x51, 0x09,
+ 0x02, 0x07, 0x5c, 0x52, 0x00, 0x60, 0xd8, 0x76, 0x07, 0x2e, 0x05,
+ 0x20, 0x60, 0xd8, 0x62, 0xd7, 0x04, 0x80, 0x3f, 0x5d, 0xd8, 0x3a,
+ 0x0a, 0xd0, 0x2b, 0xa0, 0x29, 0x53, 0x07, 0x53, 0x06, 0x26, 0x05,
+ 0xf0, 0x2e, 0x05, 0x04, 0x80, 0x18, 0x51, 0x0b, 0x78, 0x3a, 0x07,
+ 0xc0, 0x16, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x5d, 0xd8, 0x54, 0x00,
+ 0x2e, 0x05, 0x10, 0x76, 0x07, 0x80, 0x01, 0x62, 0xd7, 0x10, 0x80,
+ 0x0f, 0x62, 0xd7, 0x00, 0x80, 0x0a, 0x26, 0x05, 0xf0, 0x2e, 0x05,
+ 0x00, 0x55, 0x0c, 0x00, 0x18, 0x60, 0xd0, 0x18, 0x60, 0xd3, 0x20,
+ 0x18, 0x7e, 0x62, 0xd0, 0x00, 0x71, 0x10, 0x41, 0x04, 0xfc, 0x43,
+ 0x05, 0x03, 0x70, 0xef, 0x26, 0x03, 0xfc, 0x51, 0x03, 0x60, 0x04,
+ 0x55, 0x0c, 0x00, 0x90, 0x28, 0x90, 0x2d, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x50, 0x00, 0x53, 0x06, 0x71, 0x10, 0x43, 0x04, 0x03, 0x43,
+ 0x05, 0x03, 0x70, 0xef, 0x2e, 0x03, 0x03, 0x51, 0x03, 0x60, 0x04,
+ 0x7f, 0x62, 0xd0, 0x00, 0x51, 0x05, 0x21, 0xb0, 0x26, 0x05, 0x4f,
+ 0x7f, 0x41, 0xe0, 0x7f, 0x43, 0xe0, 0x80, 0x7f, 0x43, 0xd6, 0x31,
+ 0x7f, 0x41, 0xe0, 0x7f, 0x41, 0xd6, 0xfe, 0x7f, 0x62, 0xd0, 0x00,
+ 0x4f, 0x52, 0xfd, 0x53, 0x0a, 0x52, 0xfc, 0x53, 0x0b, 0x52, 0xfb,
+ 0x53, 0x09, 0x52, 0xfa, 0x53, 0x08, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x08, 0x5d, 0xa4, 0x04, 0x1b, 0x5d, 0xa5, 0x0c, 0x1a, 0x55, 0x1c,
+ 0x01, 0x18, 0x7e, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x53,
+ 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x8c, 0x62, 0xd3, 0x00,
+ 0x13, 0x7a, 0x62, 0xd3, 0x00, 0x54, 0x7e, 0x62, 0xd3, 0x00, 0x52,
+ 0x8b, 0x62, 0xd3, 0x00, 0x1b, 0x79, 0x62, 0xd3, 0x00, 0x54, 0x7d,
+ 0x48, 0x7d, 0x80, 0xb0, 0x33, 0x3d, 0x7d, 0x00, 0xb0, 0x7b, 0x51,
+ 0x0d, 0x3b, 0x7e, 0xc0, 0x75, 0x52, 0x7e, 0x58, 0x1e, 0x01, 0x00,
+ 0x6d, 0x62, 0xd3, 0x00, 0x05, 0x40, 0xc0, 0x09, 0x51, 0x0f, 0x3b,
+ 0x40, 0xd0, 0x12, 0xa0, 0x10, 0x56, 0x40, 0x00, 0x5b, 0x64, 0x5c,
+ 0x62, 0xd3, 0x00, 0x07, 0x7a, 0x01, 0x0f, 0x79, 0x00, 0x80, 0x41,
+ 0x3d, 0x7d, 0xff, 0xb0, 0x09, 0x50, 0xff, 0x12, 0x0e, 0x3b, 0x7e,
+ 0xc0, 0x20, 0x62, 0xd3, 0x00, 0x56, 0x7e, 0x00, 0x56, 0x7d, 0x00,
+ 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x47, 0x78, 0xd0, 0x03,
+ 0x50, 0x00, 0x54, 0x47, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c,
+ 0x62, 0xd3, 0x00, 0x52, 0x8c, 0x62, 0xd3, 0x00, 0x54, 0x7a, 0x62,
+ 0xd3, 0x00, 0x52, 0x8b, 0x62, 0xd3, 0x00, 0x54, 0x79, 0x51, 0x1e,
+ 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x56, 0x7e, 0x00, 0x56, 0x7d, 0x00,
+ 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x12, 0x54, 0x47, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf,
+ 0x08, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x42, 0x53, 0x19, 0x55, 0x18,
+ 0x00, 0x18, 0x08, 0x90, 0x7e, 0x62, 0xd3, 0x00, 0x23, 0x44, 0xb0,
+ 0x2c, 0x51, 0x10, 0x04, 0x19, 0x0e, 0x18, 0x00, 0x18, 0x64, 0x5c,
+ 0x62, 0xd3, 0x00, 0x52, 0x7e, 0x12, 0x19, 0x52, 0x7d, 0x1a, 0x18,
+ 0xc0, 0x39, 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x45, 0x78,
+ 0x54, 0x45, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x3e, 0x80, 0x18,
+ 0x51, 0x10, 0x14, 0x19, 0x1e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x52, 0x7e, 0x12, 0x19, 0x52, 0x7d, 0x1a, 0x18, 0xc0,
+ 0x0e, 0x5b, 0x67, 0x90, 0x31, 0x62, 0xd3, 0x00, 0x2d, 0x44, 0x50,
+ 0x01, 0x80, 0x24, 0x5b, 0x67, 0x08, 0x90, 0x23, 0x73, 0x62, 0xd3,
+ 0x00, 0x25, 0x44, 0x62, 0xd3, 0x00, 0x20, 0x51, 0x11, 0x54, 0x45,
+ 0x50, 0x00, 0x80, 0x0d, 0x5b, 0x67, 0x90, 0x0d, 0x73, 0x62, 0xd3,
+ 0x00, 0x25, 0x44, 0x50, 0x00, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08,
+ 0x67, 0x67, 0x67, 0x5c, 0x18, 0x21, 0x07, 0xf0, 0x01, 0x7f, 0x01,
+ 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x70, 0xbf, 0x70, 0xbf,
+ 0x62, 0xd3, 0x00, 0x50, 0x02, 0x78, 0x08, 0x5c, 0x56, 0x42, 0x19,
+ 0x18, 0x78, 0xdf, 0xf8, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x91,
+ 0xb2, 0x70, 0xbf, 0x18, 0x08, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52,
+ 0x8c, 0x62, 0xd3, 0x00, 0x54, 0x7a, 0x62, 0xd3, 0x00, 0x52, 0x8b,
+ 0x62, 0xd3, 0x00, 0x54, 0x79, 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x14, 0x00, 0x50, 0x02,
+ 0x78, 0x08, 0x9f, 0x0e, 0x39, 0x01, 0xb0, 0x04, 0x55, 0x14, 0x01,
+ 0x18, 0x78, 0xdf, 0xf3, 0x51, 0x14, 0x7f, 0x50, 0x02, 0x78, 0x08,
+ 0x9e, 0x3e, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x98, 0x90, 0x91, 0x92,
+ 0x93, 0x94, 0x95, 0x96, 0x97, 0xd8, 0xd9, 0xda, 0xdb, 0xdf, 0x00,
+ 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x70, 0xbf, 0x62,
+ 0xd0, 0x00, 0x62, 0xd3, 0x00, 0x57, 0x00, 0x56, 0x44, 0x00, 0x79,
+ 0xdf, 0xfb, 0x62, 0xd3, 0x00, 0x57, 0x01, 0x50, 0x03, 0x54, 0x45,
+ 0x79, 0xdf, 0xfc, 0x62, 0xd3, 0x00, 0x50, 0x14, 0x57, 0x01, 0x54,
+ 0x47, 0x79, 0xdf, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x55, 0x0d, 0x14,
+ 0x55, 0x0e, 0x05, 0x55, 0x0f, 0x14, 0x55, 0x10, 0x01, 0x55, 0x11,
+ 0x03, 0x55, 0x12, 0x14, 0x55, 0x22, 0x04, 0x55, 0x1f, 0x14, 0x43,
+ 0x61, 0x0d, 0x57, 0x00, 0x50, 0x02, 0x90, 0xae, 0x50, 0x04, 0xff,
+ 0x98, 0x29, 0x00, 0x60, 0xa9, 0x62, 0xa0, 0x08, 0x43, 0xa2, 0x04,
+ 0x62, 0xa3, 0x70, 0x43, 0x7a, 0x01, 0x43, 0xaa, 0x02, 0x43, 0xdf,
+ 0x01, 0x50, 0x01, 0x57, 0x09, 0x90, 0x20, 0x90, 0x55, 0x57, 0x01,
+ 0x50, 0xb3, 0x91, 0x5d, 0x50, 0x01, 0x57, 0x0e, 0x90, 0x12, 0x90,
+ 0x47, 0x7f, 0x53, 0x22, 0xff, 0x67, 0x29, 0x00, 0x60, 0xa9, 0x51,
+ 0x21, 0x58, 0x20, 0x90, 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21, 0x03,
+ 0x53, 0x21, 0x64, 0x64, 0x64, 0x64, 0x64, 0x29, 0x80, 0x60, 0xa1,
+ 0x5b, 0x78, 0x21, 0x0f, 0x29, 0x08, 0x74, 0x53, 0x20, 0x12, 0x22,
+ 0x02, 0x21, 0x5c, 0x50, 0x00, 0x53, 0x1d, 0x53, 0x23, 0x29, 0x01,
+ 0x79, 0xa0, 0x08, 0x64, 0x6b, 0x1d, 0x6b, 0x23, 0x8f, 0xf5, 0x60,
+ 0xb5, 0x51, 0x1d, 0x60, 0xb4, 0x7f, 0x50, 0x02, 0x78, 0x08, 0x90,
+ 0x28, 0x90, 0x5a, 0x18, 0x78, 0xdf, 0xf8, 0x7f, 0x41, 0xdf, 0xfe,
+ 0x71, 0x10, 0x41, 0xd8, 0xfd, 0x70, 0xef, 0x41, 0x61, 0xf3, 0x41,
+ 0xa2, 0xfb, 0x41, 0xa0, 0xf7, 0x62, 0xa3, 0x00, 0x62, 0xa9, 0x00,
+ 0x41, 0xaa, 0xfd, 0x7f, 0x02, 0x20, 0x02, 0x08, 0x64, 0x5c, 0xff,
+ 0xf8, 0x4b, 0x74, 0xff, 0xf4, 0x7f, 0x62, 0xd0, 0x00, 0x53, 0x1d,
+ 0x10, 0x5b, 0x64, 0x64, 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x2a, 0x1d,
+ 0x61, 0x01, 0x36, 0x1d, 0xff, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00,
+ 0x36, 0x1d, 0xff, 0x18, 0xfe, 0xd6, 0x5c, 0x5e, 0x00, 0x2a, 0x1d,
+ 0x61, 0x00, 0x70, 0xef, 0x7f, 0x62, 0xd0, 0x00, 0x10, 0x73, 0x53,
+ 0x1d, 0x71, 0x10, 0x5b, 0xfe, 0xc0, 0x5c, 0x5e, 0x00, 0x22, 0x1d,
+ 0x61, 0x00, 0x70, 0xef, 0x18, 0x64, 0x64, 0x5c, 0x71, 0x10, 0x5e,
+ 0x01, 0x22, 0x1d, 0x61, 0x01, 0x36, 0x1d, 0xff, 0x5e, 0x00, 0x2a,
+ 0x1d, 0x61, 0x00, 0x70, 0xef, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00,
+ 0x53, 0x1e, 0x50, 0x00, 0x53, 0x1a, 0x53, 0x1b, 0x51, 0x1e, 0x5c,
+ 0x62, 0xd3, 0x00, 0x52, 0x24, 0x53, 0x1f, 0x43, 0xa0, 0x01, 0x51,
+ 0x1f, 0x60, 0xfd, 0x41, 0xa3, 0xdf, 0x51, 0x1e, 0x9f, 0x7a, 0x9f,
+ 0x81, 0x58, 0x23, 0x55, 0x1c, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4,
+ 0x00, 0x43, 0xb3, 0x01, 0x51, 0x1c, 0xaf, 0xfd, 0x79, 0xdf, 0xee,
+ 0x51, 0x1e, 0x9f, 0x5f, 0x9f, 0x91, 0x43, 0xa3, 0x20, 0x41, 0xa0,
+ 0xfe, 0x62, 0xfd, 0x00, 0x50, 0xff, 0x4c, 0x1b, 0x14, 0x1b, 0x51,
+ 0x20, 0x11, 0x08, 0xfe, 0x4d, 0x4c, 0x1a, 0x1c, 0x1a, 0xd0, 0x07,
+ 0x55, 0x1a, 0x00, 0x55, 0x1b, 0x00, 0x51, 0x1e, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x51, 0x1b, 0x54, 0x8c, 0x51, 0x1a, 0x54, 0x8b, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x9f, 0x86, 0x18, 0x78, 0xdf, 0xfa,
+ 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53, 0x27, 0x5a, 0x26, 0x55,
+ 0x1e, 0x01, 0x62, 0xd3, 0x00, 0x58, 0x1e, 0x56, 0x24, 0x80, 0x55,
+ 0x29, 0x08, 0x55, 0x28, 0x80, 0x51, 0x1e, 0x9f, 0x63, 0x51, 0x1e,
+ 0x9f, 0x5f, 0x70, 0xbf, 0x58, 0x1e, 0x62, 0xd3, 0x00, 0x51, 0x1b,
+ 0x3a, 0x27, 0x51, 0x1a, 0x1a, 0x26, 0xd0, 0x06, 0x51, 0x28, 0x73,
+ 0x25, 0x24, 0x68, 0x28, 0x26, 0x28, 0x7f, 0x51, 0x28, 0x2d, 0x24,
+ 0x7a, 0x29, 0xbf, 0xd6, 0x7a, 0x1e, 0xdf, 0xc4, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0xa0, 0x11, 0x10, 0x51, 0x9f,
+ 0x19, 0x0e, 0xd0, 0x12, 0x7c, 0x14, 0x1d, 0x39, 0x0f, 0xa0, 0x16,
+ 0x62, 0xd0, 0x00, 0x76, 0xa0, 0x0e, 0x9f, 0x00, 0x80, 0x0c, 0x62,
+ 0xd0, 0x00, 0x55, 0xa0, 0x00, 0x55, 0x9f, 0x00, 0x90, 0xa9, 0x7f,
+ 0x62, 0xd0, 0x00, 0x3c, 0xa7, 0xf0, 0xd0, 0x03, 0x76, 0xa7, 0x62,
+ 0xd0, 0x00, 0x51, 0x2f, 0x21, 0x7f, 0x53, 0x58, 0x51, 0xa7, 0x3a,
+ 0x58, 0xb0, 0x50, 0x7c, 0x14, 0x1d, 0x62, 0xd0, 0x00, 0x53, 0xad,
+ 0x3c, 0xad, 0x0f, 0xa0, 0x3d, 0x3c, 0xa9, 0x00, 0xb0, 0x1c, 0x55,
+ 0x93, 0x00, 0x55, 0x94, 0x00, 0x51, 0xad, 0x53, 0x57, 0x55, 0x58,
+ 0x00, 0x06, 0x57, 0x93, 0x0e, 0x58, 0x00, 0x51, 0x58, 0x60, 0xd5,
+ 0x50, 0x08, 0x3f, 0x57, 0x62, 0xd0, 0x00, 0x55, 0xa5, 0x00, 0x3c,
+ 0xac, 0x00, 0xb0, 0x0a, 0x7c, 0x14, 0xb2, 0x62, 0xd0, 0x00, 0x55,
+ 0xac, 0x01, 0x62, 0xd0, 0x00, 0x55, 0xb0, 0x03, 0x80, 0x07, 0x62,
+ 0xd0, 0x00, 0x55, 0xa7, 0x00, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0xa0,
+ 0x00, 0x55, 0x9f, 0x00, 0x3c, 0xac, 0x01, 0xb0, 0x31, 0x7a, 0xb0,
+ 0x3c, 0xb0, 0x00, 0xb0, 0x2a, 0x3c, 0xac, 0x01, 0xb0, 0x0a, 0x7c,
+ 0x15, 0x45, 0x62, 0xd0, 0x00, 0x55, 0xac, 0x00, 0x62, 0xd0, 0x00,
+ 0x3c, 0xa9, 0x00, 0xb0, 0x0e, 0x51, 0xad, 0x53, 0x57, 0x55, 0x58,
+ 0x00, 0x06, 0x57, 0x93, 0x7c, 0x1a, 0xcf, 0x62, 0xd0, 0x00, 0x55,
+ 0xa7, 0x00, 0x7f, 0x10, 0x4f, 0x38, 0x16, 0x62, 0xd0, 0x00, 0x3c,
+ 0xa8, 0x00, 0xb0, 0x05, 0x51, 0x9b, 0x53, 0x24, 0x56, 0x0d, 0x00,
+ 0x80, 0x67, 0x56, 0x00, 0x00, 0x80, 0x5b, 0x62, 0xd0, 0x00, 0x3c,
+ 0xa8, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00,
+ 0x06, 0x57, 0x9b, 0x7c, 0x19, 0xf9, 0x52, 0x00, 0x53, 0x55, 0x55,
+ 0x56, 0x00, 0x06, 0x55, 0x24, 0x7c, 0x1a, 0xc3, 0x10, 0x52, 0x00,
+ 0x7c, 0x09, 0x5a, 0x20, 0x10, 0x7c, 0x05, 0xe5, 0x62, 0xd0, 0x00,
+ 0x20, 0x39, 0x00, 0xbf, 0xee, 0x7c, 0x19, 0x52, 0x52, 0x0d, 0x7c,
+ 0x1a, 0xb7, 0x02, 0x57, 0x53, 0x57, 0x51, 0x56, 0x0a, 0x58, 0x53,
+ 0x58, 0x7c, 0x1a, 0x85, 0x06, 0x55, 0x8b, 0x0e, 0x56, 0x00, 0x51,
+ 0x56, 0x7c, 0x19, 0xe3, 0x7c, 0x1a, 0x05, 0x77, 0x00, 0x3d, 0x00,
+ 0x02, 0xcf, 0xa2, 0x77, 0x0d, 0x3d, 0x0d, 0x03, 0xcf, 0x96, 0x56,
+ 0x00, 0x00, 0x81, 0x06, 0x7c, 0x19, 0x47, 0x7c, 0x19, 0x9e, 0x51,
+ 0x58, 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x0e, 0x3e, 0x57, 0x54, 0x0f,
+ 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00, 0x55, 0x55, 0x06, 0x55,
+ 0x56, 0x00, 0x55, 0x52, 0x00, 0x55, 0x51, 0x00, 0x3c, 0x56, 0x00,
+ 0xb0, 0x06, 0x3c, 0x55, 0x00, 0xa0, 0x1a, 0x70, 0xfb, 0x6e, 0x56,
+ 0x6e, 0x55, 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x57, 0x04, 0x52,
+ 0x51, 0x58, 0x0c, 0x51, 0x65, 0x57, 0x6b, 0x58, 0x8f, 0xde, 0x5f,
+ 0x57, 0x52, 0x5f, 0x58, 0x51, 0x62, 0xd0, 0x00, 0x5a, 0x55, 0x06,
+ 0x55, 0x03, 0x51, 0x55, 0x04, 0x57, 0x0e, 0x58, 0x03, 0x51, 0x58,
+ 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x10, 0x3e, 0x57, 0x54, 0x11, 0x52,
+ 0x00, 0x53, 0x57, 0x55, 0x58, 0x00, 0x55, 0x55, 0x06, 0x55, 0x56,
+ 0x00, 0x55, 0x52, 0x00, 0x55, 0x51, 0x00, 0x3c, 0x56, 0x00, 0xb0,
+ 0x06, 0x3c, 0x55, 0x00, 0xa0, 0x1a, 0x70, 0xfb, 0x6e, 0x56, 0x6e,
+ 0x55, 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x57, 0x04, 0x52, 0x51,
+ 0x58, 0x0c, 0x51, 0x65, 0x57, 0x6b, 0x58, 0x8f, 0xde, 0x5f, 0x57,
+ 0x52, 0x5f, 0x58, 0x51, 0x62, 0xd0, 0x00, 0x5a, 0x55, 0x06, 0x55,
+ 0x05, 0x51, 0x55, 0x04, 0x57, 0x0e, 0x58, 0x03, 0x51, 0x58, 0x60,
+ 0xd4, 0x3e, 0x57, 0x54, 0x12, 0x3e, 0x57, 0x54, 0x13, 0x50, 0x03,
+ 0x08, 0x5a, 0x57, 0x06, 0x57, 0x0e, 0x08, 0x51, 0x57, 0x08, 0x7c,
+ 0x17, 0xdc, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51, 0x57, 0x54, 0x15,
+ 0x51, 0x58, 0x54, 0x14, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x8b,
+ 0x7c, 0x1a, 0x33, 0x06, 0x57, 0x79, 0x7c, 0x1a, 0x6a, 0x7c, 0x19,
+ 0x2a, 0x51, 0x57, 0x01, 0x61, 0x7c, 0x1a, 0x33, 0x51, 0x57, 0x01,
+ 0x69, 0x7c, 0x1a, 0x33, 0x06, 0x57, 0x71, 0x7c, 0x1a, 0x6a, 0x77,
+ 0x00, 0x3d, 0x00, 0x02, 0xce, 0xf7, 0x38, 0xea, 0x20, 0x7f, 0x10,
+ 0x4f, 0x38, 0x16, 0x10, 0x57, 0x09, 0x50, 0x01, 0x7c, 0x08, 0x94,
+ 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x10, 0x08, 0x57, 0xc2, 0x28,
+ 0x53, 0x58, 0x18, 0x75, 0x09, 0x00, 0x28, 0x53, 0x57, 0x20, 0x10,
+ 0x51, 0x58, 0x08, 0x51, 0x57, 0x20, 0x7c, 0x09, 0xd9, 0x20, 0x10,
+ 0x57, 0x0e, 0x50, 0x01, 0x7c, 0x08, 0x94, 0x20, 0x62, 0xd0, 0x00,
+ 0x3c, 0xa8, 0x01, 0xb0, 0x0b, 0x51, 0x24, 0x53, 0x30, 0x51, 0x25,
+ 0x53, 0x31, 0x80, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x9b, 0x53, 0x24,
+ 0x51, 0x9c, 0x53, 0x25, 0x10, 0x50, 0x00, 0x7c, 0x09, 0x5a, 0x20,
+ 0x56, 0x0d, 0x00, 0x80, 0x67, 0x56, 0x00, 0x00, 0x80, 0x5b, 0x62,
+ 0xd0, 0x00, 0x3c, 0xa8, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x57,
+ 0x55, 0x58, 0x00, 0x06, 0x57, 0x9b, 0x7c, 0x19, 0xf9, 0x52, 0x00,
+ 0x53, 0x55, 0x55, 0x56, 0x00, 0x06, 0x55, 0x24, 0x7c, 0x1a, 0xc3,
+ 0x10, 0x52, 0x00, 0x7c, 0x09, 0x5a, 0x20, 0x10, 0x7c, 0x05, 0xe5,
+ 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x7c, 0x19, 0x52,
+ 0x52, 0x0d, 0x7c, 0x1a, 0xb7, 0x02, 0x57, 0x53, 0x57, 0x51, 0x56,
+ 0x0a, 0x58, 0x53, 0x58, 0x7c, 0x1a, 0x85, 0x06, 0x55, 0x8b, 0x0e,
+ 0x56, 0x00, 0x51, 0x56, 0x7c, 0x19, 0xe3, 0x7c, 0x1a, 0x05, 0x77,
+ 0x00, 0x3d, 0x00, 0x02, 0xcf, 0xa2, 0x77, 0x0d, 0x3d, 0x0d, 0x03,
+ 0xcf, 0x96, 0x56, 0x00, 0x00, 0x81, 0x06, 0x7c, 0x19, 0x47, 0x7c,
+ 0x19, 0x9e, 0x51, 0x58, 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x0e, 0x3e,
+ 0x57, 0x54, 0x0f, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00, 0x55,
+ 0x55, 0x06, 0x55, 0x56, 0x00, 0x55, 0x52, 0x00, 0x55, 0x51, 0x00,
+ 0x3c, 0x56, 0x00, 0xb0, 0x06, 0x3c, 0x55, 0x00, 0xa0, 0x1a, 0x70,
+ 0xfb, 0x6e, 0x56, 0x6e, 0x55, 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51,
+ 0x57, 0x04, 0x52, 0x51, 0x58, 0x0c, 0x51, 0x65, 0x57, 0x6b, 0x58,
+ 0x8f, 0xde, 0x5f, 0x57, 0x52, 0x5f, 0x58, 0x51, 0x62, 0xd0, 0x00,
+ 0x5a, 0x55, 0x06, 0x55, 0x03, 0x51, 0x55, 0x04, 0x57, 0x0e, 0x58,
+ 0x03, 0x51, 0x58, 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x10, 0x3e, 0x57,
+ 0x54, 0x11, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00, 0x55, 0x55,
+ 0x06, 0x55, 0x56, 0x00, 0x55, 0x52, 0x00, 0x55, 0x51, 0x00, 0x3c,
+ 0x56, 0x00, 0xb0, 0x06, 0x3c, 0x55, 0x00, 0xa0, 0x1a, 0x70, 0xfb,
+ 0x6e, 0x56, 0x6e, 0x55, 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x57,
+ 0x04, 0x52, 0x51, 0x58, 0x0c, 0x51, 0x65, 0x57, 0x6b, 0x58, 0x8f,
+ 0xde, 0x5f, 0x57, 0x52, 0x5f, 0x58, 0x51, 0x62, 0xd0, 0x00, 0x5a,
+ 0x55, 0x06, 0x55, 0x05, 0x51, 0x55, 0x04, 0x57, 0x0e, 0x58, 0x03,
+ 0x51, 0x58, 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x12, 0x3e, 0x57, 0x54,
+ 0x13, 0x50, 0x03, 0x08, 0x5a, 0x57, 0x06, 0x57, 0x0e, 0x08, 0x51,
+ 0x57, 0x08, 0x7c, 0x17, 0xdc, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51,
+ 0x57, 0x54, 0x15, 0x51, 0x58, 0x54, 0x14, 0x7c, 0x19, 0x2a, 0x51,
+ 0x57, 0x01, 0x8b, 0x7c, 0x1a, 0x33, 0x06, 0x57, 0x79, 0x7c, 0x1a,
+ 0x6a, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x61, 0x7c, 0x1a, 0x33,
+ 0x51, 0x57, 0x01, 0x69, 0x7c, 0x1a, 0x33, 0x06, 0x57, 0x71, 0x7c,
+ 0x1a, 0x6a, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0xf7, 0x56, 0x00,
+ 0x00, 0x80, 0x19, 0x7c, 0x19, 0x47, 0x06, 0x57, 0x24, 0x7c, 0x19,
+ 0xf9, 0x52, 0x00, 0x53, 0x55, 0x55, 0x56, 0x00, 0x06, 0x55, 0x30,
+ 0x7c, 0x1a, 0xc3, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0xe4, 0x38,
+ 0xea, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x62, 0xd0, 0x00, 0x52,
+ 0xfc, 0x01, 0x02, 0x53, 0x57, 0x52, 0xfb, 0x09, 0x00, 0x7c, 0x1a,
+ 0x12, 0x52, 0xfc, 0x01, 0x04, 0x53, 0x55, 0x52, 0xfb, 0x7c, 0x19,
+ 0xee, 0x12, 0x57, 0x51, 0x56, 0x1a, 0x58, 0xc0, 0x6f, 0x52, 0xfc,
+ 0x53, 0x57, 0x52, 0xfb, 0x7c, 0x1a, 0x12, 0x52, 0xfc, 0x01, 0x02,
+ 0x53, 0x55, 0x52, 0xfb, 0x7c, 0x19, 0xee, 0x12, 0x57, 0x51, 0x56,
+ 0x1a, 0x58, 0xc0, 0x10, 0x52, 0xfc, 0x01, 0x02, 0x7c, 0x1a, 0x51,
+ 0x54, 0x00, 0x3e, 0x57, 0x54, 0x01, 0x80, 0xb3, 0x62, 0xd0, 0x00,
+ 0x52, 0xfc, 0x01, 0x04, 0x53, 0x57, 0x52, 0xfb, 0x09, 0x00, 0x7c,
+ 0x1a, 0x12, 0x52, 0xfc, 0x53, 0x55, 0x52, 0xfb, 0x60, 0xd4, 0x3e,
+ 0x55, 0x53, 0x56, 0x3e, 0x55, 0x12, 0x57, 0x51, 0x56, 0x1a, 0x58,
+ 0xc0, 0x10, 0x52, 0xfc, 0x01, 0x04, 0x7c, 0x1a, 0x51, 0x54, 0x00,
+ 0x3e, 0x57, 0x54, 0x01, 0x80, 0x7e, 0x62, 0xd0, 0x00, 0x52, 0xfc,
+ 0x53, 0x57, 0x52, 0xfb, 0x7c, 0x1a, 0x7a, 0x80, 0x70, 0x62, 0xd0,
+ 0x00, 0x52, 0xfc, 0x53, 0x57, 0x52, 0xfb, 0x7c, 0x1a, 0x12, 0x52,
+ 0xfc, 0x01, 0x04, 0x53, 0x55, 0x52, 0xfb, 0x7c, 0x19, 0xee, 0x12,
+ 0x57, 0x51, 0x56, 0x1a, 0x58, 0xc0, 0x10, 0x52, 0xfc, 0x01, 0x04,
+ 0x7c, 0x1a, 0x51, 0x54, 0x00, 0x3e, 0x57, 0x54, 0x01, 0x80, 0x42,
+ 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x01, 0x02, 0x53, 0x57, 0x52, 0xfb,
+ 0x09, 0x00, 0x7c, 0x1a, 0x12, 0x52, 0xfc, 0x53, 0x55, 0x52, 0xfb,
+ 0x60, 0xd4, 0x3e, 0x55, 0x53, 0x56, 0x3e, 0x55, 0x12, 0x57, 0x51,
+ 0x56, 0x1a, 0x58, 0xc0, 0x10, 0x52, 0xfc, 0x01, 0x02, 0x7c, 0x1a,
+ 0x51, 0x54, 0x00, 0x3e, 0x57, 0x54, 0x01, 0x80, 0x0d, 0x62, 0xd0,
+ 0x00, 0x52, 0xfc, 0x53, 0x57, 0x52, 0xfb, 0x7c, 0x1a, 0x7a, 0x62,
+ 0xd0, 0x00, 0x52, 0x01, 0x53, 0x57, 0x52, 0x00, 0x53, 0x58, 0x38,
+ 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x05, 0x62, 0xd0, 0x00, 0x55,
+ 0xaf, 0x00, 0x56, 0x00, 0x00, 0x80, 0x38, 0x62, 0xd0, 0x00, 0x3c,
+ 0xa8, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00,
+ 0x06, 0x57, 0x9b, 0x7c, 0x19, 0xf9, 0x52, 0x00, 0x53, 0x55, 0x55,
+ 0x56, 0x00, 0x06, 0x55, 0x24, 0x7c, 0x1a, 0xc3, 0x10, 0x52, 0x00,
+ 0x7c, 0x09, 0x5a, 0x20, 0x10, 0x7c, 0x05, 0xe5, 0x62, 0xd0, 0x00,
+ 0x20, 0x39, 0x00, 0xbf, 0xee, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf,
+ 0xc5, 0x56, 0x00, 0x00, 0x82, 0x86, 0x62, 0xd0, 0x00, 0x3c, 0xae,
+ 0x02, 0xa0, 0x9f, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x79, 0x7c,
+ 0x19, 0x36, 0x06, 0x57, 0x8b, 0x7c, 0x19, 0xf9, 0x7c, 0x1a, 0x44,
+ 0xd0, 0x16, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x79, 0x7c, 0x19,
+ 0x36, 0x06, 0x57, 0x8b, 0x7c, 0x19, 0xf9, 0x7c, 0x1a, 0xdb, 0x80,
+ 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x8b,
+ 0x7c, 0x19, 0x36, 0x06, 0x57, 0x79, 0x7c, 0x19, 0xf9, 0x7c, 0x1a,
+ 0xdb, 0x50, 0x5e, 0x13, 0x02, 0x50, 0x01, 0x1b, 0x01, 0xc0, 0x4e,
+ 0x62, 0xd0, 0x00, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x71, 0x7c,
+ 0x19, 0x36, 0x06, 0x57, 0x8b, 0x7c, 0x19, 0xf9, 0x7c, 0x1a, 0x44,
+ 0xd0, 0x16, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x71, 0x7c, 0x19,
+ 0x36, 0x06, 0x57, 0x8b, 0x7c, 0x19, 0xf9, 0x7c, 0x1a, 0xe8, 0x80,
+ 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x8b,
+ 0x7c, 0x19, 0x36, 0x06, 0x57, 0x71, 0x7c, 0x19, 0xf9, 0x7c, 0x1a,
+ 0xe8, 0x50, 0x5e, 0x13, 0x04, 0x50, 0x01, 0x1b, 0x03, 0xd0, 0x08,
+ 0x62, 0xd0, 0x00, 0x76, 0xaf, 0x81, 0xde, 0x62, 0xd0, 0x00, 0x7c,
+ 0x19, 0x2a, 0x51, 0x57, 0x01, 0x8b, 0x7c, 0x19, 0x36, 0x06, 0x57,
+ 0x71, 0x7c, 0x19, 0xf9, 0x7c, 0x1a, 0x44, 0xd0, 0x5a, 0x7c, 0x19,
+ 0x2a, 0x7c, 0x1a, 0x1d, 0x06, 0x55, 0x01, 0x0e, 0x56, 0x00, 0x7c,
+ 0x1a, 0x05, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x8b, 0x7c, 0x19,
+ 0x36, 0x06, 0x57, 0x71, 0x7c, 0x19, 0xf9, 0x7c, 0x1a, 0x44, 0xd0,
+ 0xb4, 0x7c, 0x19, 0x2a, 0x7c, 0x1a, 0x1d, 0x06, 0x55, 0x01, 0x0e,
+ 0x56, 0x00, 0x7c, 0x1a, 0x05, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01,
+ 0x8b, 0x7c, 0x19, 0x36, 0x06, 0x57, 0x71, 0x7c, 0x19, 0xf9, 0x7c,
+ 0x1a, 0x44, 0xd0, 0x90, 0x7c, 0x19, 0x2a, 0x7c, 0x1a, 0x1d, 0x06,
+ 0x55, 0x01, 0x0e, 0x56, 0x00, 0x7c, 0x1a, 0x05, 0x80, 0x7f, 0x62,
+ 0xd0, 0x00, 0x7c, 0x19, 0x2a, 0x51, 0x57, 0x01, 0x8b, 0x7c, 0x19,
+ 0x36, 0x06, 0x57, 0x71, 0x7c, 0x19, 0xf9, 0x3e, 0x57, 0x12, 0x55,
+ 0x51, 0x58, 0x1a, 0x56, 0xd0, 0x62, 0x7c, 0x19, 0x2a, 0x7c, 0x1a,
+ 0x1d, 0x16, 0x55, 0x01, 0x1e, 0x56, 0x00, 0x7c, 0x1a, 0x05, 0x97,
+ 0xf8, 0x40, 0x51, 0x57, 0x01, 0x8b, 0x97, 0xfd, 0x40, 0x06, 0x57,
+ 0x71, 0x7c, 0x19, 0xf9, 0x3e, 0x57, 0x12, 0x55, 0x51, 0x58, 0x1a,
+ 0x56, 0xd0, 0x39, 0x97, 0xde, 0x40, 0x7c, 0x1a, 0x1d, 0x16, 0x55,
+ 0x01, 0x1e, 0x56, 0x00, 0x7c, 0x1a, 0x05, 0x97, 0xcf, 0x40, 0x51,
+ 0x57, 0x01, 0x8b, 0x97, 0xd4, 0x40, 0x06, 0x57, 0x71, 0x7c, 0x19,
+ 0xf9, 0x3e, 0x57, 0x12, 0x55, 0x51, 0x58, 0x1a, 0x56, 0xd0, 0x10,
+ 0x97, 0xb5, 0x40, 0x7c, 0x1a, 0x1d, 0x16, 0x55, 0x01, 0x1e, 0x56,
+ 0x00, 0x7c, 0x1a, 0x05, 0x62, 0xd0, 0x00, 0x97, 0xa3, 0x40, 0x51,
+ 0x57, 0x01, 0x69, 0x97, 0xa8, 0x40, 0x06, 0x57, 0x61, 0x0e, 0x58,
+ 0x00, 0x7c, 0x1a, 0x05, 0x97, 0x90, 0x40, 0x51, 0x57, 0x01, 0x71,
+ 0x97, 0x95, 0x40, 0x06, 0x57, 0x69, 0x0e, 0x58, 0x00, 0x7c, 0x1a,
+ 0x05, 0x97, 0x7d, 0x40, 0x51, 0x57, 0x01, 0x8b, 0x97, 0x82, 0x40,
+ 0x06, 0x57, 0x71, 0x0e, 0x58, 0x00, 0x7c, 0x1a, 0x05, 0x10, 0x52,
+ 0x00, 0x7c, 0x06, 0x29, 0x20, 0x62, 0xd0, 0x00, 0x97, 0x60, 0x40,
+ 0x51, 0x57, 0x01, 0x8b, 0x97, 0x65, 0x40, 0x06, 0x57, 0x79, 0x7c,
+ 0x19, 0xf9, 0x7c, 0x1a, 0x44, 0xd0, 0x25, 0x52, 0x00, 0x53, 0x57,
+ 0x55, 0x58, 0x00, 0x06, 0x57, 0x97, 0x0e, 0x58, 0x00, 0x51, 0x58,
+ 0x60, 0xd4, 0x3e, 0x57, 0x7a, 0x57, 0x53, 0x56, 0x06, 0x56, 0x01,
+ 0x51, 0x58, 0x60, 0xd5, 0x51, 0x56, 0x3f, 0x57, 0x80, 0x0a, 0x97,
+ 0x44, 0x40, 0x06, 0x57, 0x97, 0x7c, 0x1a, 0xcf, 0x97, 0x3b, 0x40,
+ 0x06, 0x57, 0x97, 0x97, 0xe7, 0x40, 0x50, 0x05, 0x3a, 0x58, 0xd0,
+ 0x58, 0x97, 0x0f, 0x40, 0x51, 0x57, 0x01, 0x79, 0x53, 0x55, 0x51,
+ 0x58, 0x09, 0x00, 0x53, 0x56, 0x06, 0x57, 0x8b, 0x97, 0xcc, 0x40,
+ 0x3e, 0x57, 0x53, 0x57, 0x51, 0x56, 0x60, 0xd4, 0x3e, 0x55, 0x53,
+ 0x54, 0x3e, 0x55, 0x16, 0x55, 0x02, 0x02, 0x57, 0x53, 0x57, 0x51,
+ 0x54, 0x0a, 0x58, 0x53, 0x58, 0x70, 0xfb, 0x6e, 0x58, 0x6e, 0x57,
+ 0x51, 0x56, 0x60, 0xd5, 0x51, 0x58, 0x3f, 0x55, 0x51, 0x57, 0x3f,
+ 0x55, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00, 0x06, 0x57, 0x97,
+ 0x0e, 0x58, 0x00, 0x51, 0x58, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x57,
+ 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcd, 0x77, 0x62, 0xd0, 0x00, 0x3c,
+ 0xae, 0x02, 0xb1, 0x10, 0x56, 0x00, 0x00, 0x81, 0x06, 0x62, 0xd0,
+ 0x00, 0x96, 0xa1, 0x40, 0x51, 0x57, 0x01, 0x8b, 0x96, 0xa6, 0x40,
+ 0x06, 0x57, 0x38, 0x0e, 0x58, 0x00, 0x97, 0x6c, 0x40, 0x96, 0x8e,
+ 0x40, 0x51, 0x57, 0x01, 0x79, 0x96, 0x93, 0x40, 0x06, 0x57, 0x3c,
+ 0x0e, 0x58, 0x00, 0x97, 0x59, 0x40, 0x96, 0x7b, 0x40, 0x51, 0x57,
+ 0x01, 0x79, 0x96, 0x80, 0x40, 0x51, 0x57, 0x01, 0x8b, 0x53, 0x53,
+ 0x51, 0x58, 0x97, 0xe9, 0x40, 0x51, 0x55, 0x12, 0x53, 0x51, 0x56,
+ 0x1a, 0x54, 0xd0, 0x21, 0x97, 0xb7, 0x40, 0x51, 0x55, 0x01, 0x79,
+ 0x53, 0x53, 0x51, 0x56, 0x97, 0xd1, 0x40, 0x06, 0x55, 0x8b, 0x97,
+ 0x7d, 0x40, 0x12, 0x53, 0x54, 0x02, 0x51, 0x56, 0x1a, 0x54, 0x54,
+ 0x01, 0x80, 0x07, 0x56, 0x02, 0x00, 0x56, 0x01, 0x00, 0x62, 0xd0,
+ 0x00, 0x06, 0x57, 0x34, 0x0e, 0x58, 0x00, 0x51, 0x58, 0x60, 0xd5,
+ 0x52, 0x01, 0x3f, 0x57, 0x52, 0x02, 0x3f, 0x57, 0x96, 0x21, 0x40,
+ 0x51, 0x57, 0x01, 0x8b, 0x96, 0x26, 0x40, 0x06, 0x57, 0x38, 0x0e,
+ 0x58, 0x00, 0x96, 0xec, 0x40, 0x96, 0x0e, 0x40, 0x51, 0x57, 0x01,
+ 0x79, 0x96, 0x13, 0x40, 0x06, 0x57, 0x3c, 0x0e, 0x58, 0x00, 0x96,
+ 0xd9, 0x40, 0x95, 0xfb, 0x40, 0x51, 0x57, 0x01, 0x79, 0x96, 0x00,
+ 0x40, 0x51, 0x57, 0x01, 0x8b, 0x53, 0x53, 0x51, 0x58, 0x97, 0x69,
+ 0x40, 0x51, 0x55, 0x12, 0x53, 0x51, 0x56, 0x1a, 0x54, 0xd0, 0x21,
+ 0x97, 0x37, 0x40, 0x51, 0x55, 0x01, 0x79, 0x53, 0x53, 0x51, 0x56,
+ 0x97, 0x51, 0x40, 0x06, 0x55, 0x8b, 0x96, 0xfd, 0x40, 0x12, 0x53,
+ 0x54, 0x04, 0x51, 0x56, 0x1a, 0x54, 0x54, 0x03, 0x80, 0x07, 0x56,
+ 0x04, 0x00, 0x56, 0x03, 0x00, 0x62, 0xd0, 0x00, 0x06, 0x57, 0x34,
+ 0x0e, 0x58, 0x00, 0x51, 0x58, 0x60, 0xd5, 0x52, 0x03, 0x3f, 0x57,
+ 0x52, 0x04, 0x3f, 0x57, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0xf7,
+ 0x62, 0xd0, 0x00, 0x3c, 0xae, 0x02, 0xa0, 0x18, 0x3c, 0xaf, 0x00,
+ 0xa0, 0x13, 0x50, 0x01, 0x08, 0x50, 0x2c, 0x08, 0x90, 0x0e, 0x38,
+ 0xfe, 0x7c, 0x0a, 0xf9, 0x10, 0x7c, 0x07, 0xe5, 0x20, 0x38, 0xfb,
+ 0x20, 0x7f, 0x10, 0x4f, 0x80, 0x02, 0x40, 0x62, 0xd0, 0x00, 0x52,
+ 0xfc, 0x53, 0x57, 0x52, 0xfb, 0x53, 0x58, 0x51, 0x57, 0x11, 0x01,
+ 0x54, 0xfc, 0x51, 0x58, 0x19, 0x00, 0x54, 0xfb, 0x3c, 0x58, 0x00,
+ 0xbf, 0xe4, 0x3c, 0x57, 0x00, 0xbf, 0xdf, 0x20, 0x7f, 0x10, 0x7c,
+ 0x04, 0xaf, 0x7c, 0x04, 0x8c, 0x20, 0x7f, 0x10, 0x7c, 0x04, 0xab,
+ 0x7c, 0x04, 0x88, 0x20, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0x42, 0x12,
+ 0x7e, 0x50, 0x00, 0x1a, 0x7d, 0xd0, 0x0f, 0x51, 0x43, 0x12, 0x80,
+ 0x50, 0x00, 0x1a, 0x7f, 0xd0, 0x05, 0x50, 0x0f, 0x80, 0x17, 0x62,
+ 0xd0, 0x00, 0x51, 0x80, 0x12, 0x7e, 0x51, 0x7f, 0x1a, 0x7d, 0xd0,
+ 0x05, 0x50, 0x00, 0x80, 0x06, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x7f,
+ 0x10, 0x4f, 0x38, 0x05, 0x62, 0xd0, 0x00, 0x51, 0x7e, 0x54, 0x02,
+ 0x51, 0x7d, 0x54, 0x01, 0x56, 0x04, 0x00, 0x56, 0x00, 0x00, 0x56,
+ 0x03, 0x00, 0x80, 0x61, 0x95, 0x0e, 0x40, 0x06, 0x57, 0x42, 0x0e,
+ 0x58, 0x00, 0x51, 0x58, 0x60, 0xd4, 0x3e, 0x57, 0x53, 0x57, 0x96,
+ 0x3b, 0x40, 0x06, 0x55, 0x7d, 0x0e, 0x56, 0x00, 0x51, 0x56, 0x95,
+ 0x8e, 0x40, 0x51, 0x57, 0x12, 0x55, 0x50, 0x00, 0x1a, 0x56, 0xd0,
+ 0x03, 0x77, 0x03, 0x62, 0xd0, 0x00, 0x94, 0xc3, 0x40, 0x06, 0x57,
+ 0x7d, 0x95, 0x8c, 0x40, 0x3e, 0x57, 0x53, 0x57, 0x52, 0x02, 0x12,
+ 0x57, 0x52, 0x01, 0x1a, 0x58, 0xd0, 0x1a, 0x94, 0xac, 0x40, 0x06,
+ 0x57, 0x7d, 0x0e, 0x58, 0x00, 0x51, 0x58, 0x60, 0xd4, 0x3e, 0x57,
+ 0x54, 0x01, 0x3e, 0x57, 0x54, 0x02, 0x52, 0x00, 0x54, 0x04, 0x77,
+ 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x9c, 0x50, 0x01, 0x3b, 0x03, 0xd0,
+ 0x08, 0x62, 0xd0, 0x00, 0x50, 0x0f, 0x80, 0x06, 0x52, 0x04, 0x62,
+ 0xd0, 0x00, 0x38, 0xfb, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x70,
+ 0xfe, 0x62, 0xd0, 0x00, 0x26, 0x2a, 0xf0, 0x51, 0xad, 0x01, 0x01,
+ 0x53, 0x58, 0x51, 0x2a, 0x2a, 0x58, 0x53, 0x2a, 0x71, 0x01, 0x62,
+ 0xe3, 0x38, 0x10, 0x7c, 0x05, 0xe5, 0x62, 0xd0, 0x00, 0x20, 0x41,
+ 0x00, 0xf7, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21, 0x10,
+ 0x7c, 0x05, 0xe5, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x58, 0x47, 0x58,
+ 0x20, 0xa0, 0x03, 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x01, 0x08,
+ 0x9e, 0xb6, 0x38, 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01,
+ 0x11, 0x0a, 0x52, 0x00, 0x19, 0x04, 0xcf, 0xd7, 0x56, 0x01, 0x00,
+ 0x56, 0x00, 0x00, 0x80, 0x21, 0x10, 0x7c, 0x05, 0xe5, 0x62, 0xd0,
+ 0x00, 0x20, 0x53, 0x58, 0x47, 0x58, 0x20, 0xb0, 0x03, 0x80, 0x1a,
+ 0x50, 0x00, 0x08, 0x50, 0x01, 0x08, 0x9e, 0x84, 0x38, 0xfe, 0x77,
+ 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01, 0x11, 0xce, 0x52, 0x00, 0x19,
+ 0x00, 0xcf, 0xd7, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10,
+ 0x4f, 0x38, 0x02, 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x26, 0x2a, 0xf0,
+ 0x51, 0xad, 0x01, 0x09, 0x53, 0x58, 0x51, 0x2a, 0x2a, 0x58, 0x53,
+ 0x2a, 0x71, 0x01, 0x62, 0xe3, 0x38, 0x10, 0x7c, 0x05, 0xe5, 0x62,
+ 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56, 0x01, 0x00, 0x56, 0x00,
+ 0x00, 0x80, 0x21, 0x10, 0x7c, 0x05, 0xe5, 0x62, 0xd0, 0x00, 0x20,
+ 0x53, 0x58, 0x47, 0x58, 0x20, 0xa0, 0x03, 0x80, 0x1a, 0x50, 0x00,
+ 0x08, 0x50, 0x01, 0x08, 0x9e, 0x23, 0x38, 0xfe, 0x77, 0x01, 0x0f,
+ 0x00, 0x00, 0x52, 0x01, 0x11, 0x0a, 0x52, 0x00, 0x19, 0x04, 0xcf,
+ 0xd7, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21, 0x10, 0x7c,
+ 0x05, 0xe5, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x58, 0x47, 0x58, 0x20,
+ 0xb0, 0x03, 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x01, 0x08, 0x9d,
+ 0xf1, 0x38, 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01, 0x11,
+ 0xce, 0x52, 0x00, 0x19, 0x00, 0xcf, 0xd7, 0x43, 0x00, 0x08, 0x38,
+ 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x04, 0x62, 0xd0, 0x00, 0x51,
+ 0x2a, 0x21, 0xf0, 0x54, 0x00, 0x51, 0x2d, 0x54, 0x01, 0x3d, 0x00,
+ 0x10, 0xb0, 0x2a, 0x55, 0xa5, 0x00, 0x3c, 0xa9, 0x01, 0xb0, 0x09,
+ 0x55, 0x93, 0x00, 0x55, 0x94, 0x00, 0x80, 0x0f, 0x62, 0xd0, 0x00,
+ 0x3c, 0xac, 0x01, 0xa0, 0x07, 0x55, 0x93, 0x00, 0x55, 0x94, 0x00,
+ 0x56, 0x00, 0x00, 0x62, 0xd0, 0x00, 0x26, 0x2a, 0x0f, 0x81, 0x7d,
+ 0x3d, 0x00, 0x20, 0xb0, 0x18, 0x62, 0xd0, 0x00, 0x55, 0xa5, 0x01,
+ 0x55, 0xa6, 0x00, 0x55, 0x93, 0x08, 0x55, 0x94, 0x08, 0x56, 0x00,
+ 0x00, 0x26, 0x2a, 0x0f, 0x81, 0x61, 0x3d, 0x00, 0x30, 0xb0, 0x0f,
+ 0x62, 0xd0, 0x00, 0x55, 0xae, 0x00, 0x56, 0x00, 0x00, 0x26, 0x2a,
+ 0x0f, 0x81, 0x4e, 0x3d, 0x00, 0x40, 0xb0, 0x0f, 0x62, 0xd0, 0x00,
+ 0x55, 0xae, 0x02, 0x56, 0x00, 0x00, 0x26, 0x2a, 0x0f, 0x81, 0x3b,
+ 0x3d, 0x00, 0x50, 0xb0, 0xa7, 0x52, 0x01, 0x54, 0x03, 0x56, 0x02,
+ 0x00, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x01, 0xa0, 0x21,
+ 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x02, 0xa0, 0x28, 0x3d,
+ 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x04, 0xa0, 0x36, 0x3d, 0x02,
+ 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x08, 0xa0, 0x48, 0x80, 0x62, 0x62,
+ 0xd0, 0x00, 0x55, 0xa8, 0x01, 0x51, 0x2f, 0x29, 0x80, 0x53, 0x2f,
+ 0x7c, 0x0c, 0x8c, 0x80, 0x51, 0x62, 0xd0, 0x00, 0x51, 0x2b, 0x53,
+ 0x42, 0x51, 0x2b, 0x53, 0x43, 0x51, 0x2b, 0x53, 0x2e, 0x51, 0x2c,
+ 0x53, 0x0e, 0x55, 0x0d, 0x00, 0x80, 0x39, 0x62, 0xd0, 0x00, 0x51,
+ 0x2b, 0x53, 0x2f, 0x3c, 0xa8, 0x00, 0xa0, 0x09, 0x51, 0x2f, 0x29,
+ 0x80, 0x53, 0x2f, 0x80, 0x25, 0x62, 0xd0, 0x00, 0x26, 0x2f, 0x7f,
+ 0x80, 0x1d, 0x62, 0xd0, 0x00, 0x55, 0xa8, 0x00, 0x26, 0x2f, 0x7f,
+ 0x51, 0x9b, 0x53, 0x24, 0x51, 0x24, 0x53, 0x30, 0x51, 0x9c, 0x53,
+ 0x25, 0x51, 0x25, 0x53, 0x31, 0x7c, 0x0c, 0x8c, 0x56, 0x00, 0x00,
+ 0x62, 0xd0, 0x00, 0x26, 0x2a, 0x0f, 0x55, 0x2b, 0x06, 0x55, 0x2c,
+ 0x05, 0x55, 0x2d, 0x00, 0x80, 0x90, 0x3d, 0x00, 0x60, 0xb0, 0x0f,
+ 0x62, 0xd0, 0x00, 0x55, 0xa9, 0x01, 0x56, 0x00, 0x00, 0x26, 0x2a,
+ 0x0f, 0x80, 0x7d, 0x3d, 0x00, 0x70, 0xb0, 0x0f, 0x62, 0xd0, 0x00,
+ 0x55, 0xa9, 0x00, 0x56, 0x00, 0x00, 0x26, 0x2a, 0x0f, 0x80, 0x6a,
+ 0x3d, 0x00, 0x80, 0xb0, 0x65, 0x56, 0x00, 0x00, 0x62, 0xd0, 0x00,
+ 0x26, 0x2a, 0x0f, 0x9c, 0x9f, 0x10, 0x7c, 0x08, 0xd8, 0x7c, 0x05,
+ 0xfb, 0x20, 0x70, 0xfe, 0x71, 0x10, 0x41, 0x00, 0xf7, 0x41, 0x01,
+ 0xf7, 0x70, 0xcf, 0x62, 0xda, 0x00, 0x71, 0x10, 0x41, 0xdc, 0xfe,
+ 0x70, 0xcf, 0x43, 0x01, 0x08, 0x43, 0x00, 0x08, 0x50, 0x00, 0x08,
+ 0x50, 0x1e, 0x08, 0x9c, 0x4b, 0x38, 0xfe, 0x71, 0x01, 0x43, 0xe0,
+ 0x10, 0x43, 0xff, 0x08, 0x70, 0xfe, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x10, 0x7c, 0x08, 0x07, 0x7c, 0x05, 0xaf, 0x7c, 0x05,
+ 0xf0, 0x20, 0x93, 0x0b, 0x40, 0x62, 0xe3, 0x38, 0x56, 0x00, 0x00,
+ 0x62, 0xd0, 0x00, 0x26, 0x2a, 0x0f, 0x38, 0xfc, 0x20, 0x7f, 0x62,
+ 0xd0, 0x00, 0x3c, 0xa5, 0x00, 0xa0, 0x13, 0x9c, 0x38, 0x62, 0xd0,
+ 0x00, 0x3c, 0xa6, 0x00, 0xb0, 0x33, 0x55, 0xa6, 0x01, 0x7c, 0x0a,
+ 0xf9, 0x80, 0x2b, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x93, 0xd0,
+ 0x08, 0x10, 0x7c, 0x04, 0xaf, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04,
+ 0xab, 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x94, 0xd0, 0x08,
+ 0x10, 0x7c, 0x04, 0x8c, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0x88,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x03, 0x56, 0x02, 0x00, 0x56, 0x01,
+ 0x00, 0x56, 0x00, 0x00, 0x80, 0x3e, 0x62, 0xd0, 0x00, 0x91, 0x3a,
+ 0x40, 0x52, 0xfc, 0x04, 0x57, 0x52, 0xfb, 0x0c, 0x58, 0x51, 0x58,
+ 0x60, 0xd4, 0x3e, 0x57, 0x53, 0x58, 0x3e, 0x57, 0x53, 0x57, 0x52,
+ 0x02, 0x12, 0x57, 0x52, 0x01, 0x1a, 0x58, 0xd0, 0x18, 0x91, 0x19,
+ 0x40, 0x52, 0xfc, 0x04, 0x57, 0x52, 0xfb, 0x0c, 0x58, 0x51, 0x58,
+ 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x01, 0x3e, 0x57, 0x54, 0x02, 0x77,
+ 0x00, 0x52, 0x00, 0x3b, 0xfa, 0xcf, 0xbe, 0x62, 0xd0, 0x00, 0x52,
+ 0x02, 0x53, 0x57, 0x52, 0x01, 0x53, 0x58, 0x38, 0xfd, 0x20, 0x7f,
+ 0x10, 0x7c, 0x04, 0x3a, 0x20, 0x10, 0x50, 0x04, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x8b, 0x08, 0x7c, 0x04, 0x43, 0x38, 0xfd, 0x20, 0x10,
+ 0x50, 0x04, 0x08, 0x50, 0x00, 0x08, 0x50, 0x79, 0x08, 0x7c, 0x04,
+ 0x43, 0x38, 0xfd, 0x20, 0x10, 0x50, 0x04, 0x08, 0x50, 0x00, 0x08,
+ 0x50, 0x7d, 0x08, 0x7c, 0x04, 0x43, 0x38, 0xfd, 0x20, 0x10, 0x50,
+ 0x00, 0x7c, 0x03, 0x5e, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x5e,
+ 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x5e, 0x20, 0x7f, 0x62, 0xd0,
+ 0x00, 0x55, 0xa8, 0x00, 0x55, 0xa9, 0x01, 0x10, 0x7c, 0x04, 0xaf,
+ 0x7c, 0x04, 0x8c, 0x20, 0x9b, 0x3e, 0x62, 0xe3, 0x38, 0x71, 0x10,
+ 0x43, 0x00, 0x08, 0x41, 0x01, 0xf7, 0x70, 0xcf, 0x43, 0x00, 0x08,
+ 0x62, 0xd0, 0x00, 0x55, 0x2a, 0x08, 0x55, 0x2b, 0x06, 0x55, 0x2c,
+ 0x05, 0x55, 0x2e, 0x19, 0x55, 0x2f, 0x03, 0x55, 0x30, 0x56, 0x55,
+ 0x31, 0x45, 0x55, 0x32, 0x00, 0x55, 0x33, 0x00, 0x3c, 0xa8, 0x00,
+ 0xa0, 0x09, 0x51, 0x2f, 0x29, 0x80, 0x53, 0x2f, 0x80, 0x07, 0x62,
+ 0xd0, 0x00, 0x26, 0x2f, 0x7f, 0x10, 0x50, 0x00, 0x08, 0x50, 0x2a,
+ 0x08, 0x50, 0x06, 0x08, 0x50, 0x16, 0x08, 0x7c, 0x06, 0x02, 0x38,
+ 0xfc, 0x7c, 0x05, 0xaf, 0x7c, 0x05, 0xf0, 0x20, 0x91, 0x9a, 0x40,
+ 0x10, 0x7c, 0x08, 0x07, 0x7c, 0x07, 0x8d, 0x20, 0x7c, 0x0c, 0x8c,
+ 0x80, 0x22, 0x62, 0xe3, 0x38, 0x7c, 0x0f, 0x9d, 0x10, 0x7c, 0x07,
+ 0xcb, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xa0, 0x09, 0x7c, 0x0a,
+ 0x27, 0x7c, 0x0a, 0x51, 0x80, 0x04, 0x7c, 0x0a, 0xba, 0x9c, 0xb4,
+ 0x9e, 0x71, 0x8f, 0xde, 0x8f, 0xff, 0x52, 0x00, 0x53, 0x57, 0x55,
+ 0x58, 0x00, 0x65, 0x57, 0x6b, 0x58, 0x7f, 0x53, 0x55, 0x51, 0x58,
+ 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x55, 0x53, 0x56, 0x3e, 0x55, 0x53,
+ 0x55, 0x7f, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58,
+ 0x00, 0x7f, 0x52, 0x00, 0x53, 0x57, 0x55, 0x58, 0x00, 0x55, 0x55,
+ 0x06, 0x55, 0x56, 0x00, 0x55, 0x52, 0x00, 0x55, 0x51, 0x00, 0x3c,
+ 0x56, 0x00, 0xb0, 0x06, 0x3c, 0x55, 0x00, 0xa0, 0x1a, 0x70, 0xfb,
+ 0x6e, 0x56, 0x6e, 0x55, 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x57,
+ 0x04, 0x52, 0x51, 0x58, 0x0c, 0x51, 0x65, 0x57, 0x6b, 0x58, 0x8f,
+ 0xde, 0x5f, 0x57, 0x52, 0x5f, 0x58, 0x51, 0x62, 0xd0, 0x00, 0x5a,
+ 0x55, 0x06, 0x55, 0x01, 0x51, 0x55, 0x04, 0x57, 0x0e, 0x58, 0x03,
+ 0x7f, 0x55, 0x55, 0x06, 0x55, 0x56, 0x00, 0x55, 0x52, 0x00, 0x55,
+ 0x51, 0x00, 0x3c, 0x56, 0x00, 0xb0, 0x06, 0x3c, 0x55, 0x00, 0xa0,
+ 0x1a, 0x70, 0xfb, 0x6e, 0x56, 0x6e, 0x55, 0xd0, 0x0c, 0x62, 0xd0,
+ 0x00, 0x51, 0x57, 0x04, 0x52, 0x51, 0x58, 0x0c, 0x51, 0x65, 0x57,
+ 0x6b, 0x58, 0x8f, 0xde, 0x5f, 0x57, 0x52, 0x5f, 0x58, 0x51, 0x62,
+ 0xd0, 0x00, 0x5a, 0x55, 0x06, 0x55, 0x01, 0x51, 0x55, 0x04, 0x57,
+ 0x0e, 0x58, 0x03, 0x7f, 0x60, 0xd4, 0x3e, 0x55, 0x53, 0x56, 0x3e,
+ 0x55, 0x53, 0x55, 0x7f, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x55, 0x53,
+ 0x56, 0x3e, 0x55, 0x7f, 0x0e, 0x58, 0x00, 0x51, 0x58, 0x60, 0xd4,
+ 0x3e, 0x57, 0x53, 0x58, 0x7f, 0x51, 0x58, 0x60, 0xd5, 0x51, 0x56,
+ 0x3f, 0x57, 0x51, 0x55, 0x3f, 0x57, 0x7f, 0x60, 0xd4, 0x3e, 0x57,
+ 0x53, 0x58, 0x3e, 0x57, 0x53, 0x57, 0x7f, 0x06, 0x57, 0x8b, 0x0e,
+ 0x58, 0x00, 0x51, 0x58, 0x60, 0xd4, 0x3e, 0x57, 0x53, 0x56, 0x3e,
+ 0x57, 0x16, 0x57, 0x02, 0x53, 0x55, 0x7f, 0x53, 0x55, 0x51, 0x58,
+ 0x09, 0x00, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x55, 0x52, 0x15, 0x3f,
+ 0x55, 0x7f, 0x3e, 0x57, 0x53, 0x57, 0x51, 0x55, 0x12, 0x57, 0x51,
+ 0x56, 0x1a, 0x58, 0x7f, 0x53, 0x57, 0x52, 0xfb, 0x09, 0x00, 0x60,
+ 0xd4, 0x3e, 0x57, 0x7f, 0x0e, 0x56, 0x00, 0x51, 0x56, 0x60, 0xd4,
+ 0x3e, 0x55, 0x53, 0x56, 0x3e, 0x55, 0x7f, 0x0e, 0x58, 0x00, 0x51,
+ 0x58, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x57, 0x52, 0x15, 0x3f, 0x57,
+ 0x7f, 0x60, 0xd4, 0x3e, 0x57, 0x54, 0x00, 0x3e, 0x57, 0x54, 0x01,
+ 0x7f, 0x52, 0x00, 0x53, 0x55, 0x55, 0x56, 0x00, 0x65, 0x55, 0x6b,
+ 0x56, 0x7f, 0x71, 0x10, 0x41, 0x04, 0xfe, 0x41, 0x05, 0xfe, 0x41,
+ 0x04, 0xfd, 0x41, 0x05, 0xfd, 0x70, 0xcf, 0x43, 0x04, 0x01, 0x43,
+ 0x04, 0x02, 0x71, 0x01, 0x7f, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x53,
+ 0x53, 0x54, 0x3e, 0x53, 0x53, 0x53, 0x7f, 0x53, 0x55, 0x55, 0x56,
+ 0x00, 0x65, 0x55, 0x6b, 0x56, 0x51, 0x55, 0x7f, 0x0e, 0x56, 0x00,
+ 0x51, 0x56, 0x60, 0xd5, 0x51, 0x58, 0x3f, 0x55, 0x7f, 0x0e, 0x58,
+ 0x00, 0x51, 0x58, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x57, 0x7f, 0x3e,
+ 0x57, 0x12, 0x55, 0x54, 0x02, 0x51, 0x58, 0x1a, 0x56, 0x54, 0x01,
+ 0x7f, 0x3e, 0x57, 0x12, 0x55, 0x54, 0x04, 0x51, 0x58, 0x1a, 0x56,
+ 0x54, 0x03, 0x7f, 0x00, 0x2a, 0x00, 0x16, 0x00, 0x49, 0x00, 0x08,
+ 0x00, 0x59, 0x00, 0x20, 0x00, 0x81, 0x00, 0x0a, 0x00, 0x8f, 0x00,
+ 0x04, 0x00, 0x93, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x97, 0x00,
+ 0x04, 0x00, 0x9b, 0x02, 0x56, 0x45, 0x00, 0x9d, 0x00, 0x08, 0x00,
+ 0xa5, 0x06, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0xab, 0x00,
+ 0x05, 0x00, 0xb0, 0x01, 0x03, 0xff, 0x00, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_NA.h b/drivers/input/keyboard/cypressbln/touchkey_fw_NA.h
new file mode 100644
index 0000000..2667cf6
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_NA.h
@@ -0,0 +1,747 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x00, 0x68,
+ 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x05, 0x47, 0x7e, 0x7e, 0x30,
+ 0x30, 0x30, 0x7d, 0x06, 0x93, 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30,
+ 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x40, 0x71, 0x10, 0x62, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe3, 0x38, 0x50, 0x80, 0x4e, 0x62, 0xe3, 0x38, 0x5d,
+ 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55, 0xfa, 0x01, 0x40, 0x4f, 0x5b,
+ 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a, 0x50, 0x06, 0x00, 0x40,
+ 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8, 0x70, 0xef, 0x18, 0x60,
+ 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00, 0x71, 0x10, 0x62, 0xe0,
+ 0x02, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x71, 0x10, 0x41, 0xe1, 0xfe,
+ 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1, 0x03, 0x50, 0x00, 0x4e,
+ 0x62, 0xd3, 0x03, 0x62, 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4,
+ 0x00, 0x71, 0xc0, 0x7c, 0x03, 0x01, 0x62, 0xd0, 0x00, 0x50, 0x02,
+ 0x57, 0xff, 0x08, 0x28, 0x53, 0x79, 0x18, 0x75, 0x09, 0x00, 0x28,
+ 0x4b, 0x51, 0x79, 0x80, 0x04, 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00,
+ 0x08, 0x28, 0x60, 0xd5, 0x74, 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00,
+ 0x08, 0x28, 0x53, 0x79, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xa0,
+ 0x1c, 0x53, 0x78, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x3f, 0x79,
+ 0x47, 0x79, 0xff, 0xb0, 0x06, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x18,
+ 0x7a, 0x78, 0xbf, 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09, 0x00, 0x08,
+ 0x28, 0x53, 0x78, 0x50, 0x00, 0x3f, 0x79, 0x47, 0x79, 0xff, 0xb0,
+ 0x08, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x78, 0xbf,
+ 0xef, 0x18, 0x8f, 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71,
+ 0x10, 0x62, 0xe0, 0x03, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x0a,
+ 0x86, 0x8f, 0xff, 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x61, 0x00, 0xfd, 0x00, 0xcd, 0x00,
+ 0xce, 0x00, 0xa5, 0x00, 0xa4, 0x00, 0xa0, 0x00, 0xa1, 0x80, 0xa2,
+ 0xc0, 0xa3, 0x0c, 0xa8, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0x7c, 0x33,
+ 0x7a, 0x00, 0x7b, 0x00, 0x79, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38,
+ 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00,
+ 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43,
+ 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
+ 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e,
+ 0x00, 0x4f, 0x00, 0xca, 0x20, 0xd6, 0x44, 0xcf, 0x00, 0xcb, 0x00,
+ 0xc8, 0x00, 0xcc, 0x00, 0xc9, 0x00, 0xd7, 0x00, 0xa9, 0x00, 0x2b,
+ 0x00, 0xb0, 0x00, 0xb3, 0x02, 0xb6, 0x00, 0xb2, 0x00, 0xb5, 0x00,
+ 0xb8, 0x00, 0xb1, 0x00, 0xb4, 0x00, 0xb7, 0x00, 0x33, 0x00, 0x34,
+ 0x00, 0x35, 0x00, 0xff, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
+ 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0xdc, 0x00,
+ 0xe2, 0x00, 0xdd, 0x00, 0xd8, 0x02, 0xd9, 0xb4, 0xda, 0x00, 0xdb,
+ 0x00, 0xdf, 0x00, 0x29, 0x00, 0x30, 0x00, 0xbd, 0x00, 0xff, 0x70,
+ 0xef, 0x62, 0x00, 0x08, 0x71, 0x10, 0x62, 0x00, 0x98, 0x62, 0x01,
+ 0x02, 0x70, 0xef, 0x62, 0x04, 0x03, 0x71, 0x10, 0x62, 0x04, 0x00,
+ 0x62, 0x05, 0xbc, 0x70, 0xef, 0x62, 0x08, 0x00, 0x71, 0x10, 0x62,
+ 0x08, 0x28, 0x62, 0x09, 0x00, 0x70, 0xef, 0x62, 0x0c, 0x00, 0x71,
+ 0x10, 0x62, 0x0c, 0x00, 0x62, 0x0d, 0x00, 0x70, 0xef, 0x62, 0x10,
+ 0x00, 0x71, 0x10, 0x62, 0x10, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef,
+ 0x62, 0x01, 0x00, 0x62, 0x05, 0x00, 0x62, 0x09, 0x00, 0x62, 0x0d,
+ 0x00, 0x62, 0x11, 0x00, 0x70, 0xef, 0x7f, 0x1d, 0x3e, 0x55, 0x02,
+ 0x08, 0x55, 0x03, 0x03, 0x55, 0x04, 0x00, 0x7c, 0x03, 0x11, 0x7c,
+ 0x02, 0xaa, 0x7f, 0x10, 0x70, 0xef, 0x50, 0x00, 0x67, 0x50, 0x02,
+ 0x57, 0x00, 0x7c, 0x03, 0x2c, 0x50, 0x01, 0x67, 0x50, 0x02, 0x57,
+ 0x83, 0x7c, 0x03, 0x2c, 0x70, 0xef, 0x20, 0x7f, 0x38, 0x02, 0x10,
+ 0x08, 0x4f, 0x56, 0xfc, 0x00, 0xd0, 0x04, 0x56, 0xfc, 0x01, 0x18,
+ 0x20, 0x70, 0xef, 0x62, 0xe3, 0x00, 0x10, 0x08, 0x28, 0x39, 0xff,
+ 0xa0, 0x1f, 0x4f, 0x48, 0xfc, 0x01, 0xa0, 0x03, 0x71, 0x10, 0x54,
+ 0xfd, 0x18, 0x20, 0x75, 0x09, 0x00, 0x10, 0x08, 0x28, 0x4f, 0x59,
+ 0xfd, 0x61, 0x00, 0x18, 0x20, 0x75, 0x09, 0x00, 0x8f, 0xd7, 0x38,
+ 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x30, 0x31, 0x32, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+ 0x62, 0xd0, 0x00, 0x2e, 0x02, 0x08, 0x51, 0x02, 0x60, 0x00, 0x71,
+ 0x10, 0x41, 0x01, 0xf7, 0x43, 0x00, 0x08, 0x70, 0xef, 0x7f, 0x62,
+ 0xd0, 0x00, 0x53, 0x00, 0x71, 0x10, 0x5d, 0xe0, 0x08, 0x21, 0xf8,
+ 0x29, 0x00, 0x70, 0xfe, 0x60, 0xe0, 0x70, 0xef, 0x4b, 0x4b, 0x4b,
+ 0x4b, 0x51, 0x02, 0x21, 0xf7, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05,
+ 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e,
+ 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01,
+ 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29,
+ 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0,
+ 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80,
+ 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21,
+ 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x47, 0x00,
+ 0x00, 0x49, 0x01, 0x00, 0x29, 0x08, 0x60, 0x00, 0x57, 0x01, 0x79,
+ 0xbf, 0xfe, 0x18, 0x71, 0x10, 0x60, 0xe0, 0x70, 0xef, 0x71, 0x01,
+ 0x7f, 0x08, 0x67, 0x67, 0x67, 0x67, 0x21, 0x0f, 0xff, 0x2b, 0x9f,
+ 0x4e, 0x18, 0x21, 0x0f, 0xff, 0x24, 0x9f, 0x47, 0x7f, 0x08, 0x10,
+ 0x28, 0xa0, 0x0b, 0x9f, 0x3f, 0x20, 0x18, 0x75, 0xdf, 0xf5, 0x74,
+ 0x8f, 0xf2, 0x38, 0xfe, 0x7f, 0x52, 0x00, 0xa0, 0x08, 0x10, 0x9f,
+ 0x2d, 0x20, 0x75, 0x8f, 0xf6, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50,
+ 0x0d, 0x9f, 0x20, 0x50, 0x0a, 0x9f, 0x1c, 0x7f, 0x70, 0xbf, 0x62,
+ 0xd3, 0x03, 0x4f, 0x52, 0xfb, 0xa0, 0x15, 0x7b, 0xfb, 0x52, 0xfc,
+ 0x59, 0xfd, 0x60, 0xd3, 0x52, 0x00, 0x9f, 0x05, 0x4f, 0x62, 0xd3,
+ 0x03, 0x77, 0xfd, 0x8f, 0xe9, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x3d,
+ 0xfa, 0x00, 0xb0, 0x06, 0x3d, 0xfb, 0x00, 0xa0, 0x18, 0x10, 0x52,
+ 0xfc, 0x59, 0xfd, 0x28, 0x9e, 0xe6, 0x20, 0x07, 0xfd, 0x01, 0x0f,
+ 0xfc, 0x00, 0x17, 0xfb, 0x01, 0x1f, 0xfa, 0x00, 0x8f, 0xe0, 0x7f,
+ 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00,
+ 0xa0, 0x06, 0x26, 0x04, 0xdf, 0x80, 0x04, 0x2e, 0x04, 0x20, 0x51,
+ 0x04, 0x60, 0x08, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00,
+ 0x29, 0x00, 0xa0, 0x06, 0x26, 0x04, 0xf7, 0x80, 0x04, 0x2e, 0x04,
+ 0x08, 0x51, 0x04, 0x60, 0x08, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62,
+ 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x02, 0xef, 0x80, 0x04,
+ 0x2e, 0x02, 0x10, 0x51, 0x02, 0x60, 0x00, 0x70, 0x3f, 0x71, 0xc0,
+ 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50,
+ 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x02, 0x7f,
+ 0x80, 0x04, 0x2e, 0x02, 0x80, 0x51, 0x02, 0x60, 0x00, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x10, 0x70,
+ 0x3f, 0x71, 0x80, 0x5d, 0xd3, 0x08, 0x5d, 0xd0, 0x08, 0x62, 0xd0,
+ 0x00, 0x51, 0x08, 0x60, 0xd3, 0x2e, 0x05, 0x80, 0x49, 0xd7, 0x08,
+ 0xa0, 0x09, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x00, 0x80, 0x08, 0x49,
+ 0xd7, 0x20, 0xa0, 0x03, 0x80, 0xac, 0x51, 0x05, 0x21, 0x0e, 0xe0,
+ 0x01, 0x80, 0x11, 0x80, 0x6d, 0x80, 0x7f, 0x80, 0x4d, 0x80, 0x9c,
+ 0x80, 0x9a, 0x80, 0x98, 0x80, 0x96, 0x80, 0x9d, 0x5d, 0xd8, 0x21,
+ 0xfe, 0x39, 0x40, 0xa0, 0x06, 0x62, 0xd7, 0x00, 0x80, 0x90, 0x49,
+ 0xd8, 0x01, 0xb0, 0x15, 0x55, 0x0c, 0x02, 0x26, 0x07, 0x00, 0x26,
+ 0x06, 0x00, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x62, 0xd7, 0x10,
+ 0x80, 0x77, 0x55, 0x0c, 0x01, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x06,
+ 0x5f, 0x07, 0x06, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00, 0x60,
+ 0xd8, 0x76, 0x07, 0x62, 0xd7, 0x14, 0x80, 0x5b, 0x51, 0x0a, 0x78,
+ 0x3a, 0x07, 0xc0, 0x0f, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00,
+ 0x60, 0xd8, 0x76, 0x07, 0x2e, 0x05, 0x20, 0x60, 0xd8, 0x62, 0xd7,
+ 0x04, 0x80, 0x3f, 0x5d, 0xd8, 0x3a, 0x0a, 0xd0, 0x2b, 0xa0, 0x29,
+ 0x53, 0x07, 0x53, 0x06, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x80,
+ 0x18, 0x51, 0x0b, 0x78, 0x3a, 0x07, 0xc0, 0x16, 0x51, 0x09, 0x02,
+ 0x07, 0x5c, 0x5d, 0xd8, 0x54, 0x00, 0x2e, 0x05, 0x10, 0x76, 0x07,
+ 0x80, 0x01, 0x62, 0xd7, 0x10, 0x80, 0x0f, 0x62, 0xd7, 0x00, 0x80,
+ 0x0a, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x00, 0x55, 0x0c, 0x00, 0x18,
+ 0x60, 0xd0, 0x18, 0x60, 0xd3, 0x20, 0x18, 0x7e, 0x62, 0xd0, 0x00,
+ 0x71, 0x10, 0x41, 0x04, 0xfc, 0x43, 0x05, 0x03, 0x70, 0xef, 0x26,
+ 0x03, 0xfc, 0x51, 0x03, 0x60, 0x04, 0x55, 0x0c, 0x00, 0x90, 0x28,
+ 0x90, 0x2d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x00, 0x53, 0x06,
+ 0x71, 0x10, 0x43, 0x04, 0x03, 0x43, 0x05, 0x03, 0x70, 0xef, 0x2e,
+ 0x03, 0x03, 0x51, 0x03, 0x60, 0x04, 0x7f, 0x62, 0xd0, 0x00, 0x51,
+ 0x05, 0x21, 0xb0, 0x26, 0x05, 0x4f, 0x7f, 0x41, 0xe0, 0x7f, 0x43,
+ 0xe0, 0x80, 0x7f, 0x43, 0xd6, 0x31, 0x7f, 0x62, 0xd0, 0x00, 0x4f,
+ 0x52, 0xfd, 0x53, 0x0a, 0x52, 0xfc, 0x53, 0x0b, 0x52, 0xfb, 0x53,
+ 0x09, 0x52, 0xfa, 0x53, 0x08, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08,
+ 0x5d, 0xa4, 0x04, 0x1b, 0x5d, 0xa5, 0x0c, 0x1a, 0x55, 0x1c, 0x01,
+ 0x18, 0x7e, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x53, 0x1e,
+ 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x7b, 0x62, 0xd3, 0x00, 0x13,
+ 0x60, 0x62, 0xd3, 0x00, 0x54, 0x68, 0x62, 0xd3, 0x00, 0x52, 0x7a,
+ 0x62, 0xd3, 0x00, 0x1b, 0x5f, 0x62, 0xd3, 0x00, 0x54, 0x67, 0x48,
+ 0x67, 0x80, 0xb0, 0x33, 0x3d, 0x67, 0x00, 0xb0, 0x7b, 0x51, 0x0d,
+ 0x3b, 0x68, 0xc0, 0x75, 0x52, 0x68, 0x58, 0x1e, 0x01, 0x00, 0x6d,
+ 0x62, 0xd3, 0x00, 0x05, 0x4e, 0xc0, 0x09, 0x51, 0x0f, 0x3b, 0x4e,
+ 0xd0, 0x12, 0xa0, 0x10, 0x56, 0x4e, 0x00, 0x5b, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x07, 0x60, 0x01, 0x0f, 0x5f, 0x00, 0x80, 0x41, 0x3d,
+ 0x67, 0xff, 0xb0, 0x09, 0x50, 0xff, 0x12, 0x0e, 0x3b, 0x68, 0xc0,
+ 0x20, 0x62, 0xd3, 0x00, 0x56, 0x68, 0x00, 0x56, 0x67, 0x00, 0x5b,
+ 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x5b, 0x78, 0xd0, 0x03, 0x50,
+ 0x00, 0x54, 0x5b, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c, 0x62,
+ 0xd3, 0x00, 0x52, 0x7b, 0x62, 0xd3, 0x00, 0x54, 0x60, 0x62, 0xd3,
+ 0x00, 0x52, 0x7a, 0x62, 0xd3, 0x00, 0x54, 0x5f, 0x51, 0x1e, 0x64,
+ 0x5c, 0x62, 0xd3, 0x00, 0x56, 0x68, 0x00, 0x56, 0x67, 0x00, 0x5b,
+ 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x12, 0x54, 0x5b, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x08,
+ 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x52, 0x53, 0x19, 0x55, 0x18, 0x00,
+ 0x18, 0x08, 0x90, 0x7e, 0x62, 0xd3, 0x00, 0x23, 0x56, 0xb0, 0x2c,
+ 0x51, 0x10, 0x04, 0x19, 0x0e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x52, 0x68, 0x12, 0x19, 0x52, 0x67, 0x1a, 0x18, 0xc0,
+ 0x39, 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x57, 0x78, 0x54,
+ 0x57, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x3e, 0x80, 0x18, 0x51,
+ 0x10, 0x14, 0x19, 0x1e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3,
+ 0x00, 0x52, 0x68, 0x12, 0x19, 0x52, 0x67, 0x1a, 0x18, 0xc0, 0x0e,
+ 0x5b, 0x67, 0x90, 0x31, 0x62, 0xd3, 0x00, 0x2d, 0x56, 0x50, 0x01,
+ 0x80, 0x24, 0x5b, 0x67, 0x08, 0x90, 0x23, 0x73, 0x62, 0xd3, 0x00,
+ 0x25, 0x56, 0x62, 0xd3, 0x00, 0x20, 0x51, 0x11, 0x54, 0x57, 0x50,
+ 0x00, 0x80, 0x0d, 0x5b, 0x67, 0x90, 0x0d, 0x73, 0x62, 0xd3, 0x00,
+ 0x25, 0x56, 0x50, 0x00, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x67,
+ 0x67, 0x67, 0x5c, 0x18, 0x21, 0x07, 0xf0, 0x01, 0x7f, 0x01, 0x02,
+ 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x70, 0xbf, 0x70, 0xbf, 0x62,
+ 0xd3, 0x00, 0x50, 0x04, 0x78, 0x08, 0x5c, 0x56, 0x52, 0x32, 0x18,
+ 0x78, 0xdf, 0xf8, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x91, 0x99,
+ 0x70, 0xbf, 0x18, 0x08, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x7b,
+ 0x62, 0xd3, 0x00, 0x54, 0x60, 0x62, 0xd3, 0x00, 0x52, 0x7a, 0x62,
+ 0xd3, 0x00, 0x54, 0x5f, 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x14, 0x00, 0x50, 0x04, 0x78,
+ 0x08, 0x9f, 0x0e, 0x39, 0x01, 0xb0, 0x04, 0x55, 0x14, 0x01, 0x18,
+ 0x78, 0xdf, 0xf3, 0x51, 0x14, 0x7f, 0x50, 0x04, 0x78, 0x08, 0x9e,
+ 0x3e, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x98, 0x90, 0x91, 0x92, 0x93,
+ 0x94, 0x95, 0x96, 0x97, 0xd8, 0xd9, 0xda, 0xdb, 0xdf, 0x00, 0x01,
+ 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x70, 0xbf, 0x62, 0xd0,
+ 0x00, 0x62, 0xd3, 0x00, 0x57, 0x00, 0x56, 0x56, 0x00, 0x79, 0xdf,
+ 0xfb, 0x62, 0xd3, 0x00, 0x57, 0x03, 0x50, 0x02, 0x54, 0x57, 0x79,
+ 0xdf, 0xfc, 0x62, 0xd3, 0x00, 0x50, 0x0a, 0x57, 0x03, 0x54, 0x5b,
+ 0x79, 0xdf, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x55, 0x0d, 0x28, 0x55,
+ 0x0e, 0x05, 0x55, 0x0f, 0x0f, 0x55, 0x10, 0x01, 0x55, 0x11, 0x02,
+ 0x55, 0x12, 0x0a, 0x55, 0x22, 0x05, 0x55, 0x1f, 0x64, 0x43, 0x61,
+ 0x0d, 0x57, 0x00, 0x50, 0x02, 0x90, 0x95, 0x50, 0x05, 0xff, 0x98,
+ 0x29, 0x00, 0x60, 0xa9, 0x62, 0xa0, 0x08, 0x43, 0xa2, 0x04, 0x62,
+ 0xa3, 0x70, 0x43, 0x7a, 0x01, 0x43, 0xaa, 0x02, 0x43, 0xdf, 0x01,
+ 0x50, 0x01, 0x57, 0x09, 0x90, 0x20, 0x90, 0x55, 0x57, 0x01, 0x50,
+ 0xb3, 0x91, 0x44, 0x50, 0x01, 0x57, 0x0e, 0x90, 0x12, 0x90, 0x47,
+ 0x7f, 0x53, 0x22, 0xff, 0x67, 0x29, 0x00, 0x60, 0xa9, 0x51, 0x21,
+ 0x58, 0x20, 0x90, 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21, 0x03, 0x53,
+ 0x21, 0x64, 0x64, 0x64, 0x64, 0x64, 0x29, 0x80, 0x60, 0xa1, 0x5b,
+ 0x78, 0x21, 0x0f, 0x29, 0x08, 0x74, 0x53, 0x20, 0x12, 0x22, 0x02,
+ 0x21, 0x5c, 0x50, 0x00, 0x53, 0x1d, 0x53, 0x23, 0x29, 0x01, 0x79,
+ 0xa0, 0x08, 0x64, 0x6b, 0x1d, 0x6b, 0x23, 0x8f, 0xf5, 0x60, 0xb5,
+ 0x51, 0x1d, 0x60, 0xb4, 0x7f, 0x50, 0x04, 0x78, 0x08, 0x90, 0x0f,
+ 0x90, 0x41, 0x18, 0x78, 0xdf, 0xf8, 0x7f, 0x01, 0x04, 0x01, 0x10,
+ 0x01, 0x20, 0x01, 0x80, 0x64, 0x5c, 0xff, 0xf4, 0x4b, 0x74, 0xff,
+ 0xf0, 0x7f, 0x62, 0xd0, 0x00, 0x53, 0x1d, 0x10, 0x5b, 0x64, 0x64,
+ 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x2a, 0x1d, 0x61, 0x01, 0x36, 0x1d,
+ 0xff, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x36, 0x1d, 0xff, 0x18,
+ 0xfe, 0xef, 0x5c, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef,
+ 0x7f, 0x62, 0xd0, 0x00, 0x10, 0x73, 0x53, 0x1d, 0x71, 0x10, 0x5b,
+ 0xfe, 0xd9, 0x5c, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x70, 0xef,
+ 0x18, 0x64, 0x64, 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x22, 0x1d, 0x61,
+ 0x01, 0x36, 0x1d, 0xff, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70,
+ 0xef, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53, 0x1e, 0x50, 0x00,
+ 0x53, 0x1a, 0x53, 0x1b, 0x51, 0x1e, 0x5c, 0x62, 0xd3, 0x00, 0x52,
+ 0x24, 0x53, 0x1f, 0x43, 0xa0, 0x01, 0x51, 0x1f, 0x60, 0xfd, 0x41,
+ 0xa3, 0xdf, 0x51, 0x1e, 0x9f, 0x7a, 0x9f, 0x81, 0x58, 0x23, 0x55,
+ 0x1c, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x43, 0xb3, 0x01,
+ 0x51, 0x1c, 0xaf, 0xfd, 0x79, 0xdf, 0xee, 0x51, 0x1e, 0x9f, 0x5f,
+ 0x9f, 0x91, 0x43, 0xa3, 0x20, 0x41, 0xa0, 0xfe, 0x62, 0xfd, 0x00,
+ 0x50, 0xff, 0x4c, 0x1b, 0x14, 0x1b, 0x51, 0x20, 0x11, 0x08, 0xfe,
+ 0x66, 0x4c, 0x1a, 0x1c, 0x1a, 0xd0, 0x07, 0x55, 0x1a, 0x00, 0x55,
+ 0x1b, 0x00, 0x51, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x1b,
+ 0x54, 0x7b, 0x51, 0x1a, 0x54, 0x7a, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x08, 0x9f, 0x86, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x70, 0xbf, 0x62,
+ 0xd0, 0x00, 0x53, 0x29, 0x5a, 0x28, 0x55, 0x1e, 0x03, 0x62, 0xd3,
+ 0x00, 0x58, 0x1e, 0x56, 0x24, 0x80, 0x55, 0x2b, 0x08, 0x55, 0x2a,
+ 0x80, 0x51, 0x1e, 0x9f, 0x63, 0x51, 0x1e, 0x9f, 0x5f, 0x70, 0xbf,
+ 0x58, 0x1e, 0x62, 0xd3, 0x00, 0x51, 0x1b, 0x3a, 0x29, 0x51, 0x1a,
+ 0x1a, 0x28, 0xd0, 0x06, 0x51, 0x2a, 0x73, 0x25, 0x24, 0x68, 0x2a,
+ 0x26, 0x2a, 0x7f, 0x51, 0x2a, 0x2d, 0x24, 0x7a, 0x2b, 0xbf, 0xd6,
+ 0x7a, 0x1e, 0xdf, 0xc4, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x10, 0x4f,
+ 0x38, 0x02, 0x62, 0xd0, 0x00, 0x55, 0xb9, 0x00, 0x10, 0x7c, 0x05,
+ 0x28, 0x7c, 0x05, 0x05, 0x7c, 0x04, 0xe2, 0x7c, 0x04, 0xbf, 0x20,
+ 0x7c, 0x16, 0x44, 0x10, 0x7c, 0x03, 0x7c, 0x20, 0x43, 0x00, 0x08,
+ 0x62, 0xd0, 0x00, 0x55, 0x2c, 0x08, 0x55, 0x2d, 0x0e, 0x55, 0x2e,
+ 0x08, 0x55, 0x30, 0x32, 0x55, 0x31, 0x04, 0x10, 0x50, 0x00, 0x08,
+ 0x50, 0x2c, 0x08, 0x50, 0x05, 0x08, 0x50, 0x22, 0x08, 0x7c, 0x06,
+ 0x7a, 0x38, 0xfc, 0x7c, 0x06, 0x2e, 0x7c, 0x06, 0x6f, 0x20, 0x71,
+ 0x10, 0x41, 0x04, 0xfc, 0x41, 0x05, 0xfc, 0x71, 0x01, 0x10, 0x70,
+ 0xcf, 0x7c, 0x08, 0x7f, 0x20, 0x62, 0xd0, 0x00, 0x55, 0xb4, 0x00,
+ 0x93, 0x17, 0x10, 0x7c, 0x08, 0x05, 0x20, 0x80, 0xc7, 0x7c, 0x17,
+ 0xfe, 0x95, 0xa1, 0x62, 0xd0, 0x00, 0x3c, 0xbd, 0x01, 0xb0, 0x09,
+ 0x50, 0x00, 0x08, 0x7c, 0x1a, 0xb0, 0x38, 0xff, 0x10, 0x7c, 0x08,
+ 0x43, 0x20, 0x39, 0x00, 0xa0, 0x7c, 0x62, 0xd0, 0x00, 0x3c, 0xb1,
+ 0x00, 0xb0, 0x74, 0x51, 0xaf, 0x11, 0x4a, 0x51, 0xae, 0x19, 0x01,
+ 0xd0, 0x12, 0x7c, 0x16, 0x62, 0x39, 0xe1, 0xa0, 0x16, 0x62, 0xd0,
+ 0x00, 0x76, 0xaf, 0x0e, 0xae, 0x00, 0x80, 0x0c, 0x62, 0xd0, 0x00,
+ 0x55, 0xaf, 0x00, 0x55, 0xae, 0x00, 0x90, 0x81, 0x62, 0xd0, 0x00,
+ 0x3c, 0xbb, 0xf0, 0xd0, 0x03, 0x76, 0xbb, 0x62, 0xd0, 0x00, 0x51,
+ 0x31, 0x21, 0x0f, 0x53, 0x79, 0x51, 0xbb, 0x3a, 0x79, 0xb0, 0x5f,
+ 0x7c, 0x16, 0x62, 0x62, 0xd0, 0x00, 0x53, 0xbc, 0x3c, 0xbc, 0xe1,
+ 0xa0, 0x20, 0x3c, 0xb5, 0x01, 0xb0, 0x04, 0x55, 0xb0, 0x01, 0x62,
+ 0xd0, 0x00, 0x55, 0xb5, 0x00, 0x55, 0xb8, 0x01, 0x7c, 0x16, 0xf7,
+ 0x62, 0xd0, 0x00, 0x55, 0xb2, 0x01, 0x55, 0xb3, 0x03, 0x80, 0x33,
+ 0x62, 0xd0, 0x00, 0x55, 0xbb, 0x00, 0x80, 0x2b, 0x62, 0xd0, 0x00,
+ 0x55, 0xaf, 0x00, 0x55, 0xae, 0x00, 0x55, 0xb0, 0x00, 0x55, 0xb7,
+ 0x00, 0x55, 0xb8, 0x00, 0x3c, 0xb2, 0x01, 0xb0, 0x14, 0x7a, 0xb3,
+ 0x3c, 0xb3, 0x00, 0xb0, 0x0d, 0x7c, 0x17, 0x7f, 0x62, 0xd0, 0x00,
+ 0x55, 0xb2, 0x00, 0x55, 0xbb, 0x00, 0x7c, 0x18, 0xe4, 0x8f, 0x39,
+ 0x38, 0xfe, 0x20, 0x8f, 0xff, 0x10, 0x4f, 0x38, 0x24, 0x62, 0xd0,
+ 0x00, 0x3c, 0xb9, 0x00, 0xb0, 0x05, 0x51, 0xaa, 0x53, 0x24, 0x56,
+ 0x19, 0x00, 0x81, 0x5d, 0x56, 0x00, 0x00, 0x81, 0x51, 0x62, 0xd0,
+ 0x00, 0x3c, 0xb9, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x78, 0x55,
+ 0x79, 0x00, 0x06, 0x78, 0xaa, 0x7c, 0x1c, 0x33, 0x52, 0x00, 0x53,
+ 0x76, 0x55, 0x77, 0x00, 0x06, 0x76, 0x24, 0x7c, 0x1c, 0xc9, 0x10,
+ 0x52, 0x00, 0x7c, 0x09, 0xb9, 0x20, 0x10, 0x7c, 0x06, 0x64, 0x20,
+ 0x39, 0x00, 0xbf, 0xf1, 0x62, 0xd0, 0x00, 0x3c, 0xb9, 0x01, 0xb0,
+ 0xcf, 0x52, 0x00, 0x54, 0x23, 0x56, 0x22, 0x00, 0x3d, 0x22, 0x00,
+ 0xb0, 0x06, 0x3d, 0x23, 0x00, 0xa0, 0x21, 0x3d, 0x22, 0x00, 0xb0,
+ 0x06, 0x3d, 0x23, 0x01, 0xa0, 0x38, 0x3d, 0x22, 0x00, 0xb0, 0x06,
+ 0x3d, 0x23, 0x02, 0xa0, 0x66, 0x3d, 0x22, 0x00, 0xb0, 0x06, 0x3d,
+ 0x23, 0x03, 0xa0, 0x89, 0x80, 0x9e, 0x62, 0xd0, 0x00, 0x51, 0x7a,
+ 0x08, 0x51, 0x7b, 0x08, 0x50, 0x00, 0x08, 0x50, 0x01, 0x08, 0x7c,
+ 0x1b, 0xd0, 0x38, 0xfc, 0x51, 0x71, 0x62, 0xd0, 0x00, 0x53, 0x7b,
+ 0x51, 0x70, 0x53, 0x7a, 0x80, 0x7d, 0x62, 0xd0, 0x00, 0x51, 0x7c,
+ 0x08, 0x51, 0x7d, 0x08, 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x7c,
+ 0x1b, 0xd0, 0x38, 0xfc, 0x51, 0x71, 0x53, 0x78, 0x51, 0x70, 0x53,
+ 0x79, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x79, 0x08, 0x51,
+ 0x78, 0x08, 0x7c, 0x1b, 0x8c, 0x18, 0x62, 0xd0, 0x00, 0x53, 0x7d,
+ 0x18, 0x53, 0x7c, 0x38, 0xfe, 0x80, 0x45, 0x62, 0xd0, 0x00, 0x51,
+ 0x7f, 0x08, 0x51, 0x7e, 0x53, 0x79, 0x18, 0x53, 0x78, 0x65, 0x78,
+ 0x6b, 0x79, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x79, 0x08,
+ 0x51, 0x78, 0x08, 0x7c, 0x1b, 0x8c, 0x18, 0x62, 0xd0, 0x00, 0x53,
+ 0x7f, 0x18, 0x53, 0x7e, 0x38, 0xfe, 0x80, 0x18, 0x62, 0xd0, 0x00,
+ 0x51, 0x80, 0x08, 0x51, 0x81, 0x08, 0x50, 0x00, 0x08, 0x50, 0x01,
+ 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c, 0x86, 0x62, 0xd0,
+ 0x00, 0x55, 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52, 0x00,
+ 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08,
+ 0x50, 0x06, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c, 0x3f,
+ 0x53, 0x79, 0x52, 0x19, 0x53, 0x76, 0x55, 0x77, 0x00, 0x65, 0x76,
+ 0x6b, 0x77, 0x7c, 0x1c, 0x6a, 0x53, 0x79, 0x7c, 0x1c, 0xbd, 0x06,
+ 0x76, 0x7a, 0x0e, 0x77, 0x00, 0x51, 0x77, 0x7c, 0x1c, 0x28, 0x7c,
+ 0x1c, 0x52, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xce, 0xac, 0x77, 0x19,
+ 0x3d, 0x19, 0x03, 0xce, 0xa0, 0x56, 0x00, 0x00, 0x80, 0xc0, 0x62,
+ 0xd0, 0x00, 0x55, 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52,
+ 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c,
+ 0x3f, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1a, 0x3e, 0x78, 0x54, 0x1b,
+ 0x5a, 0x78, 0x06, 0x78, 0x03, 0x52, 0x00, 0x53, 0x76, 0x50, 0x00,
+ 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c,
+ 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c, 0x3f, 0x60, 0xd4, 0x3e, 0x78,
+ 0x54, 0x1c, 0x3e, 0x78, 0x54, 0x1d, 0x5a, 0x78, 0x06, 0x78, 0x05,
+ 0x52, 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c,
+ 0x1c, 0x3f, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1e, 0x3e, 0x78, 0x54,
+ 0x1f, 0x50, 0x03, 0x08, 0x5a, 0x78, 0x06, 0x78, 0x1a, 0x08, 0x51,
+ 0x78, 0x08, 0x7c, 0x19, 0xe5, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51,
+ 0x78, 0x54, 0x21, 0x51, 0x79, 0x54, 0x20, 0x7c, 0x1c, 0x00, 0x7c,
+ 0x1c, 0x5f, 0x7c, 0x1c, 0xa2, 0x06, 0x78, 0x5f, 0x7c, 0x1c, 0xad,
+ 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x82, 0x7c, 0x1c, 0x75, 0x51,
+ 0x78, 0x01, 0x8a, 0x7c, 0x1c, 0x75, 0x06, 0x78, 0x92, 0x7c, 0x1c,
+ 0xad, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xcf, 0x3d, 0x38, 0xdc, 0x20,
+ 0x7f, 0x10, 0x4f, 0x38, 0x24, 0x10, 0x57, 0x30, 0x50, 0x00, 0x7c,
+ 0x0a, 0x38, 0x20, 0x62, 0xd0, 0x00, 0x3c, 0xb9, 0x01, 0xb0, 0x13,
+ 0x51, 0x24, 0x53, 0x32, 0x51, 0x25, 0x53, 0x33, 0x51, 0x26, 0x53,
+ 0x34, 0x51, 0x27, 0x53, 0x35, 0x80, 0x14, 0x62, 0xd0, 0x00, 0x51,
+ 0xaa, 0x53, 0x24, 0x51, 0xab, 0x53, 0x25, 0x51, 0xac, 0x53, 0x26,
+ 0x51, 0xad, 0x53, 0x27, 0x10, 0x50, 0x00, 0x7c, 0x09, 0xb9, 0x20,
+ 0x56, 0x19, 0x00, 0x81, 0x5d, 0x56, 0x00, 0x00, 0x81, 0x51, 0x62,
+ 0xd0, 0x00, 0x3c, 0xb9, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x78,
+ 0x55, 0x79, 0x00, 0x06, 0x78, 0xaa, 0x7c, 0x1c, 0x33, 0x52, 0x00,
+ 0x53, 0x76, 0x55, 0x77, 0x00, 0x06, 0x76, 0x24, 0x7c, 0x1c, 0xc9,
+ 0x10, 0x52, 0x00, 0x7c, 0x09, 0xb9, 0x20, 0x10, 0x7c, 0x06, 0x64,
+ 0x20, 0x39, 0x00, 0xbf, 0xf1, 0x62, 0xd0, 0x00, 0x3c, 0xb9, 0x01,
+ 0xb0, 0xcf, 0x52, 0x00, 0x54, 0x23, 0x56, 0x22, 0x00, 0x3d, 0x22,
+ 0x00, 0xb0, 0x06, 0x3d, 0x23, 0x00, 0xa0, 0x21, 0x3d, 0x22, 0x00,
+ 0xb0, 0x06, 0x3d, 0x23, 0x01, 0xa0, 0x38, 0x3d, 0x22, 0x00, 0xb0,
+ 0x06, 0x3d, 0x23, 0x02, 0xa0, 0x66, 0x3d, 0x22, 0x00, 0xb0, 0x06,
+ 0x3d, 0x23, 0x03, 0xa0, 0x89, 0x80, 0x9e, 0x62, 0xd0, 0x00, 0x51,
+ 0x7a, 0x08, 0x51, 0x7b, 0x08, 0x50, 0x00, 0x08, 0x50, 0x01, 0x08,
+ 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x51, 0x71, 0x62, 0xd0, 0x00, 0x53,
+ 0x7b, 0x51, 0x70, 0x53, 0x7a, 0x80, 0x7d, 0x62, 0xd0, 0x00, 0x51,
+ 0x7c, 0x08, 0x51, 0x7d, 0x08, 0x50, 0x00, 0x08, 0x50, 0x03, 0x08,
+ 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x51, 0x71, 0x53, 0x78, 0x51, 0x70,
+ 0x53, 0x79, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x79, 0x08,
+ 0x51, 0x78, 0x08, 0x7c, 0x1b, 0x8c, 0x18, 0x62, 0xd0, 0x00, 0x53,
+ 0x7d, 0x18, 0x53, 0x7c, 0x38, 0xfe, 0x80, 0x45, 0x62, 0xd0, 0x00,
+ 0x51, 0x7f, 0x08, 0x51, 0x7e, 0x53, 0x79, 0x18, 0x53, 0x78, 0x65,
+ 0x78, 0x6b, 0x79, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x79,
+ 0x08, 0x51, 0x78, 0x08, 0x7c, 0x1b, 0x8c, 0x18, 0x62, 0xd0, 0x00,
+ 0x53, 0x7f, 0x18, 0x53, 0x7e, 0x38, 0xfe, 0x80, 0x18, 0x62, 0xd0,
+ 0x00, 0x51, 0x80, 0x08, 0x51, 0x81, 0x08, 0x50, 0x00, 0x08, 0x50,
+ 0x01, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c, 0x86, 0x62,
+ 0xd0, 0x00, 0x55, 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52,
+ 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c,
+ 0x3f, 0x53, 0x79, 0x52, 0x19, 0x53, 0x76, 0x55, 0x77, 0x00, 0x65,
+ 0x76, 0x6b, 0x77, 0x7c, 0x1c, 0x6a, 0x53, 0x79, 0x7c, 0x1c, 0xbd,
+ 0x06, 0x76, 0x7a, 0x0e, 0x77, 0x00, 0x51, 0x77, 0x7c, 0x1c, 0x28,
+ 0x7c, 0x1c, 0x52, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xce, 0xac, 0x77,
+ 0x19, 0x3d, 0x19, 0x03, 0xce, 0xa0, 0x56, 0x00, 0x00, 0x80, 0xc0,
+ 0x62, 0xd0, 0x00, 0x55, 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01,
+ 0x52, 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c,
+ 0x1c, 0x3f, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1a, 0x3e, 0x78, 0x54,
+ 0x1b, 0x5a, 0x78, 0x06, 0x78, 0x03, 0x52, 0x00, 0x53, 0x76, 0x50,
+ 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08,
+ 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x7c, 0x1c, 0x3f, 0x60, 0xd4, 0x3e,
+ 0x78, 0x54, 0x1c, 0x3e, 0x78, 0x54, 0x1d, 0x5a, 0x78, 0x06, 0x78,
+ 0x05, 0x52, 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc,
+ 0x7c, 0x1c, 0x3f, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1e, 0x3e, 0x78,
+ 0x54, 0x1f, 0x50, 0x03, 0x08, 0x5a, 0x78, 0x06, 0x78, 0x1a, 0x08,
+ 0x51, 0x78, 0x08, 0x7c, 0x19, 0xe5, 0x38, 0xfd, 0x62, 0xd0, 0x00,
+ 0x51, 0x78, 0x54, 0x21, 0x51, 0x79, 0x54, 0x20, 0x7c, 0x1c, 0x00,
+ 0x7c, 0x1c, 0x5f, 0x7c, 0x1c, 0xa2, 0x06, 0x78, 0x5f, 0x7c, 0x1c,
+ 0xad, 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x82, 0x7c, 0x1c, 0x75,
+ 0x51, 0x78, 0x01, 0x8a, 0x7c, 0x1c, 0x75, 0x06, 0x78, 0x92, 0x7c,
+ 0x1c, 0xad, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xcf, 0x3d, 0x56, 0x00,
+ 0x00, 0x80, 0x19, 0x7c, 0x1c, 0x0c, 0x06, 0x78, 0x24, 0x7c, 0x1c,
+ 0x33, 0x52, 0x00, 0x53, 0x76, 0x55, 0x77, 0x00, 0x06, 0x76, 0x32,
+ 0x7c, 0x1c, 0xc9, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xcf, 0xe4, 0x38,
+ 0xdc, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x07, 0x56, 0x02, 0x00, 0x62,
+ 0xd0, 0x00, 0x55, 0xb1, 0x00, 0x3c, 0xb9, 0x00, 0xb0, 0x05, 0x51,
+ 0xaa, 0x53, 0x24, 0x10, 0x50, 0x00, 0x7c, 0x09, 0xb9, 0x20, 0x56,
+ 0x00, 0x00, 0x81, 0x0b, 0x62, 0xd0, 0x00, 0x3c, 0xb9, 0x00, 0xb0,
+ 0x1b, 0x52, 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78, 0xaa,
+ 0x7c, 0x1c, 0x33, 0x52, 0x00, 0x53, 0x76, 0x55, 0x77, 0x00, 0x06,
+ 0x76, 0x24, 0x7c, 0x1c, 0xc9, 0x10, 0x52, 0x00, 0x7c, 0x09, 0xb9,
+ 0x20, 0x10, 0x7c, 0x06, 0x64, 0x20, 0x39, 0x00, 0xbf, 0xf1, 0x62,
+ 0xd0, 0x00, 0x3c, 0xb9, 0x01, 0xb0, 0xcf, 0x52, 0x00, 0x54, 0x04,
+ 0x56, 0x03, 0x00, 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x00,
+ 0xa0, 0x21, 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x01, 0xa0,
+ 0x38, 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x02, 0xa0, 0x66,
+ 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x03, 0xa0, 0x89, 0x80,
+ 0x9e, 0x62, 0xd0, 0x00, 0x51, 0x7a, 0x08, 0x51, 0x7b, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x01, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x51,
+ 0x71, 0x62, 0xd0, 0x00, 0x53, 0x7b, 0x51, 0x70, 0x53, 0x7a, 0x80,
+ 0x7d, 0x62, 0xd0, 0x00, 0x51, 0x7c, 0x08, 0x51, 0x7d, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x03, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x51,
+ 0x71, 0x53, 0x78, 0x51, 0x70, 0x53, 0x79, 0x50, 0x00, 0x08, 0x50,
+ 0x05, 0x08, 0x51, 0x79, 0x08, 0x51, 0x78, 0x08, 0x7c, 0x1b, 0x8c,
+ 0x18, 0x62, 0xd0, 0x00, 0x53, 0x7d, 0x18, 0x53, 0x7c, 0x38, 0xfe,
+ 0x80, 0x45, 0x62, 0xd0, 0x00, 0x51, 0x7f, 0x08, 0x51, 0x7e, 0x53,
+ 0x79, 0x18, 0x53, 0x78, 0x65, 0x78, 0x6b, 0x79, 0x50, 0x00, 0x08,
+ 0x50, 0x05, 0x08, 0x51, 0x79, 0x08, 0x51, 0x78, 0x08, 0x7c, 0x1b,
+ 0x8c, 0x18, 0x62, 0xd0, 0x00, 0x53, 0x7f, 0x18, 0x53, 0x7e, 0x38,
+ 0xfe, 0x80, 0x18, 0x62, 0xd0, 0x00, 0x51, 0x80, 0x08, 0x51, 0x81,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x01, 0x08, 0x7c, 0x1b, 0xd0, 0x38,
+ 0xfc, 0x7c, 0x1c, 0x86, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xce, 0xf2,
+ 0x56, 0x00, 0x00, 0x82, 0xa6, 0x62, 0xd0, 0x00, 0x3c, 0xbd, 0x02,
+ 0xa0, 0xb1, 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x5f, 0x7c, 0x1c,
+ 0x17, 0x06, 0x78, 0x7a, 0x7c, 0x1c, 0x33, 0x3e, 0x78, 0x53, 0x78,
+ 0x51, 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x16, 0x7c,
+ 0x1c, 0x00, 0x51, 0x78, 0x01, 0x5f, 0x7c, 0x1c, 0x17, 0x06, 0x78,
+ 0x7a, 0x7c, 0x1c, 0x33, 0x7c, 0x1d, 0x0b, 0x80, 0x17, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x7a, 0x7c, 0x1c, 0x17,
+ 0x06, 0x78, 0x5f, 0x7c, 0x1c, 0x33, 0x7c, 0x1d, 0x0b, 0x50, 0x2c,
+ 0x13, 0x04, 0x50, 0x01, 0x1b, 0x03, 0xc0, 0x57, 0x62, 0xd0, 0x00,
+ 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x92, 0x7c, 0x1c, 0x17, 0x06,
+ 0x78, 0x7a, 0x7c, 0x1c, 0x33, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76,
+ 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x16, 0x7c, 0x1c, 0x00,
+ 0x51, 0x78, 0x01, 0x92, 0x7c, 0x1c, 0x17, 0x06, 0x78, 0x7a, 0x7c,
+ 0x1c, 0x33, 0x7c, 0x1c, 0xfe, 0x80, 0x17, 0x62, 0xd0, 0x00, 0x7c,
+ 0x1c, 0x00, 0x51, 0x78, 0x01, 0x7a, 0x7c, 0x1c, 0x17, 0x06, 0x78,
+ 0x92, 0x7c, 0x1c, 0x33, 0x7c, 0x1c, 0xfe, 0x50, 0x2c, 0x13, 0x06,
+ 0x50, 0x01, 0x1b, 0x05, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x76, 0xb1,
+ 0x81, 0xec, 0x56, 0x01, 0x00, 0x80, 0x61, 0x62, 0xd0, 0x00, 0x7c,
+ 0x1c, 0x00, 0x51, 0x78, 0x01, 0x7a, 0x7c, 0x1c, 0x17, 0x06, 0x78,
+ 0x8a, 0x7c, 0x1c, 0x33, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76, 0x12,
+ 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x12, 0x7c, 0x1c, 0x00, 0x7c,
+ 0x1c, 0xd5, 0x06, 0x76, 0x01, 0x0e, 0x77, 0x00, 0x7c, 0x1c, 0x52,
+ 0x80, 0x2d, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01,
+ 0x7a, 0x7c, 0x1c, 0x17, 0x06, 0x78, 0x8a, 0x7c, 0x1c, 0x33, 0x3e,
+ 0x78, 0x12, 0x76, 0x51, 0x79, 0x1a, 0x77, 0xd0, 0x10, 0x7c, 0x1c,
+ 0x00, 0x7c, 0x1c, 0xd5, 0x16, 0x76, 0x01, 0x1e, 0x77, 0x00, 0x7c,
+ 0x1c, 0x52, 0x77, 0x01, 0x3d, 0x01, 0x06, 0xcf, 0x9c, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x8a, 0x7c, 0x1c, 0x17,
+ 0x06, 0x78, 0x82, 0x0e, 0x79, 0x00, 0x7c, 0x1c, 0x52, 0x7c, 0x1c,
+ 0x00, 0x51, 0x78, 0x01, 0x92, 0x7c, 0x1c, 0x17, 0x06, 0x78, 0x8a,
+ 0x0e, 0x79, 0x00, 0x7c, 0x1c, 0x52, 0x7c, 0x1c, 0x00, 0x51, 0x78,
+ 0x01, 0x7a, 0x7c, 0x1c, 0x17, 0x06, 0x78, 0x92, 0x0e, 0x79, 0x00,
+ 0x7c, 0x1c, 0x52, 0x7c, 0x1c, 0x00, 0x7c, 0x1c, 0x5f, 0x53, 0x77,
+ 0x7c, 0x1d, 0x32, 0x53, 0x74, 0x08, 0x51, 0x75, 0x53, 0x73, 0x18,
+ 0x53, 0x72, 0x65, 0x72, 0x6b, 0x73, 0x06, 0x78, 0x8a, 0x7c, 0x1c,
+ 0x33, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x72, 0x04, 0x78, 0x51, 0x73,
+ 0x0c, 0x79, 0x51, 0x74, 0x04, 0x78, 0x51, 0x75, 0x0c, 0x79, 0x70,
+ 0xfb, 0x6e, 0x79, 0x6e, 0x78, 0x7c, 0x1c, 0xeb, 0x10, 0x52, 0x00,
+ 0x7c, 0x06, 0xa1, 0x20, 0x7c, 0x1c, 0x0c, 0x06, 0x78, 0x52, 0x0e,
+ 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x53, 0x78, 0x7c,
+ 0x1c, 0xbd, 0x06, 0x76, 0x67, 0x0e, 0x77, 0x00, 0x51, 0x77, 0x7c,
+ 0x1c, 0x28, 0x51, 0x78, 0x12, 0x76, 0x50, 0x00, 0x1a, 0x77, 0xd0,
+ 0x1b, 0x55, 0x79, 0x01, 0x52, 0x00, 0xa0, 0x09, 0x62, 0xd0, 0x00,
+ 0x65, 0x79, 0x78, 0xbf, 0xf9, 0x62, 0xd0, 0x00, 0x51, 0xb4, 0x2a,
+ 0x79, 0x53, 0xb4, 0x80, 0x1b, 0x62, 0xd0, 0x00, 0x55, 0x79, 0x01,
+ 0x52, 0x00, 0xa0, 0x09, 0x62, 0xd0, 0x00, 0x65, 0x79, 0x78, 0xbf,
+ 0xf9, 0x62, 0xd0, 0x00, 0x51, 0x79, 0x73, 0x24, 0xb4, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x00, 0x51, 0x78, 0x01, 0x7a, 0x7c, 0x1c, 0x17,
+ 0x06, 0x78, 0x5f, 0x7c, 0x1c, 0x33, 0x3e, 0x78, 0x53, 0x78, 0x51,
+ 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x25, 0x52, 0x00,
+ 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78, 0xa2, 0x0e, 0x79, 0x00,
+ 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x7a, 0x78, 0x53, 0x77, 0x06,
+ 0x77, 0x01, 0x51, 0x79, 0x60, 0xd5, 0x51, 0x77, 0x3f, 0x78, 0x80,
+ 0x12, 0x97, 0xf7, 0x40, 0x06, 0x78, 0xa2, 0x0e, 0x79, 0x00, 0x51,
+ 0x79, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x78, 0x97, 0xe6, 0x40, 0x06,
+ 0x78, 0xa2, 0x7c, 0x1c, 0x33, 0x50, 0x05, 0x3a, 0x79, 0xd0, 0x41,
+ 0x97, 0xcb, 0x40, 0x51, 0x78, 0x01, 0x5f, 0x53, 0x76, 0x51, 0x79,
+ 0x09, 0x00, 0x53, 0x77, 0x06, 0x78, 0x7a, 0x97, 0xec, 0x40, 0x3e,
+ 0x78, 0x53, 0x78, 0x51, 0x77, 0x7c, 0x1d, 0x32, 0x02, 0x78, 0x53,
+ 0x78, 0x51, 0x75, 0x0a, 0x79, 0x53, 0x79, 0x7c, 0x1c, 0xeb, 0x52,
+ 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78, 0xa2, 0x0e, 0x79,
+ 0x00, 0x51, 0x79, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x78, 0x77, 0x00,
+ 0x3d, 0x00, 0x04, 0xcd, 0x57, 0x56, 0x00, 0x00, 0x81, 0x73, 0x62,
+ 0xd0, 0x00, 0x3c, 0xb9, 0x01, 0xb0, 0xd9, 0x52, 0x00, 0x54, 0x04,
+ 0x56, 0x03, 0x00, 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x00,
+ 0xa0, 0x21, 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x01, 0xa0,
+ 0x38, 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x02, 0xa0, 0x66,
+ 0x3d, 0x03, 0x00, 0xb0, 0x06, 0x3d, 0x04, 0x03, 0xa0, 0x8d, 0x80,
+ 0xbe, 0x62, 0xd0, 0x00, 0x51, 0x7a, 0x08, 0x51, 0x7b, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x01, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x51,
+ 0x71, 0x62, 0xd0, 0x00, 0x53, 0x3f, 0x51, 0x70, 0x53, 0x3e, 0x80,
+ 0x9d, 0x62, 0xd0, 0x00, 0x51, 0x7c, 0x08, 0x51, 0x7d, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x05, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc, 0x51,
+ 0x71, 0x53, 0x78, 0x51, 0x70, 0x53, 0x79, 0x50, 0x00, 0x08, 0x50,
+ 0x03, 0x08, 0x51, 0x79, 0x08, 0x51, 0x78, 0x08, 0x7c, 0x1b, 0x8c,
+ 0x18, 0x62, 0xd0, 0x00, 0x53, 0x41, 0x18, 0x53, 0x40, 0x38, 0xfe,
+ 0x80, 0x65, 0x62, 0xd0, 0x00, 0x51, 0x7e, 0x08, 0x51, 0x7f, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x7c, 0x1b, 0xd0, 0x38, 0xfc,
+ 0x51, 0x71, 0x53, 0x78, 0x51, 0x70, 0x53, 0x79, 0x70, 0xfb, 0x6e,
+ 0x79, 0x6e, 0x78, 0x51, 0x78, 0x08, 0x51, 0x79, 0x62, 0xd0, 0x00,
+ 0x53, 0x42, 0x18, 0x53, 0x43, 0x80, 0x34, 0x62, 0xd0, 0x00, 0x51,
+ 0x81, 0x08, 0x51, 0x80, 0x53, 0x79, 0x18, 0x53, 0x78, 0x65, 0x78,
+ 0x6b, 0x79, 0x51, 0x78, 0x08, 0x51, 0x79, 0x53, 0x44, 0x18, 0x53,
+ 0x45, 0x80, 0x17, 0x62, 0xd0, 0x00, 0x96, 0x9c, 0x40, 0x51, 0x78,
+ 0x01, 0x7a, 0x96, 0xac, 0x40, 0x06, 0x78, 0x3e, 0x0e, 0x79, 0x00,
+ 0x96, 0xde, 0x40, 0x62, 0xd0, 0x00, 0x96, 0x86, 0x40, 0x51, 0x78,
+ 0x01, 0x5f, 0x96, 0x96, 0x40, 0x51, 0x78, 0x01, 0x7a, 0x53, 0x74,
+ 0x51, 0x79, 0x97, 0x99, 0x40, 0x51, 0x76, 0x12, 0x74, 0x51, 0x77,
+ 0x1a, 0x75, 0xd0, 0x2b, 0x97, 0x24, 0x40, 0x51, 0x76, 0x01, 0x5f,
+ 0x53, 0x74, 0x51, 0x77, 0x97, 0x81, 0x40, 0x06, 0x76, 0x7a, 0x0e,
+ 0x77, 0x00, 0x51, 0x77, 0x60, 0xd4, 0x3e, 0x76, 0x53, 0x77, 0x3e,
+ 0x76, 0x12, 0x74, 0x54, 0x04, 0x51, 0x77, 0x1a, 0x75, 0x54, 0x03,
+ 0x80, 0x07, 0x56, 0x04, 0x00, 0x56, 0x03, 0x00, 0x62, 0xd0, 0x00,
+ 0x06, 0x78, 0x36, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd5, 0x52,
+ 0x03, 0x3f, 0x78, 0x52, 0x04, 0x3f, 0x78, 0x96, 0x22, 0x40, 0x51,
+ 0x78, 0x01, 0x5f, 0x96, 0x32, 0x40, 0x06, 0x78, 0x46, 0x0e, 0x79,
+ 0x00, 0x96, 0x64, 0x40, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xce, 0x8a,
+ 0x62, 0xd0, 0x00, 0x3c, 0xbd, 0x02, 0xa0, 0x1b, 0x3c, 0xb1, 0x00,
+ 0xa0, 0x16, 0x55, 0xbb, 0x00, 0x50, 0x75, 0x08, 0x50, 0x30, 0x08,
+ 0x90, 0x0e, 0x38, 0xfe, 0x7c, 0x0b, 0xc1, 0x10, 0x7c, 0x08, 0x5d,
+ 0x20, 0x38, 0xf9, 0x20, 0x7f, 0x10, 0x4f, 0x80, 0x02, 0x40, 0x62,
+ 0xd0, 0x00, 0x52, 0xfc, 0x53, 0x78, 0x52, 0xfb, 0x53, 0x79, 0x51,
+ 0x78, 0x11, 0x01, 0x54, 0xfc, 0x51, 0x79, 0x19, 0x00, 0x54, 0xfb,
+ 0x3c, 0x79, 0x00, 0xbf, 0xe4, 0x3c, 0x78, 0x00, 0xbf, 0xdf, 0x20,
+ 0x7f, 0x10, 0x7c, 0x05, 0x28, 0x7c, 0x05, 0x05, 0x7c, 0x04, 0xe2,
+ 0x7c, 0x04, 0xbf, 0x20, 0x7f, 0x10, 0x7c, 0x05, 0x24, 0x7c, 0x05,
+ 0x01, 0x7c, 0x04, 0xde, 0x7c, 0x04, 0xbb, 0x20, 0x7f, 0x10, 0x4f,
+ 0x38, 0x05, 0x62, 0xd0, 0x00, 0x51, 0x68, 0x54, 0x02, 0x51, 0x67,
+ 0x54, 0x01, 0x56, 0x04, 0x00, 0x56, 0x00, 0x00, 0x56, 0x03, 0x00,
+ 0x80, 0x61, 0x95, 0x8e, 0x40, 0x06, 0x78, 0x52, 0x0e, 0x79, 0x00,
+ 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x53, 0x78, 0x96, 0x2e, 0x40,
+ 0x06, 0x76, 0x67, 0x0e, 0x77, 0x00, 0x51, 0x77, 0x95, 0x8e, 0x40,
+ 0x51, 0x78, 0x12, 0x76, 0x50, 0x00, 0x1a, 0x77, 0xd0, 0x03, 0x77,
+ 0x03, 0x62, 0xd0, 0x00, 0x95, 0x54, 0x40, 0x06, 0x78, 0x67, 0x95,
+ 0x81, 0x40, 0x3e, 0x78, 0x53, 0x78, 0x52, 0x02, 0x12, 0x78, 0x52,
+ 0x01, 0x1a, 0x79, 0xd0, 0x1a, 0x95, 0x3d, 0x40, 0x06, 0x78, 0x67,
+ 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x01,
+ 0x3e, 0x78, 0x54, 0x02, 0x52, 0x00, 0x54, 0x04, 0x77, 0x00, 0x3d,
+ 0x00, 0x04, 0xcf, 0x9c, 0x50, 0x01, 0x3b, 0x03, 0xd0, 0x08, 0x62,
+ 0xd0, 0x00, 0x50, 0xe1, 0x80, 0x06, 0x52, 0x04, 0x62, 0xd0, 0x00,
+ 0x38, 0xfb, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x62, 0xd0, 0x00,
+ 0x3c, 0xb2, 0x00, 0xb0, 0x79, 0x70, 0xfe, 0x26, 0x2c, 0xf0, 0x51,
+ 0xbc, 0x01, 0x01, 0x53, 0x79, 0x51, 0x2c, 0x2a, 0x79, 0x53, 0x2c,
+ 0x71, 0x01, 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x41,
+ 0x00, 0xf7, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x64,
+ 0x62, 0xd0, 0x00, 0x20, 0x53, 0x79, 0x47, 0x79, 0x20, 0xa0, 0x03,
+ 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0xdd, 0x38,
+ 0xfe, 0x77, 0x00, 0x3d, 0x00, 0xc8, 0xcf, 0xdf, 0x56, 0x00, 0x00,
+ 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x53,
+ 0x79, 0x47, 0x79, 0x20, 0xb0, 0x03, 0x80, 0x12, 0x50, 0x00, 0x08,
+ 0x50, 0x14, 0x08, 0x9e, 0xb6, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00,
+ 0x1e, 0xcf, 0xdf, 0x62, 0xd0, 0x00, 0x51, 0x2c, 0x29, 0x08, 0x53,
+ 0x2c, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38,
+ 0x02, 0x62, 0xd0, 0x00, 0x3c, 0xb2, 0x01, 0xb0, 0x70, 0x70, 0xfe,
+ 0x26, 0x2c, 0xf0, 0x51, 0xbc, 0x01, 0x09, 0x53, 0x79, 0x51, 0x2c,
+ 0x2a, 0x79, 0x53, 0x2c, 0x71, 0x01, 0x10, 0x7c, 0x06, 0x64, 0x62,
+ 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56, 0x00, 0x00, 0x80, 0x1e,
+ 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x79, 0x47,
+ 0x79, 0x20, 0xa0, 0x03, 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14,
+ 0x08, 0x9e, 0x55, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00, 0xc8, 0xcf,
+ 0xdf, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x64, 0x62,
+ 0xd0, 0x00, 0x20, 0x53, 0x79, 0x47, 0x79, 0x20, 0xb0, 0x03, 0x80,
+ 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0x2e, 0x38, 0xfe,
+ 0x77, 0x00, 0x3d, 0x00, 0x1e, 0xcf, 0xdf, 0x43, 0x00, 0x08, 0x38,
+ 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x04, 0x62, 0xd0, 0x00, 0x51,
+ 0x2c, 0x21, 0xf0, 0x54, 0x00, 0x51, 0x2f, 0x54, 0x01, 0x3d, 0x00,
+ 0x10, 0xb0, 0x18, 0x55, 0xb5, 0x00, 0x55, 0x9b, 0x00, 0x55, 0x9a,
+ 0x00, 0x55, 0x9d, 0x00, 0x55, 0x9c, 0x00, 0x56, 0x00, 0x00, 0x26,
+ 0x2c, 0x0f, 0x80, 0xb6, 0x3d, 0x00, 0x20, 0xb0, 0x1e, 0x62, 0xd0,
+ 0x00, 0x55, 0xb5, 0x01, 0x55, 0xb6, 0x00, 0x55, 0x9b, 0x08, 0x55,
+ 0x9a, 0x08, 0x55, 0x9d, 0x08, 0x55, 0x9c, 0x08, 0x56, 0x00, 0x00,
+ 0x26, 0x2c, 0x0f, 0x80, 0x94, 0x3d, 0x00, 0x40, 0xb0, 0x0f, 0x62,
+ 0xd0, 0x00, 0x55, 0xbd, 0x02, 0x56, 0x00, 0x00, 0x26, 0x2c, 0x0f,
+ 0x80, 0x81, 0x3d, 0x00, 0x50, 0xb0, 0x7c, 0x52, 0x01, 0x54, 0x03,
+ 0x56, 0x02, 0x00, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x01,
+ 0xa0, 0x17, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x02, 0xa0,
+ 0x27, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x04, 0xa0, 0x38,
+ 0x80, 0x46, 0x62, 0xd0, 0x00, 0x55, 0xb9, 0x01, 0x7c, 0x0e, 0x04,
+ 0x62, 0xd0, 0x00, 0x51, 0x31, 0x29, 0x80, 0x53, 0x31, 0x56, 0x00,
+ 0x00, 0x26, 0x2c, 0x0f, 0x80, 0x2c, 0x62, 0xd0, 0x00, 0x51, 0x30,
+ 0x53, 0x52, 0x51, 0x30, 0x53, 0x53, 0x51, 0x30, 0x53, 0x54, 0x51,
+ 0x30, 0x53, 0x55, 0x56, 0x00, 0x00, 0x26, 0x2c, 0x0f, 0x80, 0x11,
+ 0x62, 0xd0, 0x00, 0x51, 0x30, 0x53, 0x0e, 0x55, 0x0d, 0x00, 0x56,
+ 0x00, 0x00, 0x26, 0x2c, 0x0f, 0x56, 0x01, 0x00, 0x62, 0xd0, 0x00,
+ 0x55, 0x2d, 0x0e, 0x55, 0x2e, 0x08, 0x55, 0x2f, 0x00, 0x38, 0xfc,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x04, 0x62, 0xd0, 0x00, 0x3c, 0xb5,
+ 0x00, 0xa0, 0x13, 0x9d, 0x52, 0x62, 0xd0, 0x00, 0x3c, 0xb6, 0x00,
+ 0xb0, 0xe8, 0x55, 0xb6, 0x01, 0x7c, 0x0b, 0xc1, 0x80, 0xe0, 0x62,
+ 0xd0, 0x00, 0x3c, 0xb7, 0x00, 0xb0, 0x27, 0x3c, 0xb0, 0x01, 0xb0,
+ 0x22, 0x51, 0xbc, 0x53, 0x78, 0x55, 0x79, 0x00, 0x65, 0x78, 0x6b,
+ 0x79, 0x06, 0x78, 0x67, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4,
+ 0x3e, 0x78, 0x54, 0x01, 0x3e, 0x78, 0x54, 0x02, 0x51, 0xbc, 0x54,
+ 0x00, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x9a, 0xd0, 0x08, 0x10,
+ 0x7c, 0x05, 0x28, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x05, 0x24, 0x20,
+ 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x9b, 0xd0, 0x08, 0x10, 0x7c,
+ 0x05, 0x05, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x05, 0x01, 0x20, 0x62,
+ 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x9c, 0xd0, 0x08, 0x10, 0x7c, 0x04,
+ 0xe2, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0xde, 0x20, 0x62, 0xd0,
+ 0x00, 0x50, 0x01, 0x3a, 0x9d, 0xd0, 0x08, 0x10, 0x7c, 0x04, 0xbf,
+ 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0xbb, 0x20, 0x7c, 0x10, 0x9a,
+ 0x62, 0xd0, 0x00, 0x3c, 0xb7, 0x00, 0xb0, 0x53, 0x3c, 0xb0, 0x01,
+ 0xb0, 0x4e, 0x3c, 0xb1, 0x00, 0xb0, 0x40, 0x92, 0x65, 0x40, 0x51,
+ 0x78, 0x01, 0x5f, 0x92, 0x75, 0x40, 0x06, 0x76, 0x37, 0x0e, 0x77,
+ 0x00, 0x06, 0x78, 0x7a, 0x92, 0x85, 0x40, 0x3e, 0x78, 0x53, 0x78,
+ 0x51, 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x1c, 0x92,
+ 0x41, 0x40, 0x51, 0x78, 0x01, 0x7a, 0x92, 0x51, 0x40, 0x52, 0x02,
+ 0x14, 0x76, 0x52, 0x01, 0x1c, 0x77, 0x06, 0x78, 0x5f, 0x0e, 0x79,
+ 0x00, 0x92, 0x7b, 0x40, 0x62, 0xd0, 0x00, 0x55, 0xb7, 0x01, 0x55,
+ 0xb0, 0x00, 0x38, 0xfc, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x03, 0x56,
+ 0x02, 0x00, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x3e, 0x62,
+ 0xd0, 0x00, 0x92, 0x07, 0x40, 0x52, 0xfc, 0x04, 0x78, 0x52, 0xfb,
+ 0x0c, 0x79, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x53, 0x79, 0x3e,
+ 0x78, 0x53, 0x78, 0x52, 0x02, 0x12, 0x78, 0x52, 0x01, 0x1a, 0x79,
+ 0xd0, 0x18, 0x91, 0xe6, 0x40, 0x52, 0xfc, 0x04, 0x78, 0x52, 0xfb,
+ 0x0c, 0x79, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x01, 0x3e,
+ 0x78, 0x54, 0x02, 0x77, 0x00, 0x52, 0x00, 0x3b, 0xfa, 0xcf, 0xbe,
+ 0x62, 0xd0, 0x00, 0x52, 0x02, 0x53, 0x78, 0x52, 0x01, 0x53, 0x79,
+ 0x38, 0xfd, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x71, 0x10, 0x41,
+ 0x01, 0xf7, 0x43, 0x00, 0x08, 0x70, 0xcf, 0x43, 0x00, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x64, 0x08, 0x9b, 0xbd, 0x71, 0x10, 0x41, 0x01,
+ 0xf7, 0x41, 0x00, 0xf7, 0x70, 0xcf, 0x43, 0x00, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x64, 0x08, 0x9b, 0xa8, 0x38, 0xfc, 0x5d, 0x00, 0x62,
+ 0xd0, 0x00, 0x53, 0x79, 0x26, 0x79, 0x08, 0x3c, 0x79, 0x08, 0xb0,
+ 0x09, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x07, 0x56, 0x01,
+ 0x01, 0x56, 0x00, 0x00, 0x52, 0x01, 0x62, 0xd0, 0x00, 0x53, 0xbd,
+ 0x71, 0x10, 0x43, 0x00, 0x08, 0x41, 0x01, 0xf7, 0x70, 0xcf, 0x3c,
+ 0xbd, 0x00, 0xb0, 0x04, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f,
+ 0x10, 0x4f, 0x38, 0x01, 0x10, 0x50, 0x02, 0x7c, 0x03, 0x91, 0x20,
+ 0x10, 0x50, 0xff, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0xff, 0x7c,
+ 0x03, 0x91, 0x20, 0x10, 0x50, 0x08, 0x08, 0x50, 0x00, 0x08, 0x50,
+ 0x7a, 0x08, 0x7c, 0x04, 0x76, 0x38, 0xfd, 0x20, 0x56, 0x00, 0x00,
+ 0x80, 0x6e, 0x62, 0xd0, 0x00, 0x91, 0x1d, 0x40, 0x51, 0x78, 0x01,
+ 0x5f, 0x91, 0x2d, 0x40, 0x06, 0x78, 0x7a, 0x91, 0x43, 0x40, 0x3e,
+ 0x78, 0x53, 0x78, 0x51, 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79,
+ 0xd0, 0x3d, 0x90, 0xff, 0x40, 0x51, 0x78, 0x01, 0x5f, 0x91, 0x0f,
+ 0x40, 0x06, 0x78, 0x7a, 0x91, 0x25, 0x40, 0x92, 0x07, 0x40, 0x51,
+ 0x79, 0x10, 0x7c, 0x03, 0x91, 0x20, 0x62, 0xd0, 0x00, 0x90, 0xe2,
+ 0x40, 0x51, 0x78, 0x01, 0x5f, 0x90, 0xf2, 0x40, 0x06, 0x78, 0x7a,
+ 0x91, 0x08, 0x40, 0x91, 0xea, 0x40, 0x26, 0x79, 0x00, 0x51, 0x78,
+ 0x10, 0x7c, 0x03, 0x91, 0x20, 0x80, 0x0f, 0x10, 0x50, 0x00, 0x7c,
+ 0x03, 0x91, 0x20, 0x10, 0x50, 0x00, 0x7c, 0x03, 0x91, 0x20, 0x77,
+ 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x8f, 0x10, 0x50, 0x00, 0x7c, 0x03,
+ 0x91, 0x20, 0x10, 0x50, 0x01, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50,
+ 0x00, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0x01, 0x7c, 0x03, 0x91,
+ 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0xff,
+ 0x7c, 0x03, 0x91, 0x7c, 0x04, 0x6d, 0x20, 0x50, 0x13, 0x08, 0x50,
+ 0x88, 0x08, 0x9a, 0x97, 0x38, 0xfe, 0x38, 0xff, 0x20, 0x7f, 0x7f,
+ 0x10, 0x4f, 0x7c, 0x1b, 0x97, 0x20, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50, 0x00, 0x53, 0x70, 0x53,
+ 0x71, 0x55, 0x6f, 0x10, 0x66, 0xfc, 0x6c, 0xfb, 0x6b, 0x70, 0x6b,
+ 0x71, 0x51, 0x70, 0x1b, 0xfa, 0x51, 0x71, 0x1b, 0xf9, 0xc0, 0x09,
+ 0x53, 0x71, 0x52, 0xfa, 0x1c, 0x70, 0x77, 0xfc, 0x7a, 0x6f, 0xbf,
+ 0xe3, 0x51, 0x70, 0x54, 0xfa, 0x51, 0x71, 0x54, 0xf9, 0x18, 0x60,
+ 0xd0, 0x7f, 0x10, 0x4f, 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50,
+ 0x00, 0x53, 0x71, 0x53, 0x70, 0x55, 0x6f, 0x10, 0x6f, 0xf9, 0x6f,
+ 0xfa, 0xd0, 0x09, 0x52, 0xfc, 0x04, 0x71, 0x52, 0xfb, 0x0c, 0x70,
+ 0x66, 0xfc, 0x6c, 0xfb, 0x7a, 0x6f, 0xbf, 0xeb, 0x18, 0x60, 0xd0,
+ 0x20, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x52, 0x00, 0x53, 0x78, 0x55,
+ 0x79, 0x00, 0x65, 0x78, 0x6b, 0x79, 0x7f, 0x62, 0xd0, 0x00, 0x52,
+ 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x7f, 0x53, 0x76, 0x51, 0x79,
+ 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x76, 0x53, 0x77, 0x3e, 0x76, 0x53,
+ 0x76, 0x7f, 0x60, 0xd4, 0x3e, 0x76, 0x53, 0x77, 0x3e, 0x76, 0x53,
+ 0x76, 0x7f, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78,
+ 0x53, 0x79, 0x7f, 0x51, 0x71, 0x53, 0x76, 0x51, 0x70, 0x53, 0x77,
+ 0x51, 0x76, 0x02, 0x78, 0x53, 0x78, 0x51, 0x77, 0x0a, 0x79, 0x7f,
+ 0x51, 0x79, 0x60, 0xd5, 0x51, 0x77, 0x3f, 0x78, 0x51, 0x76, 0x3f,
+ 0x78, 0x7f, 0x51, 0x78, 0x01, 0x7a, 0x53, 0x76, 0x51, 0x79, 0x09,
+ 0x00, 0x7f, 0x51, 0x76, 0x02, 0x78, 0x53, 0x78, 0x51, 0x77, 0x0a,
+ 0x79, 0x7f, 0x53, 0x76, 0x51, 0x79, 0x09, 0x00, 0x60, 0xd5, 0x52,
+ 0x20, 0x3f, 0x76, 0x52, 0x21, 0x3f, 0x76, 0x7f, 0x51, 0x71, 0x53,
+ 0x78, 0x51, 0x70, 0x53, 0x79, 0x70, 0xfb, 0x6e, 0x79, 0x6e, 0x78,
+ 0x51, 0x78, 0x08, 0x51, 0x79, 0x62, 0xd0, 0x00, 0x53, 0x80, 0x18,
+ 0x53, 0x81, 0x7f, 0x60, 0xd5, 0x52, 0x20, 0x3f, 0x76, 0x52, 0x21,
+ 0x3f, 0x76, 0x7f, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd5, 0x52,
+ 0x20, 0x3f, 0x78, 0x52, 0x21, 0x3f, 0x78, 0x7f, 0x52, 0x00, 0x53,
+ 0x76, 0x55, 0x77, 0x00, 0x65, 0x76, 0x6b, 0x77, 0x7f, 0x0e, 0x77,
+ 0x00, 0x51, 0x77, 0x60, 0xd5, 0x51, 0x79, 0x3f, 0x76, 0x7f, 0x06,
+ 0x78, 0x7a, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78,
+ 0x53, 0x77, 0x3e, 0x78, 0x16, 0x78, 0x02, 0x53, 0x76, 0x7f, 0x70,
+ 0xfb, 0x6e, 0x79, 0x6e, 0x78, 0x51, 0x77, 0x60, 0xd5, 0x51, 0x79,
+ 0x3f, 0x76, 0x51, 0x78, 0x3f, 0x76, 0x7f, 0x3e, 0x78, 0x12, 0x76,
+ 0x54, 0x06, 0x51, 0x79, 0x1a, 0x77, 0x54, 0x05, 0x7f, 0x3e, 0x78,
+ 0x12, 0x76, 0x54, 0x04, 0x51, 0x79, 0x1a, 0x77, 0x54, 0x03, 0x7f,
+ 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76, 0x14, 0x78, 0x51, 0x77, 0x1c,
+ 0x79, 0x7f, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x74, 0x53, 0x75, 0x3e,
+ 0x74, 0x53, 0x74, 0x7f, 0x60, 0xd4, 0x3e, 0x76, 0x53, 0x75, 0x3e,
+ 0x76, 0x16, 0x76, 0x02, 0x7f, 0x00, 0x2c, 0x00, 0x22, 0x00, 0x82,
+ 0x00, 0x18, 0x00, 0x9a, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x9e,
+ 0x00, 0x09, 0x00, 0xa7, 0x07, 0x01, 0x02, 0x03, 0x10, 0x17, 0x1c,
+ 0x15, 0x00, 0xae, 0x00, 0x05, 0x00, 0xb3, 0x04, 0x03, 0x00, 0x01,
+ 0x01, 0x00, 0xb7, 0x00, 0x07, 0xff, 0x00, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_NAATT.h b/drivers/input/keyboard/cypressbln/touchkey_fw_NAATT.h
new file mode 100644
index 0000000..9a966b1
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_NAATT.h
@@ -0,0 +1,747 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x00, 0x68,
+ 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x05, 0x47, 0x7e, 0x7e, 0x30,
+ 0x30, 0x30, 0x7d, 0x06, 0x93, 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30,
+ 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x40, 0x71, 0x10, 0x62, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe3, 0x38, 0x50, 0x80, 0x4e, 0x62, 0xe3, 0x38, 0x5d,
+ 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55, 0xfa, 0x01, 0x40, 0x4f, 0x5b,
+ 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a, 0x50, 0x06, 0x00, 0x40,
+ 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8, 0x70, 0xef, 0x18, 0x60,
+ 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00, 0x71, 0x10, 0x62, 0xe0,
+ 0x02, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x71, 0x10, 0x41, 0xe1, 0xfe,
+ 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1, 0x03, 0x50, 0x00, 0x4e,
+ 0x62, 0xd3, 0x03, 0x62, 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4,
+ 0x00, 0x71, 0xc0, 0x7c, 0x03, 0x01, 0x62, 0xd0, 0x00, 0x50, 0x02,
+ 0x57, 0xff, 0x08, 0x28, 0x53, 0x79, 0x18, 0x75, 0x09, 0x00, 0x28,
+ 0x4b, 0x51, 0x79, 0x80, 0x04, 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00,
+ 0x08, 0x28, 0x60, 0xd5, 0x74, 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00,
+ 0x08, 0x28, 0x53, 0x79, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xa0,
+ 0x1c, 0x53, 0x78, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x3f, 0x79,
+ 0x47, 0x79, 0xff, 0xb0, 0x06, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x18,
+ 0x7a, 0x78, 0xbf, 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09, 0x00, 0x08,
+ 0x28, 0x53, 0x78, 0x50, 0x00, 0x3f, 0x79, 0x47, 0x79, 0xff, 0xb0,
+ 0x08, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x78, 0xbf,
+ 0xef, 0x18, 0x8f, 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71,
+ 0x10, 0x62, 0xe0, 0x02, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x0a,
+ 0x86, 0x8f, 0xff, 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x61, 0x00, 0xfd, 0x00, 0xcd, 0x00,
+ 0xce, 0x00, 0xa5, 0x00, 0xa4, 0x00, 0xa0, 0x00, 0xa1, 0x80, 0xa2,
+ 0xc0, 0xa3, 0x0c, 0xa8, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0x7c, 0x33,
+ 0x7a, 0x00, 0x7b, 0x00, 0x79, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38,
+ 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00,
+ 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43,
+ 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
+ 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e,
+ 0x00, 0x4f, 0x00, 0xca, 0x20, 0xd6, 0x44, 0xcf, 0x00, 0xcb, 0x00,
+ 0xc8, 0x00, 0xcc, 0x00, 0xc9, 0x00, 0xd7, 0x00, 0xa9, 0x00, 0x2b,
+ 0x00, 0xb0, 0x00, 0xb3, 0x02, 0xb6, 0x00, 0xb2, 0x00, 0xb5, 0x00,
+ 0xb8, 0x00, 0xb1, 0x00, 0xb4, 0x00, 0xb7, 0x00, 0x33, 0x00, 0x34,
+ 0x00, 0x35, 0x00, 0xff, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
+ 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0xdc, 0x00,
+ 0xe2, 0x00, 0xdd, 0x00, 0xd8, 0x02, 0xd9, 0xa0, 0xda, 0x28, 0xdb,
+ 0x00, 0xdf, 0x00, 0x29, 0x00, 0x30, 0x00, 0xbd, 0x00, 0xff, 0x70,
+ 0xef, 0x62, 0x00, 0x08, 0x71, 0x10, 0x62, 0x00, 0x98, 0x62, 0x01,
+ 0x02, 0x70, 0xef, 0x62, 0x04, 0x03, 0x71, 0x10, 0x62, 0x04, 0x17,
+ 0x62, 0x05, 0xab, 0x70, 0xef, 0x62, 0x08, 0x00, 0x71, 0x10, 0x62,
+ 0x08, 0x00, 0x62, 0x09, 0x28, 0x70, 0xef, 0x62, 0x0c, 0x00, 0x71,
+ 0x10, 0x62, 0x0c, 0x00, 0x62, 0x0d, 0x00, 0x70, 0xef, 0x62, 0x10,
+ 0x00, 0x71, 0x10, 0x62, 0x10, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef,
+ 0x62, 0x01, 0x00, 0x62, 0x05, 0x00, 0x62, 0x09, 0x00, 0x62, 0x0d,
+ 0x00, 0x62, 0x11, 0x00, 0x70, 0xef, 0x7f, 0x1d, 0x8c, 0x55, 0x02,
+ 0x08, 0x55, 0x03, 0x03, 0x55, 0x04, 0x00, 0x7c, 0x03, 0x11, 0x7c,
+ 0x02, 0xaa, 0x7f, 0x10, 0x70, 0xef, 0x50, 0x00, 0x67, 0x50, 0x02,
+ 0x57, 0x00, 0x7c, 0x03, 0x2c, 0x50, 0x01, 0x67, 0x50, 0x02, 0x57,
+ 0x83, 0x7c, 0x03, 0x2c, 0x70, 0xef, 0x20, 0x7f, 0x38, 0x02, 0x10,
+ 0x08, 0x4f, 0x56, 0xfc, 0x00, 0xd0, 0x04, 0x56, 0xfc, 0x01, 0x18,
+ 0x20, 0x70, 0xef, 0x62, 0xe3, 0x00, 0x10, 0x08, 0x28, 0x39, 0xff,
+ 0xa0, 0x1f, 0x4f, 0x48, 0xfc, 0x01, 0xa0, 0x03, 0x71, 0x10, 0x54,
+ 0xfd, 0x18, 0x20, 0x75, 0x09, 0x00, 0x10, 0x08, 0x28, 0x4f, 0x59,
+ 0xfd, 0x61, 0x00, 0x18, 0x20, 0x75, 0x09, 0x00, 0x8f, 0xd7, 0x38,
+ 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x30, 0x31, 0x32, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+ 0x62, 0xd0, 0x00, 0x2e, 0x02, 0x08, 0x51, 0x02, 0x60, 0x00, 0x71,
+ 0x10, 0x41, 0x01, 0xf7, 0x43, 0x00, 0x08, 0x70, 0xef, 0x7f, 0x62,
+ 0xd0, 0x00, 0x53, 0x00, 0x71, 0x10, 0x5d, 0xe0, 0x08, 0x21, 0xf8,
+ 0x29, 0x00, 0x70, 0xfe, 0x60, 0xe0, 0x70, 0xef, 0x4b, 0x4b, 0x4b,
+ 0x4b, 0x51, 0x02, 0x21, 0xf7, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05,
+ 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e,
+ 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01,
+ 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29,
+ 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0,
+ 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80,
+ 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21,
+ 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x47, 0x00,
+ 0x00, 0x49, 0x01, 0x00, 0x29, 0x08, 0x60, 0x00, 0x57, 0x01, 0x79,
+ 0xbf, 0xfe, 0x18, 0x71, 0x10, 0x60, 0xe0, 0x70, 0xef, 0x71, 0x01,
+ 0x7f, 0x08, 0x67, 0x67, 0x67, 0x67, 0x21, 0x0f, 0xff, 0x2b, 0x9f,
+ 0x4e, 0x18, 0x21, 0x0f, 0xff, 0x24, 0x9f, 0x47, 0x7f, 0x08, 0x10,
+ 0x28, 0xa0, 0x0b, 0x9f, 0x3f, 0x20, 0x18, 0x75, 0xdf, 0xf5, 0x74,
+ 0x8f, 0xf2, 0x38, 0xfe, 0x7f, 0x52, 0x00, 0xa0, 0x08, 0x10, 0x9f,
+ 0x2d, 0x20, 0x75, 0x8f, 0xf6, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50,
+ 0x0d, 0x9f, 0x20, 0x50, 0x0a, 0x9f, 0x1c, 0x7f, 0x70, 0xbf, 0x62,
+ 0xd3, 0x03, 0x4f, 0x52, 0xfb, 0xa0, 0x15, 0x7b, 0xfb, 0x52, 0xfc,
+ 0x59, 0xfd, 0x60, 0xd3, 0x52, 0x00, 0x9f, 0x05, 0x4f, 0x62, 0xd3,
+ 0x03, 0x77, 0xfd, 0x8f, 0xe9, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x3d,
+ 0xfa, 0x00, 0xb0, 0x06, 0x3d, 0xfb, 0x00, 0xa0, 0x18, 0x10, 0x52,
+ 0xfc, 0x59, 0xfd, 0x28, 0x9e, 0xe6, 0x20, 0x07, 0xfd, 0x01, 0x0f,
+ 0xfc, 0x00, 0x17, 0xfb, 0x01, 0x1f, 0xfa, 0x00, 0x8f, 0xe0, 0x7f,
+ 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00,
+ 0xa0, 0x06, 0x26, 0x02, 0x7f, 0x80, 0x04, 0x2e, 0x02, 0x80, 0x51,
+ 0x02, 0x60, 0x00, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00,
+ 0x29, 0x00, 0xa0, 0x06, 0x26, 0x02, 0xef, 0x80, 0x04, 0x2e, 0x02,
+ 0x10, 0x51, 0x02, 0x60, 0x00, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62,
+ 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xef, 0x80, 0x04,
+ 0x2e, 0x03, 0x10, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f, 0x71, 0xc0,
+ 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50,
+ 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xfb,
+ 0x80, 0x04, 0x2e, 0x03, 0x04, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x10, 0x70,
+ 0x3f, 0x71, 0x80, 0x5d, 0xd3, 0x08, 0x5d, 0xd0, 0x08, 0x62, 0xd0,
+ 0x00, 0x51, 0x08, 0x60, 0xd3, 0x2e, 0x05, 0x80, 0x49, 0xd7, 0x08,
+ 0xa0, 0x09, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x00, 0x80, 0x08, 0x49,
+ 0xd7, 0x20, 0xa0, 0x03, 0x80, 0xac, 0x51, 0x05, 0x21, 0x0e, 0xe0,
+ 0x01, 0x80, 0x11, 0x80, 0x6d, 0x80, 0x7f, 0x80, 0x4d, 0x80, 0x9c,
+ 0x80, 0x9a, 0x80, 0x98, 0x80, 0x96, 0x80, 0x9d, 0x5d, 0xd8, 0x21,
+ 0xfe, 0x39, 0x40, 0xa0, 0x06, 0x62, 0xd7, 0x00, 0x80, 0x90, 0x49,
+ 0xd8, 0x01, 0xb0, 0x15, 0x55, 0x0c, 0x02, 0x26, 0x07, 0x00, 0x26,
+ 0x06, 0x00, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x62, 0xd7, 0x10,
+ 0x80, 0x77, 0x55, 0x0c, 0x01, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x06,
+ 0x5f, 0x07, 0x06, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00, 0x60,
+ 0xd8, 0x76, 0x07, 0x62, 0xd7, 0x14, 0x80, 0x5b, 0x51, 0x0a, 0x78,
+ 0x3a, 0x07, 0xc0, 0x0f, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00,
+ 0x60, 0xd8, 0x76, 0x07, 0x2e, 0x05, 0x20, 0x60, 0xd8, 0x62, 0xd7,
+ 0x04, 0x80, 0x3f, 0x5d, 0xd8, 0x3a, 0x0a, 0xd0, 0x2b, 0xa0, 0x29,
+ 0x53, 0x07, 0x53, 0x06, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x80,
+ 0x18, 0x51, 0x0b, 0x78, 0x3a, 0x07, 0xc0, 0x16, 0x51, 0x09, 0x02,
+ 0x07, 0x5c, 0x5d, 0xd8, 0x54, 0x00, 0x2e, 0x05, 0x10, 0x76, 0x07,
+ 0x80, 0x01, 0x62, 0xd7, 0x10, 0x80, 0x0f, 0x62, 0xd7, 0x00, 0x80,
+ 0x0a, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x00, 0x55, 0x0c, 0x00, 0x18,
+ 0x60, 0xd0, 0x18, 0x60, 0xd3, 0x20, 0x18, 0x7e, 0x62, 0xd0, 0x00,
+ 0x71, 0x10, 0x41, 0x04, 0xfc, 0x43, 0x05, 0x03, 0x70, 0xef, 0x26,
+ 0x03, 0xfc, 0x51, 0x03, 0x60, 0x04, 0x55, 0x0c, 0x00, 0x90, 0x28,
+ 0x90, 0x2d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x00, 0x53, 0x06,
+ 0x71, 0x10, 0x43, 0x04, 0x03, 0x43, 0x05, 0x03, 0x70, 0xef, 0x2e,
+ 0x03, 0x03, 0x51, 0x03, 0x60, 0x04, 0x7f, 0x62, 0xd0, 0x00, 0x51,
+ 0x05, 0x21, 0xb0, 0x26, 0x05, 0x4f, 0x7f, 0x41, 0xe0, 0x7f, 0x43,
+ 0xe0, 0x80, 0x7f, 0x43, 0xd6, 0x31, 0x7f, 0x62, 0xd0, 0x00, 0x4f,
+ 0x52, 0xfd, 0x53, 0x0a, 0x52, 0xfc, 0x53, 0x0b, 0x52, 0xfb, 0x53,
+ 0x09, 0x52, 0xfa, 0x53, 0x08, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08,
+ 0x5d, 0xa4, 0x04, 0x1b, 0x5d, 0xa5, 0x0c, 0x1a, 0x55, 0x1c, 0x01,
+ 0x18, 0x7e, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x53, 0x1e,
+ 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0xa3, 0x62, 0xd3, 0x00, 0x13,
+ 0x60, 0x62, 0xd3, 0x00, 0x54, 0x68, 0x62, 0xd3, 0x00, 0x52, 0xa2,
+ 0x62, 0xd3, 0x00, 0x1b, 0x5f, 0x62, 0xd3, 0x00, 0x54, 0x67, 0x48,
+ 0x67, 0x80, 0xb0, 0x33, 0x3d, 0x67, 0x00, 0xb0, 0x7b, 0x51, 0x0d,
+ 0x3b, 0x68, 0xc0, 0x75, 0x52, 0x68, 0x58, 0x1e, 0x01, 0x00, 0x6d,
+ 0x62, 0xd3, 0x00, 0x05, 0x4e, 0xc0, 0x09, 0x51, 0x0f, 0x3b, 0x4e,
+ 0xd0, 0x12, 0xa0, 0x10, 0x56, 0x4e, 0x00, 0x5b, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x07, 0x60, 0x01, 0x0f, 0x5f, 0x00, 0x80, 0x41, 0x3d,
+ 0x67, 0xff, 0xb0, 0x09, 0x50, 0xff, 0x12, 0x0e, 0x3b, 0x68, 0xc0,
+ 0x20, 0x62, 0xd3, 0x00, 0x56, 0x68, 0x00, 0x56, 0x67, 0x00, 0x5b,
+ 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x5b, 0x78, 0xd0, 0x03, 0x50,
+ 0x00, 0x54, 0x5b, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c, 0x62,
+ 0xd3, 0x00, 0x52, 0xa3, 0x62, 0xd3, 0x00, 0x54, 0x60, 0x62, 0xd3,
+ 0x00, 0x52, 0xa2, 0x62, 0xd3, 0x00, 0x54, 0x5f, 0x51, 0x1e, 0x64,
+ 0x5c, 0x62, 0xd3, 0x00, 0x56, 0x68, 0x00, 0x56, 0x67, 0x00, 0x5b,
+ 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x12, 0x54, 0x5b, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x08,
+ 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x52, 0x53, 0x19, 0x55, 0x18, 0x00,
+ 0x18, 0x08, 0x90, 0x7e, 0x62, 0xd3, 0x00, 0x23, 0x56, 0xb0, 0x2c,
+ 0x51, 0x10, 0x04, 0x19, 0x0e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x52, 0x68, 0x12, 0x19, 0x52, 0x67, 0x1a, 0x18, 0xc0,
+ 0x39, 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x57, 0x78, 0x54,
+ 0x57, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x3e, 0x80, 0x18, 0x51,
+ 0x10, 0x14, 0x19, 0x1e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3,
+ 0x00, 0x52, 0x68, 0x12, 0x19, 0x52, 0x67, 0x1a, 0x18, 0xc0, 0x0e,
+ 0x5b, 0x67, 0x90, 0x31, 0x62, 0xd3, 0x00, 0x2d, 0x56, 0x50, 0x01,
+ 0x80, 0x24, 0x5b, 0x67, 0x08, 0x90, 0x23, 0x73, 0x62, 0xd3, 0x00,
+ 0x25, 0x56, 0x62, 0xd3, 0x00, 0x20, 0x51, 0x11, 0x54, 0x57, 0x50,
+ 0x00, 0x80, 0x0d, 0x5b, 0x67, 0x90, 0x0d, 0x73, 0x62, 0xd3, 0x00,
+ 0x25, 0x56, 0x50, 0x00, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x67,
+ 0x67, 0x67, 0x5c, 0x18, 0x21, 0x07, 0xf0, 0x01, 0x7f, 0x01, 0x02,
+ 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x70, 0xbf, 0x70, 0xbf, 0x62,
+ 0xd3, 0x00, 0x50, 0x04, 0x78, 0x08, 0x5c, 0x56, 0x52, 0x32, 0x18,
+ 0x78, 0xdf, 0xf8, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x91, 0x99,
+ 0x70, 0xbf, 0x18, 0x08, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0xa3,
+ 0x62, 0xd3, 0x00, 0x54, 0x60, 0x62, 0xd3, 0x00, 0x52, 0xa2, 0x62,
+ 0xd3, 0x00, 0x54, 0x5f, 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x14, 0x00, 0x50, 0x04, 0x78,
+ 0x08, 0x9f, 0x0e, 0x39, 0x01, 0xb0, 0x04, 0x55, 0x14, 0x01, 0x18,
+ 0x78, 0xdf, 0xf3, 0x51, 0x14, 0x7f, 0x50, 0x04, 0x78, 0x08, 0x9e,
+ 0x3e, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x98, 0x90, 0x91, 0x92, 0x93,
+ 0x94, 0x95, 0x96, 0x97, 0xd8, 0xd9, 0xda, 0xdb, 0xdf, 0x00, 0x01,
+ 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x70, 0xbf, 0x62, 0xd0,
+ 0x00, 0x62, 0xd3, 0x00, 0x57, 0x00, 0x56, 0x56, 0x00, 0x79, 0xdf,
+ 0xfb, 0x62, 0xd3, 0x00, 0x57, 0x03, 0x50, 0x03, 0x54, 0x57, 0x79,
+ 0xdf, 0xfc, 0x62, 0xd3, 0x00, 0x50, 0x32, 0x57, 0x03, 0x54, 0x5b,
+ 0x79, 0xdf, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x55, 0x0d, 0x19, 0x55,
+ 0x0e, 0x0a, 0x55, 0x0f, 0x0f, 0x55, 0x10, 0x0a, 0x55, 0x11, 0x03,
+ 0x55, 0x12, 0x32, 0x55, 0x22, 0x01, 0x55, 0x1f, 0x14, 0x43, 0x61,
+ 0x0d, 0x57, 0x00, 0x50, 0x02, 0x90, 0x95, 0x50, 0x01, 0xff, 0x98,
+ 0x29, 0x00, 0x60, 0xa9, 0x62, 0xa0, 0x28, 0x43, 0xa2, 0x04, 0x62,
+ 0xa3, 0x70, 0x43, 0x7a, 0x01, 0x43, 0xaa, 0x02, 0x43, 0xdf, 0x01,
+ 0x50, 0x01, 0x57, 0x09, 0x90, 0x20, 0x90, 0x55, 0x57, 0x01, 0x50,
+ 0xb3, 0x91, 0x44, 0x50, 0x01, 0x57, 0x0e, 0x90, 0x12, 0x90, 0x47,
+ 0x7f, 0x53, 0x22, 0xff, 0x67, 0x29, 0x00, 0x60, 0xa9, 0x51, 0x21,
+ 0x58, 0x20, 0x90, 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21, 0x03, 0x53,
+ 0x21, 0x64, 0x64, 0x64, 0x64, 0x64, 0x29, 0x80, 0x60, 0xa1, 0x5b,
+ 0x78, 0x21, 0x0f, 0x29, 0x08, 0x74, 0x53, 0x20, 0x12, 0x22, 0x02,
+ 0x21, 0x5c, 0x50, 0x00, 0x53, 0x1d, 0x53, 0x23, 0x29, 0x01, 0x79,
+ 0xa0, 0x08, 0x64, 0x6b, 0x1d, 0x6b, 0x23, 0x8f, 0xf5, 0x60, 0xb5,
+ 0x51, 0x1d, 0x60, 0xb4, 0x7f, 0x50, 0x04, 0x78, 0x08, 0x90, 0x0f,
+ 0x90, 0x41, 0x18, 0x78, 0xdf, 0xf8, 0x7f, 0x02, 0x20, 0x02, 0x08,
+ 0x01, 0x80, 0x01, 0x20, 0x64, 0x5c, 0xff, 0xf4, 0x4b, 0x74, 0xff,
+ 0xf0, 0x7f, 0x62, 0xd0, 0x00, 0x53, 0x1d, 0x10, 0x5b, 0x64, 0x64,
+ 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x2a, 0x1d, 0x61, 0x01, 0x36, 0x1d,
+ 0xff, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x36, 0x1d, 0xff, 0x18,
+ 0xfe, 0xef, 0x5c, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef,
+ 0x7f, 0x62, 0xd0, 0x00, 0x10, 0x73, 0x53, 0x1d, 0x71, 0x10, 0x5b,
+ 0xfe, 0xd9, 0x5c, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x70, 0xef,
+ 0x18, 0x64, 0x64, 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x22, 0x1d, 0x61,
+ 0x01, 0x36, 0x1d, 0xff, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70,
+ 0xef, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53, 0x1e, 0x50, 0x00,
+ 0x53, 0x1a, 0x53, 0x1b, 0x51, 0x1e, 0x5c, 0x62, 0xd3, 0x00, 0x52,
+ 0x24, 0x53, 0x1f, 0x43, 0xa0, 0x01, 0x51, 0x1f, 0x60, 0xfd, 0x41,
+ 0xa3, 0xdf, 0x51, 0x1e, 0x9f, 0x7a, 0x9f, 0x81, 0x58, 0x23, 0x55,
+ 0x1c, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x43, 0xb3, 0x01,
+ 0x51, 0x1c, 0xaf, 0xfd, 0x79, 0xdf, 0xee, 0x51, 0x1e, 0x9f, 0x5f,
+ 0x9f, 0x91, 0x43, 0xa3, 0x20, 0x41, 0xa0, 0xfe, 0x62, 0xfd, 0x00,
+ 0x50, 0xff, 0x4c, 0x1b, 0x14, 0x1b, 0x51, 0x20, 0x11, 0x08, 0xfe,
+ 0x66, 0x4c, 0x1a, 0x1c, 0x1a, 0xd0, 0x07, 0x55, 0x1a, 0x00, 0x55,
+ 0x1b, 0x00, 0x51, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x1b,
+ 0x54, 0xa3, 0x51, 0x1a, 0x54, 0xa2, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x08, 0x9f, 0x86, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x70, 0xbf, 0x62,
+ 0xd0, 0x00, 0x53, 0x29, 0x5a, 0x28, 0x55, 0x1e, 0x03, 0x62, 0xd3,
+ 0x00, 0x58, 0x1e, 0x56, 0x24, 0x80, 0x55, 0x2b, 0x08, 0x55, 0x2a,
+ 0x80, 0x51, 0x1e, 0x9f, 0x63, 0x51, 0x1e, 0x9f, 0x5f, 0x70, 0xbf,
+ 0x58, 0x1e, 0x62, 0xd3, 0x00, 0x51, 0x1b, 0x3a, 0x29, 0x51, 0x1a,
+ 0x1a, 0x28, 0xd0, 0x06, 0x51, 0x2a, 0x73, 0x25, 0x24, 0x68, 0x2a,
+ 0x26, 0x2a, 0x7f, 0x51, 0x2a, 0x2d, 0x24, 0x7a, 0x2b, 0xbf, 0xd6,
+ 0x7a, 0x1e, 0xdf, 0xc4, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x10, 0x7c,
+ 0x05, 0x28, 0x7c, 0x05, 0x05, 0x7c, 0x04, 0xe2, 0x7c, 0x04, 0xbf,
+ 0x20, 0x7c, 0x16, 0xb6, 0x62, 0xe3, 0x38, 0x10, 0x7c, 0x03, 0x7c,
+ 0x20, 0x43, 0x00, 0x08, 0x62, 0xd0, 0x00, 0x55, 0x2c, 0x08, 0x55,
+ 0x2d, 0x0b, 0x55, 0x2e, 0x03, 0x55, 0x30, 0x32, 0x55, 0x31, 0x02,
+ 0x10, 0x50, 0x00, 0x08, 0x50, 0x2c, 0x08, 0x50, 0x06, 0x08, 0x50,
+ 0x22, 0x08, 0x7c, 0x06, 0x7a, 0x38, 0xfc, 0x7c, 0x06, 0x2e, 0x7c,
+ 0x06, 0x6f, 0x20, 0x71, 0x10, 0x41, 0x04, 0xfc, 0x41, 0x05, 0xfc,
+ 0x71, 0x01, 0x10, 0x70, 0xcf, 0x7c, 0x08, 0x7f, 0x20, 0x62, 0xd0,
+ 0x00, 0x55, 0xc5, 0x00, 0x91, 0x23, 0x10, 0x7c, 0x08, 0x05, 0x20,
+ 0x93, 0xcb, 0x81, 0x17, 0x7c, 0x18, 0x71, 0x62, 0xe3, 0x38, 0x7c,
+ 0x11, 0x2d, 0x62, 0xd0, 0x00, 0x3c, 0xc0, 0x01, 0xb0, 0x09, 0x50,
+ 0x00, 0x08, 0x7c, 0x1a, 0xfe, 0x38, 0xff, 0x62, 0xe3, 0x38, 0x10,
+ 0x7c, 0x08, 0x43, 0x20, 0x39, 0x00, 0xa0, 0xa8, 0x62, 0xd0, 0x00,
+ 0x51, 0xbf, 0x11, 0x4a, 0x51, 0xbe, 0x19, 0x01, 0xd0, 0x12, 0x7c,
+ 0x16, 0xd4, 0x39, 0xe1, 0xa0, 0x16, 0x62, 0xd0, 0x00, 0x76, 0xbf,
+ 0x0e, 0xbe, 0x00, 0x80, 0x0c, 0x62, 0xd0, 0x00, 0x55, 0xbf, 0x00,
+ 0x55, 0xbe, 0x00, 0x90, 0xcc, 0x62, 0xd0, 0x00, 0x3c, 0xcd, 0xf0,
+ 0xd0, 0x03, 0x76, 0xcd, 0x62, 0xd0, 0x00, 0x51, 0x31, 0x21, 0x7f,
+ 0x53, 0x79, 0x51, 0xcd, 0x3a, 0x79, 0xb0, 0xad, 0x7c, 0x16, 0xd4,
+ 0x62, 0xd0, 0x00, 0x53, 0xce, 0x3c, 0xce, 0xe1, 0xa0, 0x51, 0x3c,
+ 0xca, 0x00, 0xb0, 0x06, 0x7c, 0x1d, 0x14, 0x80, 0x25, 0x62, 0xd0,
+ 0x00, 0x55, 0xb7, 0x00, 0x55, 0xb6, 0x00, 0x55, 0xb9, 0x00, 0x55,
+ 0xb8, 0x00, 0x51, 0xce, 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78,
+ 0xb6, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd5, 0x50, 0x08, 0x3f,
+ 0x78, 0x62, 0xd0, 0x00, 0x3c, 0xc6, 0x01, 0xb0, 0x04, 0x55, 0xc8,
+ 0x01, 0x62, 0xd0, 0x00, 0x55, 0xc6, 0x00, 0x55, 0xc1, 0x01, 0x7c,
+ 0x17, 0x5a, 0x62, 0xd0, 0x00, 0x55, 0xc3, 0x01, 0x55, 0xc4, 0x03,
+ 0x80, 0x50, 0x62, 0xd0, 0x00, 0x55, 0xcd, 0x00, 0x80, 0x48, 0x62,
+ 0xd0, 0x00, 0x55, 0xbf, 0x00, 0x55, 0xbe, 0x00, 0x55, 0xc8, 0x00,
+ 0x55, 0xc9, 0x00, 0x55, 0xc1, 0x00, 0x3c, 0xc3, 0x01, 0xb0, 0x31,
+ 0x7a, 0xc4, 0x3c, 0xc4, 0x00, 0xb0, 0x2a, 0x7c, 0x17, 0xea, 0x62,
+ 0xd0, 0x00, 0x55, 0xc3, 0x00, 0x3c, 0xca, 0x00, 0xb0, 0x06, 0x7c,
+ 0x1d, 0x14, 0x80, 0x11, 0x62, 0xd0, 0x00, 0x51, 0xce, 0x53, 0x78,
+ 0x55, 0x79, 0x00, 0x06, 0x78, 0xb6, 0x7c, 0x1d, 0x4c, 0x62, 0xd0,
+ 0x00, 0x55, 0xcd, 0x00, 0x7c, 0x19, 0x32, 0x8e, 0xe9, 0x8f, 0xff,
+ 0x10, 0x4f, 0x38, 0x24, 0x62, 0xd0, 0x00, 0x3c, 0xcb, 0x00, 0xb0,
+ 0x05, 0x51, 0xaa, 0x53, 0x24, 0x10, 0x50, 0x00, 0x7c, 0x09, 0xb9,
+ 0x20, 0x56, 0x19, 0x00, 0x81, 0x2c, 0x56, 0x00, 0x00, 0x81, 0x20,
+ 0x62, 0xd0, 0x00, 0x3c, 0xcb, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53,
+ 0x78, 0x55, 0x79, 0x00, 0x06, 0x78, 0xaa, 0x7c, 0x1c, 0x86, 0x52,
+ 0x00, 0x53, 0x76, 0x55, 0x77, 0x00, 0x06, 0x76, 0x24, 0x7c, 0x1d,
+ 0x08, 0x10, 0x52, 0x00, 0x7c, 0x09, 0xb9, 0x20, 0x10, 0x7c, 0x06,
+ 0x64, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00,
+ 0x00, 0xb0, 0x3c, 0x7c, 0x1c, 0x51, 0x7c, 0x1c, 0x9d, 0x51, 0x77,
+ 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x7c,
+ 0x1c, 0x21, 0x38, 0xfc, 0x51, 0x71, 0x53, 0x76, 0x51, 0x70, 0x53,
+ 0x77, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x77, 0x08, 0x51,
+ 0x76, 0x08, 0x7c, 0x1b, 0xdd, 0x18, 0x53, 0x76, 0x18, 0x53, 0x77,
+ 0x38, 0xfe, 0x7c, 0x1c, 0x79, 0x80, 0x63, 0x3d, 0x00, 0x01, 0xb0,
+ 0x2e, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x51, 0x7c, 0x1c, 0x9d, 0x65,
+ 0x76, 0x6b, 0x77, 0x65, 0x76, 0x6b, 0x77, 0x50, 0x00, 0x08, 0x50,
+ 0x05, 0x08, 0x51, 0x77, 0x08, 0x51, 0x76, 0x08, 0x7c, 0x1b, 0xdd,
+ 0x18, 0x53, 0x76, 0x18, 0x53, 0x77, 0x38, 0xfe, 0x7c, 0x1c, 0x79,
+ 0x80, 0x31, 0x3d, 0x00, 0x02, 0xb0, 0x2c, 0x62, 0xd0, 0x00, 0x7c,
+ 0x1c, 0x51, 0x7c, 0x1c, 0x9d, 0x65, 0x76, 0x6b, 0x77, 0x65, 0x76,
+ 0x6b, 0x77, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x77, 0x08,
+ 0x51, 0x76, 0x08, 0x7c, 0x1b, 0xdd, 0x18, 0x53, 0x76, 0x18, 0x53,
+ 0x77, 0x38, 0xfe, 0x7c, 0x1c, 0x79, 0x62, 0xd0, 0x00, 0x55, 0x79,
+ 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52, 0x00, 0x53, 0x76, 0x50,
+ 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08,
+ 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x7c, 0x1c, 0xbe, 0x53, 0x79, 0x52,
+ 0x19, 0x53, 0x76, 0x55, 0x77, 0x00, 0x65, 0x76, 0x6b, 0x77, 0x7c,
+ 0x1c, 0xe2, 0x53, 0x79, 0x7c, 0x1d, 0x34, 0x06, 0x76, 0xa2, 0x0e,
+ 0x77, 0x00, 0x51, 0x77, 0x7c, 0x1c, 0x92, 0x7c, 0x1c, 0x79, 0x77,
+ 0x00, 0x3d, 0x00, 0x04, 0xce, 0xdd, 0x77, 0x19, 0x3d, 0x19, 0x03,
+ 0xce, 0xd1, 0x56, 0x00, 0x00, 0x80, 0xd0, 0x62, 0xd0, 0x00, 0x55,
+ 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52, 0x00, 0x53, 0x76,
+ 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06,
+ 0x08, 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x7c, 0x1c, 0xbe, 0x60, 0xd4,
+ 0x3e, 0x78, 0x54, 0x1a, 0x3e, 0x78, 0x54, 0x1b, 0x5a, 0x78, 0x06,
+ 0x78, 0x03, 0x52, 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1c, 0x21, 0x38,
+ 0xfc, 0x7c, 0x1c, 0xbe, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1c, 0x3e,
+ 0x78, 0x54, 0x1d, 0x5a, 0x78, 0x06, 0x78, 0x05, 0x52, 0x00, 0x53,
+ 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50,
+ 0x06, 0x08, 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x7c, 0x1c, 0xbe, 0x60,
+ 0xd4, 0x3e, 0x78, 0x54, 0x1e, 0x3e, 0x78, 0x54, 0x1f, 0x50, 0x03,
+ 0x08, 0x5a, 0x78, 0x06, 0x78, 0x1a, 0x08, 0x51, 0x78, 0x08, 0x7c,
+ 0x1a, 0x33, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51, 0x78, 0x54, 0x21,
+ 0x51, 0x79, 0x54, 0x20, 0x7c, 0x1c, 0x51, 0x7c, 0x1c, 0xb3, 0x7c,
+ 0x1c, 0xfd, 0x06, 0x78, 0x5f, 0x7c, 0x1c, 0xed, 0x7c, 0x1c, 0x51,
+ 0x51, 0x78, 0x01, 0x8a, 0x7c, 0x1c, 0xd1, 0x51, 0x78, 0x01, 0x92,
+ 0x7c, 0x1c, 0xd1, 0x06, 0x78, 0x9a, 0x7c, 0x1c, 0xed, 0x7c, 0x1c,
+ 0x51, 0x51, 0x78, 0x01, 0x7a, 0x7c, 0x1c, 0xd1, 0x06, 0x78, 0x82,
+ 0x7c, 0x1c, 0xed, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xcf, 0x2d, 0x3d,
+ 0x00, 0x00, 0xb0, 0x09, 0x62, 0xd0, 0x00, 0x47, 0xc5, 0x0e, 0xa0,
+ 0x0e, 0x3d, 0x00, 0x03, 0xb0, 0x75, 0x62, 0xd0, 0x00, 0x47, 0xc5,
+ 0x07, 0xb0, 0x6d, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x51, 0x7c, 0x1c,
+ 0xb3, 0x53, 0x77, 0x7c, 0x1d, 0x40, 0x53, 0x74, 0x06, 0x78, 0x5f,
+ 0x7c, 0x1c, 0x86, 0x3e, 0x78, 0x12, 0x74, 0x51, 0x79, 0x1a, 0x75,
+ 0xd0, 0x2c, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0x5f, 0x53, 0x72,
+ 0x51, 0x79, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x72, 0x53, 0x73, 0x3e,
+ 0x72, 0x53, 0x72, 0x06, 0x78, 0xa2, 0x7c, 0x1c, 0x86, 0x3e, 0x78,
+ 0x12, 0x72, 0x54, 0x23, 0x51, 0x79, 0x1a, 0x73, 0x54, 0x22, 0x80,
+ 0x07, 0x56, 0x23, 0x00, 0x56, 0x22, 0x00, 0x62, 0xd0, 0x00, 0x51,
+ 0x74, 0x03, 0x23, 0x53, 0x78, 0x51, 0x75, 0x0b, 0x22, 0x53, 0x79,
+ 0x51, 0x77, 0x60, 0xd5, 0x51, 0x79, 0x3f, 0x76, 0x51, 0x78, 0x3f,
+ 0x76, 0x38, 0xdc, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x22, 0x10, 0x57,
+ 0x30, 0x50, 0x00, 0x7c, 0x0a, 0x38, 0x20, 0x62, 0xd0, 0x00, 0x3c,
+ 0xcb, 0x01, 0xb0, 0x13, 0x51, 0x24, 0x53, 0x32, 0x51, 0x25, 0x53,
+ 0x33, 0x51, 0x26, 0x53, 0x34, 0x51, 0x27, 0x53, 0x35, 0x80, 0x14,
+ 0x62, 0xd0, 0x00, 0x51, 0xaa, 0x53, 0x24, 0x51, 0xab, 0x53, 0x25,
+ 0x51, 0xac, 0x53, 0x26, 0x51, 0xad, 0x53, 0x27, 0x10, 0x50, 0x00,
+ 0x7c, 0x09, 0xb9, 0x20, 0x56, 0x19, 0x00, 0x81, 0x2c, 0x56, 0x00,
+ 0x00, 0x81, 0x20, 0x62, 0xd0, 0x00, 0x3c, 0xcb, 0x00, 0xb0, 0x1b,
+ 0x52, 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78, 0xaa, 0x7c,
+ 0x1c, 0x86, 0x52, 0x00, 0x53, 0x76, 0x55, 0x77, 0x00, 0x06, 0x76,
+ 0x24, 0x7c, 0x1d, 0x08, 0x10, 0x52, 0x00, 0x7c, 0x09, 0xb9, 0x20,
+ 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf,
+ 0xee, 0x3d, 0x00, 0x00, 0xb0, 0x3c, 0x7c, 0x1c, 0x51, 0x7c, 0x1c,
+ 0x9d, 0x51, 0x77, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50,
+ 0x03, 0x08, 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x51, 0x71, 0x53, 0x76,
+ 0x51, 0x70, 0x53, 0x77, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51,
+ 0x77, 0x08, 0x51, 0x76, 0x08, 0x7c, 0x1b, 0xdd, 0x18, 0x53, 0x76,
+ 0x18, 0x53, 0x77, 0x38, 0xfe, 0x7c, 0x1c, 0x79, 0x80, 0x63, 0x3d,
+ 0x00, 0x01, 0xb0, 0x2e, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x51, 0x7c,
+ 0x1c, 0x9d, 0x65, 0x76, 0x6b, 0x77, 0x65, 0x76, 0x6b, 0x77, 0x50,
+ 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x77, 0x08, 0x51, 0x76, 0x08,
+ 0x7c, 0x1b, 0xdd, 0x18, 0x53, 0x76, 0x18, 0x53, 0x77, 0x38, 0xfe,
+ 0x7c, 0x1c, 0x79, 0x80, 0x31, 0x3d, 0x00, 0x02, 0xb0, 0x2c, 0x62,
+ 0xd0, 0x00, 0x7c, 0x1c, 0x51, 0x7c, 0x1c, 0x9d, 0x65, 0x76, 0x6b,
+ 0x77, 0x65, 0x76, 0x6b, 0x77, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08,
+ 0x51, 0x77, 0x08, 0x51, 0x76, 0x08, 0x7c, 0x1b, 0xdd, 0x18, 0x53,
+ 0x76, 0x18, 0x53, 0x77, 0x38, 0xfe, 0x7c, 0x1c, 0x79, 0x62, 0xd0,
+ 0x00, 0x55, 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52, 0x00,
+ 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08,
+ 0x50, 0x06, 0x08, 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x7c, 0x1c, 0xbe,
+ 0x53, 0x79, 0x52, 0x19, 0x53, 0x76, 0x55, 0x77, 0x00, 0x65, 0x76,
+ 0x6b, 0x77, 0x7c, 0x1c, 0xe2, 0x53, 0x79, 0x7c, 0x1d, 0x34, 0x06,
+ 0x76, 0xa2, 0x0e, 0x77, 0x00, 0x51, 0x77, 0x7c, 0x1c, 0x92, 0x7c,
+ 0x1c, 0x79, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xce, 0xdd, 0x77, 0x19,
+ 0x3d, 0x19, 0x03, 0xce, 0xd1, 0x56, 0x00, 0x00, 0x80, 0xd0, 0x62,
+ 0xd0, 0x00, 0x55, 0x79, 0x03, 0x5a, 0x78, 0x06, 0x78, 0x01, 0x52,
+ 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x7c, 0x1c,
+ 0xbe, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1a, 0x3e, 0x78, 0x54, 0x1b,
+ 0x5a, 0x78, 0x06, 0x78, 0x03, 0x52, 0x00, 0x53, 0x76, 0x50, 0x00,
+ 0x08, 0x51, 0x76, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c,
+ 0x1c, 0x21, 0x38, 0xfc, 0x7c, 0x1c, 0xbe, 0x60, 0xd4, 0x3e, 0x78,
+ 0x54, 0x1c, 0x3e, 0x78, 0x54, 0x1d, 0x5a, 0x78, 0x06, 0x78, 0x05,
+ 0x52, 0x00, 0x53, 0x76, 0x50, 0x00, 0x08, 0x51, 0x76, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x1c, 0x21, 0x38, 0xfc, 0x7c,
+ 0x1c, 0xbe, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x1e, 0x3e, 0x78, 0x54,
+ 0x1f, 0x50, 0x03, 0x08, 0x5a, 0x78, 0x06, 0x78, 0x1a, 0x08, 0x51,
+ 0x78, 0x08, 0x7c, 0x1a, 0x33, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51,
+ 0x78, 0x54, 0x21, 0x51, 0x79, 0x54, 0x20, 0x7c, 0x1c, 0x51, 0x7c,
+ 0x1c, 0xb3, 0x7c, 0x1c, 0xfd, 0x06, 0x78, 0x5f, 0x7c, 0x1c, 0xed,
+ 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0x8a, 0x7c, 0x1c, 0xd1, 0x51,
+ 0x78, 0x01, 0x92, 0x7c, 0x1c, 0xd1, 0x06, 0x78, 0x9a, 0x7c, 0x1c,
+ 0xed, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0x7a, 0x7c, 0x1c, 0xd1,
+ 0x06, 0x78, 0x82, 0x7c, 0x1c, 0xed, 0x77, 0x00, 0x3d, 0x00, 0x04,
+ 0xcf, 0x2d, 0x56, 0x00, 0x00, 0x80, 0x19, 0x7c, 0x1c, 0x5d, 0x06,
+ 0x78, 0x24, 0x7c, 0x1c, 0x86, 0x52, 0x00, 0x53, 0x76, 0x55, 0x77,
+ 0x00, 0x06, 0x76, 0x32, 0x7c, 0x1d, 0x08, 0x77, 0x00, 0x3d, 0x00,
+ 0x04, 0xcf, 0xe4, 0x38, 0xde, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x07,
+ 0x56, 0x02, 0x00, 0x62, 0xd0, 0x00, 0x55, 0xc2, 0x00, 0x3c, 0xcb,
+ 0x00, 0xb0, 0x05, 0x51, 0xaa, 0x53, 0x24, 0x10, 0x50, 0x00, 0x7c,
+ 0x09, 0xb9, 0x20, 0x56, 0x00, 0x00, 0x80, 0xda, 0x62, 0xd0, 0x00,
+ 0x3c, 0xcb, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x78, 0x55, 0x79,
+ 0x00, 0x06, 0x78, 0xaa, 0x7c, 0x1c, 0x86, 0x52, 0x00, 0x53, 0x76,
+ 0x55, 0x77, 0x00, 0x06, 0x76, 0x24, 0x7c, 0x1d, 0x08, 0x10, 0x52,
+ 0x00, 0x7c, 0x09, 0xb9, 0x20, 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0,
+ 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00, 0x00, 0xb0, 0x3c,
+ 0x7c, 0x1c, 0x51, 0x7c, 0x1c, 0x9d, 0x51, 0x77, 0x08, 0x51, 0x76,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x7c, 0x1c, 0x21, 0x38,
+ 0xfc, 0x51, 0x71, 0x53, 0x76, 0x51, 0x70, 0x53, 0x77, 0x50, 0x00,
+ 0x08, 0x50, 0x05, 0x08, 0x51, 0x77, 0x08, 0x51, 0x76, 0x08, 0x7c,
+ 0x1b, 0xdd, 0x18, 0x53, 0x76, 0x18, 0x53, 0x77, 0x38, 0xfe, 0x7c,
+ 0x1c, 0x79, 0x80, 0x63, 0x3d, 0x00, 0x01, 0xb0, 0x2e, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x51, 0x7c, 0x1c, 0x9d, 0x65, 0x76, 0x6b, 0x77,
+ 0x65, 0x76, 0x6b, 0x77, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51,
+ 0x77, 0x08, 0x51, 0x76, 0x08, 0x7c, 0x1b, 0xdd, 0x18, 0x53, 0x76,
+ 0x18, 0x53, 0x77, 0x38, 0xfe, 0x7c, 0x1c, 0x79, 0x80, 0x31, 0x3d,
+ 0x00, 0x02, 0xb0, 0x2c, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x51, 0x7c,
+ 0x1c, 0x9d, 0x65, 0x76, 0x6b, 0x77, 0x65, 0x76, 0x6b, 0x77, 0x50,
+ 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x77, 0x08, 0x51, 0x76, 0x08,
+ 0x7c, 0x1b, 0xdd, 0x18, 0x53, 0x76, 0x18, 0x53, 0x77, 0x38, 0xfe,
+ 0x7c, 0x1c, 0x79, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xcf, 0x23, 0x56,
+ 0x00, 0x00, 0x82, 0xb5, 0x62, 0xd0, 0x00, 0x3c, 0xc0, 0x02, 0xa0,
+ 0xb1, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0x5f, 0x7c, 0x1c, 0x68,
+ 0x06, 0x78, 0xa2, 0x7c, 0x1c, 0x86, 0x3e, 0x78, 0x53, 0x78, 0x51,
+ 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x16, 0x7c, 0x1c,
+ 0x51, 0x51, 0x78, 0x01, 0x5f, 0x7c, 0x1c, 0x68, 0x06, 0x78, 0xa2,
+ 0x7c, 0x1c, 0x86, 0x7c, 0x1d, 0x65, 0x80, 0x17, 0x62, 0xd0, 0x00,
+ 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0xa2, 0x7c, 0x1c, 0x68, 0x06,
+ 0x78, 0x5f, 0x7c, 0x1c, 0x86, 0x7c, 0x1d, 0x65, 0x50, 0x90, 0x13,
+ 0x04, 0x50, 0x01, 0x1b, 0x03, 0xc0, 0x57, 0x62, 0xd0, 0x00, 0x7c,
+ 0x1c, 0x51, 0x51, 0x78, 0x01, 0x9a, 0x7c, 0x1c, 0x68, 0x06, 0x78,
+ 0xa2, 0x7c, 0x1c, 0x86, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76, 0x12,
+ 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x16, 0x7c, 0x1c, 0x51, 0x51,
+ 0x78, 0x01, 0x9a, 0x7c, 0x1c, 0x68, 0x06, 0x78, 0xa2, 0x7c, 0x1c,
+ 0x86, 0x7c, 0x1d, 0x58, 0x80, 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x1c,
+ 0x51, 0x51, 0x78, 0x01, 0xa2, 0x7c, 0x1c, 0x68, 0x06, 0x78, 0x9a,
+ 0x7c, 0x1c, 0x86, 0x7c, 0x1d, 0x58, 0x50, 0x90, 0x13, 0x06, 0x50,
+ 0x01, 0x1b, 0x05, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x76, 0xc2, 0x81,
+ 0xfb, 0x56, 0x01, 0x00, 0x80, 0x61, 0x62, 0xd0, 0x00, 0x7c, 0x1c,
+ 0x51, 0x51, 0x78, 0x01, 0xa2, 0x7c, 0x1c, 0x68, 0x06, 0x78, 0x92,
+ 0x7c, 0x1c, 0x86, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76, 0x12, 0x78,
+ 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x12, 0x7c, 0x1c, 0x51, 0x7c, 0x1c,
+ 0x9d, 0x06, 0x76, 0x01, 0x0e, 0x77, 0x00, 0x7c, 0x1c, 0x79, 0x80,
+ 0x2d, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0xa2,
+ 0x7c, 0x1c, 0x68, 0x06, 0x78, 0x92, 0x7c, 0x1c, 0x86, 0x3e, 0x78,
+ 0x12, 0x76, 0x51, 0x79, 0x1a, 0x77, 0xd0, 0x10, 0x7c, 0x1c, 0x51,
+ 0x7c, 0x1c, 0x9d, 0x16, 0x76, 0x01, 0x1e, 0x77, 0x00, 0x7c, 0x1c,
+ 0x79, 0x77, 0x01, 0x3d, 0x01, 0x04, 0xcf, 0x9c, 0x62, 0xd0, 0x00,
+ 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0x82, 0x7c, 0x1c, 0x68, 0x06,
+ 0x78, 0x7a, 0x0e, 0x79, 0x00, 0x7c, 0x1c, 0x79, 0x7c, 0x1c, 0x51,
+ 0x51, 0x78, 0x01, 0x8a, 0x7c, 0x1c, 0x68, 0x06, 0x78, 0x82, 0x0e,
+ 0x79, 0x00, 0x7c, 0x1c, 0x79, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01,
+ 0x92, 0x7c, 0x1c, 0x68, 0x06, 0x78, 0x8a, 0x0e, 0x79, 0x00, 0x7c,
+ 0x1c, 0x79, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0x9a, 0x7c, 0x1c,
+ 0x68, 0x06, 0x78, 0x92, 0x0e, 0x79, 0x00, 0x7c, 0x1c, 0x79, 0x7c,
+ 0x1c, 0x51, 0x51, 0x78, 0x01, 0xa2, 0x7c, 0x1c, 0x68, 0x06, 0x78,
+ 0x9a, 0x0e, 0x79, 0x00, 0x7c, 0x1c, 0x79, 0x7c, 0x1c, 0x51, 0x7c,
+ 0x1c, 0xb3, 0x53, 0x77, 0x7c, 0x1d, 0x40, 0x53, 0x74, 0x08, 0x51,
+ 0x75, 0x53, 0x73, 0x18, 0x53, 0x72, 0x65, 0x72, 0x6b, 0x73, 0x06,
+ 0x78, 0x92, 0x7c, 0x1c, 0x86, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x72,
+ 0x04, 0x78, 0x51, 0x73, 0x0c, 0x79, 0x51, 0x74, 0x04, 0x78, 0x51,
+ 0x75, 0x0c, 0x79, 0x70, 0xfb, 0x6e, 0x79, 0x6e, 0x78, 0x7c, 0x1d,
+ 0x21, 0x10, 0x52, 0x00, 0x7c, 0x06, 0xa1, 0x20, 0x62, 0xd0, 0x00,
+ 0x7c, 0x1c, 0x51, 0x06, 0x78, 0x67, 0x7c, 0x1c, 0x86, 0x3e, 0x78,
+ 0x53, 0x78, 0x50, 0x32, 0x12, 0x78, 0x50, 0x00, 0x1a, 0x79, 0xd0,
+ 0x1b, 0x55, 0x79, 0x01, 0x52, 0x00, 0xa0, 0x09, 0x62, 0xd0, 0x00,
+ 0x65, 0x79, 0x78, 0xbf, 0xf9, 0x62, 0xd0, 0x00, 0x51, 0xc5, 0x2a,
+ 0x79, 0x53, 0xc5, 0x80, 0x1b, 0x62, 0xd0, 0x00, 0x55, 0x79, 0x01,
+ 0x52, 0x00, 0xa0, 0x09, 0x62, 0xd0, 0x00, 0x65, 0x79, 0x78, 0xbf,
+ 0xf9, 0x62, 0xd0, 0x00, 0x51, 0x79, 0x73, 0x24, 0xc5, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x51, 0x51, 0x78, 0x01, 0xa2, 0x7c, 0x1c, 0x68,
+ 0x06, 0x78, 0x5f, 0x7c, 0x1c, 0x86, 0x3e, 0x78, 0x53, 0x78, 0x51,
+ 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x25, 0x52, 0x00,
+ 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78, 0xba, 0x0e, 0x79, 0x00,
+ 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x7a, 0x78, 0x53, 0x77, 0x06,
+ 0x77, 0x01, 0x51, 0x79, 0x60, 0xd5, 0x51, 0x77, 0x3f, 0x78, 0x80,
+ 0x0a, 0x97, 0xcf, 0x40, 0x06, 0x78, 0xba, 0x7c, 0x1d, 0x4c, 0x97,
+ 0xc6, 0x40, 0x06, 0x78, 0xba, 0x97, 0xe9, 0x40, 0x50, 0x05, 0x3a,
+ 0x79, 0xd0, 0x41, 0x97, 0xab, 0x40, 0x51, 0x78, 0x01, 0x5f, 0x53,
+ 0x76, 0x51, 0x79, 0x09, 0x00, 0x53, 0x77, 0x06, 0x78, 0xa2, 0x97,
+ 0xce, 0x40, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x77, 0x7c, 0x1d, 0x40,
+ 0x02, 0x78, 0x53, 0x78, 0x51, 0x75, 0x0a, 0x79, 0x53, 0x79, 0x7c,
+ 0x1d, 0x21, 0x52, 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x06, 0x78,
+ 0xba, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd5, 0x50, 0x00, 0x3f,
+ 0x78, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xcd, 0x48, 0x62, 0xd0, 0x00,
+ 0x3c, 0xc0, 0x02, 0xb1, 0x73, 0x56, 0x00, 0x00, 0x81, 0x69, 0x3d,
+ 0x00, 0x00, 0xb0, 0x49, 0x62, 0xd0, 0x00, 0x97, 0x4f, 0x40, 0x51,
+ 0x78, 0x01, 0xa2, 0x97, 0x5f, 0x40, 0x51, 0x77, 0x08, 0x51, 0x76,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x7c, 0x1c, 0x21, 0x38,
+ 0xfc, 0x51, 0x71, 0x53, 0x76, 0x51, 0x70, 0x53, 0x77, 0x50, 0x00,
+ 0x08, 0x50, 0x03, 0x08, 0x51, 0x77, 0x08, 0x51, 0x76, 0x08, 0x7c,
+ 0x1b, 0xdd, 0x18, 0x53, 0x76, 0x18, 0x53, 0x77, 0x38, 0xfe, 0x06,
+ 0x78, 0x3e, 0x0e, 0x79, 0x00, 0x97, 0x37, 0x40, 0x80, 0xa0, 0x3d,
+ 0x00, 0x01, 0xb0, 0x3e, 0x62, 0xd0, 0x00, 0x97, 0x02, 0x40, 0x51,
+ 0x78, 0x01, 0xa2, 0x97, 0x12, 0x40, 0x51, 0x77, 0x08, 0x51, 0x76,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x7c, 0x1c, 0x21, 0x38,
+ 0xfc, 0x51, 0x71, 0x53, 0x76, 0x51, 0x70, 0x53, 0x77, 0x70, 0xfb,
+ 0x6e, 0x77, 0x6e, 0x76, 0x70, 0xfb, 0x6e, 0x77, 0x6e, 0x76, 0x06,
+ 0x78, 0x3e, 0x0e, 0x79, 0x00, 0x96, 0xf5, 0x40, 0x80, 0x5e, 0x3d,
+ 0x00, 0x02, 0xb0, 0x3e, 0x62, 0xd0, 0x00, 0x96, 0xc0, 0x40, 0x51,
+ 0x78, 0x01, 0xa2, 0x96, 0xd0, 0x40, 0x51, 0x77, 0x08, 0x51, 0x76,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x7c, 0x1c, 0x21, 0x38,
+ 0xfc, 0x51, 0x71, 0x53, 0x76, 0x51, 0x70, 0x53, 0x77, 0x70, 0xfb,
+ 0x6e, 0x77, 0x6e, 0x76, 0x70, 0xfb, 0x6e, 0x77, 0x6e, 0x76, 0x06,
+ 0x78, 0x3e, 0x0e, 0x79, 0x00, 0x96, 0xb3, 0x40, 0x80, 0x1c, 0x3d,
+ 0x00, 0x03, 0xb0, 0x17, 0x62, 0xd0, 0x00, 0x96, 0x7e, 0x40, 0x51,
+ 0x78, 0x01, 0xa2, 0x96, 0x8e, 0x40, 0x06, 0x78, 0x3e, 0x0e, 0x79,
+ 0x00, 0x96, 0x96, 0x40, 0x62, 0xd0, 0x00, 0x96, 0x68, 0x40, 0x51,
+ 0x78, 0x01, 0x5f, 0x96, 0x78, 0x40, 0x06, 0x78, 0x46, 0x0e, 0x79,
+ 0x00, 0x96, 0x80, 0x40, 0x96, 0x55, 0x40, 0x51, 0x78, 0x01, 0x5f,
+ 0x96, 0x65, 0x40, 0x51, 0x78, 0x01, 0xa2, 0x53, 0x74, 0x51, 0x79,
+ 0x97, 0x71, 0x40, 0x51, 0x76, 0x12, 0x74, 0x51, 0x77, 0x1a, 0x75,
+ 0xd0, 0x2b, 0x97, 0x19, 0x40, 0x51, 0x76, 0x01, 0x5f, 0x53, 0x74,
+ 0x51, 0x77, 0x97, 0x59, 0x40, 0x06, 0x76, 0xa2, 0x0e, 0x77, 0x00,
+ 0x51, 0x77, 0x60, 0xd4, 0x3e, 0x76, 0x53, 0x77, 0x3e, 0x76, 0x12,
+ 0x74, 0x54, 0x04, 0x51, 0x77, 0x1a, 0x75, 0x54, 0x03, 0x80, 0x07,
+ 0x56, 0x04, 0x00, 0x56, 0x03, 0x00, 0x62, 0xd0, 0x00, 0x06, 0x78,
+ 0x36, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd5, 0x52, 0x03, 0x3f,
+ 0x78, 0x52, 0x04, 0x3f, 0x78, 0x77, 0x00, 0x3d, 0x00, 0x04, 0xce,
+ 0x94, 0x62, 0xd0, 0x00, 0x3c, 0xc0, 0x02, 0xa0, 0x1e, 0x3c, 0xc2,
+ 0x00, 0xa0, 0x19, 0x55, 0xc2, 0x00, 0x55, 0xcd, 0x00, 0x50, 0x75,
+ 0x08, 0x50, 0x30, 0x08, 0x90, 0x0e, 0x38, 0xfe, 0x7c, 0x0c, 0x09,
+ 0x10, 0x7c, 0x08, 0x5d, 0x20, 0x38, 0xf9, 0x20, 0x7f, 0x10, 0x4f,
+ 0x80, 0x02, 0x40, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53, 0x78, 0x52,
+ 0xfb, 0x53, 0x79, 0x51, 0x78, 0x11, 0x01, 0x54, 0xfc, 0x51, 0x79,
+ 0x19, 0x00, 0x54, 0xfb, 0x3c, 0x79, 0x00, 0xbf, 0xe4, 0x3c, 0x78,
+ 0x00, 0xbf, 0xdf, 0x20, 0x7f, 0x10, 0x7c, 0x05, 0x28, 0x7c, 0x05,
+ 0x05, 0x7c, 0x04, 0xe2, 0x7c, 0x04, 0xbf, 0x20, 0x7f, 0x10, 0x7c,
+ 0x05, 0x24, 0x7c, 0x05, 0x01, 0x7c, 0x04, 0xde, 0x7c, 0x04, 0xbb,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x05, 0x62, 0xd0, 0x00, 0x51, 0x68,
+ 0x54, 0x02, 0x51, 0x67, 0x54, 0x01, 0x56, 0x04, 0x00, 0x56, 0x00,
+ 0x00, 0x56, 0x03, 0x00, 0x80, 0x52, 0x62, 0xd0, 0x00, 0x95, 0x5e,
+ 0x40, 0x06, 0x78, 0x67, 0x95, 0x8d, 0x40, 0x3e, 0x78, 0x53, 0x78,
+ 0x50, 0x32, 0x12, 0x78, 0x50, 0x00, 0x1a, 0x79, 0xd0, 0x03, 0x77,
+ 0x03, 0x62, 0xd0, 0x00, 0x95, 0x42, 0x40, 0x06, 0x78, 0x67, 0x95,
+ 0x71, 0x40, 0x3e, 0x78, 0x53, 0x78, 0x52, 0x02, 0x12, 0x78, 0x52,
+ 0x01, 0x1a, 0x79, 0xd0, 0x1a, 0x95, 0x2b, 0x40, 0x06, 0x78, 0x67,
+ 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x01,
+ 0x3e, 0x78, 0x54, 0x02, 0x52, 0x00, 0x54, 0x04, 0x77, 0x00, 0x3d,
+ 0x00, 0x04, 0xcf, 0xab, 0x50, 0x01, 0x3b, 0x03, 0xd0, 0x08, 0x62,
+ 0xd0, 0x00, 0x50, 0xe1, 0x80, 0x06, 0x52, 0x04, 0x62, 0xd0, 0x00,
+ 0x38, 0xfb, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x62, 0xd0, 0x00,
+ 0x3c, 0xc2, 0x00, 0xa0, 0x07, 0x51, 0x2c, 0x29, 0x10, 0x53, 0x2c,
+ 0x62, 0xd0, 0x00, 0x3c, 0xc3, 0x00, 0xb0, 0x73, 0x70, 0xfe, 0x51,
+ 0xce, 0x01, 0x01, 0x53, 0x2c, 0x71, 0x01, 0x62, 0xe3, 0x38, 0x10,
+ 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56,
+ 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00,
+ 0x20, 0x53, 0x79, 0x47, 0x79, 0x20, 0xa0, 0x03, 0x80, 0x12, 0x50,
+ 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0xe4, 0x38, 0xfe, 0x77, 0x00,
+ 0x3d, 0x00, 0xc8, 0xcf, 0xdf, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10,
+ 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x79, 0x47, 0x79,
+ 0x20, 0xb0, 0x03, 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08,
+ 0x9e, 0xbd, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00, 0x1e, 0xcf, 0xdf,
+ 0x62, 0xd0, 0x00, 0x51, 0x2c, 0x29, 0x08, 0x53, 0x2c, 0x43, 0x00,
+ 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x62, 0xd0,
+ 0x00, 0x3c, 0xc2, 0x00, 0xa0, 0x07, 0x51, 0x2c, 0x29, 0x10, 0x53,
+ 0x2c, 0x62, 0xd0, 0x00, 0x3c, 0xc3, 0x01, 0xb0, 0x6a, 0x70, 0xfe,
+ 0x51, 0xce, 0x01, 0x09, 0x53, 0x2c, 0x71, 0x01, 0x62, 0xe3, 0x38,
+ 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7,
+ 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0,
+ 0x00, 0x20, 0x53, 0x79, 0x47, 0x79, 0x20, 0xa0, 0x03, 0x80, 0x12,
+ 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0x54, 0x38, 0xfe, 0x77,
+ 0x00, 0x3d, 0x00, 0xc8, 0xcf, 0xdf, 0x56, 0x00, 0x00, 0x80, 0x1e,
+ 0x10, 0x7c, 0x06, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x79, 0x47,
+ 0x79, 0x20, 0xb0, 0x03, 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14,
+ 0x08, 0x9e, 0x2d, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00, 0x1e, 0xcf,
+ 0xdf, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38,
+ 0x02, 0x62, 0xd0, 0x00, 0x51, 0x2c, 0x54, 0x00, 0x51, 0x2f, 0x54,
+ 0x01, 0x3d, 0x00, 0x01, 0xb0, 0x1d, 0x3c, 0xca, 0x00, 0xb0, 0x18,
+ 0x55, 0xc6, 0x00, 0x55, 0xb7, 0x00, 0x55, 0xb6, 0x00, 0x55, 0xb9,
+ 0x00, 0x55, 0xb8, 0x00, 0x55, 0x2c, 0x00, 0x55, 0xca, 0x01, 0x80,
+ 0x8e, 0x3d, 0x00, 0x02, 0xb0, 0x1a, 0x62, 0xd0, 0x00, 0x3c, 0xca,
+ 0x01, 0xb0, 0x12, 0x55, 0xc6, 0x01, 0x55, 0xc7, 0x00, 0x94, 0x5e,
+ 0x40, 0x55, 0x2c, 0x00, 0x55, 0xca, 0x00, 0x80, 0x70, 0x52, 0x00,
+ 0x21, 0xf0, 0x39, 0x40, 0xb0, 0x0c, 0x62, 0xd0, 0x00, 0x55, 0xc0,
+ 0x02, 0x55, 0x2c, 0x00, 0x80, 0x5d, 0x52, 0x00, 0x21, 0xf0, 0x39,
+ 0x50, 0xb0, 0x55, 0x3d, 0x01, 0x01, 0xb0, 0x15, 0x62, 0xd0, 0x00,
+ 0x55, 0xcb, 0x01, 0x7c, 0x0e, 0xb8, 0x62, 0xd0, 0x00, 0x51, 0x31,
+ 0x29, 0x80, 0x53, 0x31, 0x80, 0x27, 0x3d, 0x01, 0x02, 0xb0, 0x16,
+ 0x62, 0xd0, 0x00, 0x51, 0x30, 0x53, 0x52, 0x51, 0x30, 0x53, 0x53,
+ 0x51, 0x30, 0x53, 0x54, 0x51, 0x30, 0x53, 0x55, 0x80, 0x0d, 0x3d,
+ 0x01, 0x04, 0xb0, 0x08, 0x62, 0xd0, 0x00, 0x51, 0x30, 0x53, 0x0d,
+ 0x62, 0xd0, 0x00, 0x55, 0x2d, 0x0b, 0x55, 0x2e, 0x03, 0x56, 0x00,
+ 0x00, 0x56, 0x01, 0x00, 0x55, 0x2f, 0x00, 0x55, 0x2c, 0x00, 0x38,
+ 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x04, 0x62, 0xd0, 0x00, 0x3c,
+ 0xc6, 0x00, 0xa0, 0x13, 0x9d, 0x76, 0x62, 0xd0, 0x00, 0x3c, 0xc7,
+ 0x00, 0xb0, 0xe8, 0x55, 0xc7, 0x01, 0x7c, 0x0c, 0x09, 0x80, 0xe0,
+ 0x62, 0xd0, 0x00, 0x3c, 0xc9, 0x00, 0xb0, 0x27, 0x3c, 0xc8, 0x01,
+ 0xb0, 0x22, 0x51, 0xce, 0x53, 0x78, 0x55, 0x79, 0x00, 0x65, 0x78,
+ 0x6b, 0x79, 0x06, 0x78, 0x67, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60,
+ 0xd4, 0x3e, 0x78, 0x54, 0x01, 0x3e, 0x78, 0x54, 0x02, 0x51, 0xce,
+ 0x54, 0x00, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0xb6, 0xd0, 0x08,
+ 0x10, 0x7c, 0x05, 0x28, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x05, 0x24,
+ 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0xb7, 0xd0, 0x08, 0x10,
+ 0x7c, 0x05, 0x05, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x05, 0x01, 0x20,
+ 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0xb8, 0xd0, 0x08, 0x10, 0x7c,
+ 0x04, 0xe2, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0xde, 0x20, 0x62,
+ 0xd0, 0x00, 0x50, 0x01, 0x3a, 0xb9, 0xd0, 0x08, 0x10, 0x7c, 0x04,
+ 0xbf, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0xbb, 0x20, 0x7c, 0x11,
+ 0x2d, 0x62, 0xd0, 0x00, 0x3c, 0xc9, 0x00, 0xb0, 0x53, 0x3c, 0xc8,
+ 0x01, 0xb0, 0x4e, 0x3c, 0xc2, 0x00, 0xb0, 0x40, 0x92, 0x68, 0x40,
+ 0x51, 0x78, 0x01, 0x5f, 0x92, 0x78, 0x40, 0x06, 0x76, 0x32, 0x0e,
+ 0x77, 0x00, 0x06, 0x78, 0xa2, 0x92, 0x8a, 0x40, 0x3e, 0x78, 0x53,
+ 0x78, 0x51, 0x76, 0x12, 0x78, 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x1c,
+ 0x92, 0x44, 0x40, 0x51, 0x78, 0x01, 0xa2, 0x92, 0x54, 0x40, 0x52,
+ 0x02, 0x14, 0x76, 0x52, 0x01, 0x1c, 0x77, 0x06, 0x78, 0x5f, 0x0e,
+ 0x79, 0x00, 0x92, 0x54, 0x40, 0x62, 0xd0, 0x00, 0x55, 0xc9, 0x01,
+ 0x55, 0xc8, 0x00, 0x38, 0xfc, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x03,
+ 0x56, 0x02, 0x00, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x3e,
+ 0x62, 0xd0, 0x00, 0x92, 0x0a, 0x40, 0x52, 0xfc, 0x04, 0x78, 0x52,
+ 0xfb, 0x0c, 0x79, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x53, 0x79,
+ 0x3e, 0x78, 0x53, 0x78, 0x52, 0x02, 0x12, 0x78, 0x52, 0x01, 0x1a,
+ 0x79, 0xd0, 0x18, 0x91, 0xe9, 0x40, 0x52, 0xfc, 0x04, 0x78, 0x52,
+ 0xfb, 0x0c, 0x79, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x54, 0x01,
+ 0x3e, 0x78, 0x54, 0x02, 0x77, 0x00, 0x52, 0x00, 0x3b, 0xfa, 0xcf,
+ 0xbe, 0x62, 0xd0, 0x00, 0x52, 0x02, 0x53, 0x78, 0x52, 0x01, 0x53,
+ 0x79, 0x38, 0xfd, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x71, 0x10,
+ 0x41, 0x01, 0xf7, 0x43, 0x00, 0x08, 0x70, 0xcf, 0x43, 0x00, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0x64, 0x08, 0x9b, 0xe1, 0x71, 0x10, 0x41,
+ 0x01, 0xf7, 0x41, 0x00, 0xf7, 0x70, 0xcf, 0x43, 0x00, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x64, 0x08, 0x9b, 0xcc, 0x38, 0xfc, 0x5d, 0x00,
+ 0x62, 0xd0, 0x00, 0x53, 0x79, 0x26, 0x79, 0x08, 0x3c, 0x79, 0x08,
+ 0xb0, 0x09, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x07, 0x56,
+ 0x01, 0x01, 0x56, 0x00, 0x00, 0x52, 0x01, 0x62, 0xd0, 0x00, 0x53,
+ 0xc0, 0x71, 0x10, 0x43, 0x00, 0x08, 0x41, 0x01, 0xf7, 0x70, 0xcf,
+ 0x3c, 0xc0, 0x00, 0xb0, 0x04, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20,
+ 0x7f, 0x10, 0x4f, 0x38, 0x01, 0x62, 0xe3, 0x38, 0x10, 0x50, 0x02,
+ 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x91, 0x20,
+ 0x10, 0x50, 0xff, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0x08, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0xa2, 0x08, 0x7c, 0x04, 0x76, 0x38, 0xfd,
+ 0x20, 0x56, 0x00, 0x00, 0x80, 0x6e, 0x62, 0xd0, 0x00, 0x91, 0x1d,
+ 0x40, 0x51, 0x78, 0x01, 0x5f, 0x91, 0x2d, 0x40, 0x06, 0x78, 0xa2,
+ 0x91, 0x45, 0x40, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76, 0x12, 0x78,
+ 0x51, 0x77, 0x1a, 0x79, 0xd0, 0x3d, 0x90, 0xff, 0x40, 0x51, 0x78,
+ 0x01, 0x5f, 0x91, 0x0f, 0x40, 0x06, 0x78, 0xa2, 0x91, 0x27, 0x40,
+ 0x92, 0x10, 0x40, 0x51, 0x79, 0x10, 0x7c, 0x03, 0x91, 0x20, 0x62,
+ 0xd0, 0x00, 0x90, 0xe2, 0x40, 0x51, 0x78, 0x01, 0x5f, 0x90, 0xf2,
+ 0x40, 0x06, 0x78, 0xa2, 0x91, 0x0a, 0x40, 0x91, 0xf3, 0x40, 0x26,
+ 0x79, 0x00, 0x51, 0x78, 0x10, 0x7c, 0x03, 0x91, 0x20, 0x80, 0x0f,
+ 0x10, 0x50, 0x00, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0x00, 0x7c,
+ 0x03, 0x91, 0x20, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x8f, 0x10,
+ 0x50, 0x00, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0x01, 0x7c, 0x03,
+ 0x91, 0x20, 0x10, 0x50, 0x00, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50,
+ 0x01, 0x7c, 0x03, 0x91, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x91,
+ 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x91, 0x7c, 0x04, 0x6d, 0x20,
+ 0x50, 0x13, 0x08, 0x50, 0x88, 0x08, 0x9a, 0xb8, 0x38, 0xfe, 0x38,
+ 0xff, 0x20, 0x7f, 0x7f, 0x10, 0x4f, 0x7c, 0x1b, 0xe8, 0x20, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50,
+ 0x00, 0x53, 0x70, 0x53, 0x71, 0x55, 0x6f, 0x10, 0x66, 0xfc, 0x6c,
+ 0xfb, 0x6b, 0x70, 0x6b, 0x71, 0x51, 0x70, 0x1b, 0xfa, 0x51, 0x71,
+ 0x1b, 0xf9, 0xc0, 0x09, 0x53, 0x71, 0x52, 0xfa, 0x1c, 0x70, 0x77,
+ 0xfc, 0x7a, 0x6f, 0xbf, 0xe3, 0x51, 0x70, 0x54, 0xfa, 0x51, 0x71,
+ 0x54, 0xf9, 0x18, 0x60, 0xd0, 0x7f, 0x10, 0x4f, 0x5d, 0xd0, 0x08,
+ 0x62, 0xd0, 0x00, 0x50, 0x00, 0x53, 0x71, 0x53, 0x70, 0x55, 0x6f,
+ 0x10, 0x6f, 0xf9, 0x6f, 0xfa, 0xd0, 0x09, 0x52, 0xfc, 0x04, 0x71,
+ 0x52, 0xfb, 0x0c, 0x70, 0x66, 0xfc, 0x6c, 0xfb, 0x7a, 0x6f, 0xbf,
+ 0xeb, 0x18, 0x60, 0xd0, 0x20, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x52,
+ 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x65, 0x78, 0x6b, 0x79, 0x7f,
+ 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x78, 0x55, 0x79, 0x00, 0x7f,
+ 0x53, 0x76, 0x51, 0x79, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x76, 0x53,
+ 0x77, 0x3e, 0x76, 0x53, 0x76, 0x7f, 0x51, 0x79, 0x60, 0xd5, 0x51,
+ 0x77, 0x3f, 0x78, 0x51, 0x76, 0x3f, 0x78, 0x7f, 0x0e, 0x79, 0x00,
+ 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x53, 0x79, 0x7f, 0x60, 0xd4,
+ 0x3e, 0x76, 0x53, 0x77, 0x3e, 0x76, 0x53, 0x76, 0x7f, 0x06, 0x78,
+ 0xa2, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd4, 0x3e, 0x78, 0x53,
+ 0x77, 0x3e, 0x78, 0x16, 0x78, 0x02, 0x53, 0x76, 0x7f, 0x51, 0x78,
+ 0x01, 0xa2, 0x53, 0x76, 0x51, 0x79, 0x09, 0x00, 0x7f, 0x51, 0x71,
+ 0x53, 0x76, 0x51, 0x70, 0x53, 0x77, 0x51, 0x76, 0x02, 0x78, 0x53,
+ 0x78, 0x51, 0x77, 0x0a, 0x79, 0x7f, 0x53, 0x76, 0x51, 0x79, 0x09,
+ 0x00, 0x60, 0xd5, 0x52, 0x20, 0x3f, 0x76, 0x52, 0x21, 0x3f, 0x76,
+ 0x7f, 0x51, 0x76, 0x02, 0x78, 0x53, 0x78, 0x51, 0x77, 0x0a, 0x79,
+ 0x7f, 0x0e, 0x79, 0x00, 0x51, 0x79, 0x60, 0xd5, 0x52, 0x20, 0x3f,
+ 0x78, 0x52, 0x21, 0x3f, 0x78, 0x7f, 0x60, 0xd5, 0x52, 0x20, 0x3f,
+ 0x76, 0x52, 0x21, 0x3f, 0x76, 0x7f, 0x0e, 0x77, 0x00, 0x51, 0x77,
+ 0x60, 0xd5, 0x51, 0x79, 0x3f, 0x76, 0x7f, 0x55, 0xb7, 0x08, 0x55,
+ 0xb6, 0x08, 0x55, 0xb9, 0x08, 0x55, 0xb8, 0x08, 0x7f, 0x70, 0xfb,
+ 0x6e, 0x79, 0x6e, 0x78, 0x51, 0x77, 0x60, 0xd5, 0x51, 0x79, 0x3f,
+ 0x76, 0x51, 0x78, 0x3f, 0x76, 0x7f, 0x52, 0x00, 0x53, 0x76, 0x55,
+ 0x77, 0x00, 0x65, 0x76, 0x6b, 0x77, 0x7f, 0x60, 0xd4, 0x3e, 0x76,
+ 0x53, 0x75, 0x3e, 0x76, 0x16, 0x76, 0x02, 0x7f, 0x0e, 0x79, 0x00,
+ 0x51, 0x79, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x78, 0x7f, 0x3e, 0x78,
+ 0x12, 0x76, 0x54, 0x06, 0x51, 0x79, 0x1a, 0x77, 0x54, 0x05, 0x7f,
+ 0x3e, 0x78, 0x12, 0x76, 0x54, 0x04, 0x51, 0x79, 0x1a, 0x77, 0x54,
+ 0x03, 0x7f, 0x3e, 0x78, 0x53, 0x78, 0x51, 0x76, 0x14, 0x78, 0x51,
+ 0x77, 0x1c, 0x79, 0x7f, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x74, 0x53,
+ 0x75, 0x3e, 0x74, 0x53, 0x74, 0x7f, 0x00, 0x2c, 0x00, 0x22, 0x00,
+ 0x7a, 0x00, 0x28, 0x00, 0xaa, 0x04, 0x2a, 0x31, 0x33, 0x39, 0x00,
+ 0xae, 0x00, 0x05, 0x00, 0xb3, 0x07, 0x01, 0x02, 0x03, 0x08, 0x08,
+ 0x08, 0x08, 0x00, 0xba, 0x00, 0x0a, 0x00, 0xc4, 0x04, 0x03, 0x00,
+ 0x01, 0x01, 0x00, 0xc8, 0x00, 0x07, 0xff, 0x00, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_NTT.h b/drivers/input/keyboard/cypressbln/touchkey_fw_NTT.h
new file mode 100644
index 0000000..b5b5564
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_NTT.h
@@ -0,0 +1,685 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x04, 0x6f, 0x7e, 0x7e, 0x30, 0x30, 0x30,
+ 0x7d, 0x05, 0xa4, 0x7e, 0x7d, 0x04, 0x28, 0x7e, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x10, 0x41, 0xd7,
+ 0x9f, 0x70, 0xef, 0x40, 0x71, 0x10, 0x62, 0xe3, 0x00, 0x70, 0xef, 0x50,
+ 0x80, 0x4e, 0x5d, 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55, 0xfa, 0x01, 0x40,
+ 0x4f, 0x5b, 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a, 0x50, 0x06, 0x00,
+ 0x40, 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8, 0x70, 0xef, 0x18, 0x60,
+ 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00, 0x71, 0x10, 0x41, 0xe1, 0xfe,
+ 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1, 0x03, 0x50, 0x00, 0x4e, 0x62,
+ 0xd3, 0x03, 0x62, 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4, 0x00, 0x71,
+ 0xc0, 0x7c, 0x02, 0x71, 0x62, 0xd0, 0x00, 0x50, 0x02, 0x57, 0x6f, 0x08,
+ 0x28, 0x53, 0x40, 0x18, 0x75, 0x09, 0x00, 0x28, 0x4b, 0x51, 0x40, 0x80,
+ 0x04, 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00, 0x08, 0x28, 0x60, 0xd5, 0x74,
+ 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x53, 0x40, 0x18, 0x75,
+ 0x09, 0x00, 0x08, 0x28, 0xa0, 0x1c, 0x53, 0x3f, 0x18, 0x75, 0x09, 0x00,
+ 0x08, 0x28, 0x3f, 0x40, 0x47, 0x40, 0xff, 0xb0, 0x06, 0x5d, 0xd5, 0x74,
+ 0x60, 0xd5, 0x18, 0x7a, 0x3f, 0xbf, 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09,
+ 0x00, 0x08, 0x28, 0x53, 0x3f, 0x50, 0x00, 0x3f, 0x40, 0x47, 0x40, 0xff,
+ 0xb0, 0x08, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x3f, 0xbf,
+ 0xef, 0x18, 0x8f, 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70, 0xef,
+ 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71, 0x10, 0x62,
+ 0xe0, 0x12, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x09, 0x1c, 0x8f, 0xff,
+ 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x61, 0x00,
+ 0xfd, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xa5, 0x00, 0xa4, 0x00, 0xa0, 0x00,
+ 0xa1, 0x80, 0xa2, 0x80, 0xa3, 0x0c, 0xa8, 0x00, 0xa6, 0x00, 0xa7, 0x00,
+ 0x7c, 0x33, 0x7a, 0x00, 0x7b, 0x04, 0x79, 0x00, 0x36, 0x00, 0x37, 0x00,
+ 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00,
+ 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00,
+ 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00,
+ 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00,
+ 0xd6, 0x44, 0xcf, 0x00, 0xca, 0x00, 0xcb, 0x00, 0xc8, 0x00, 0xcc, 0x00,
+ 0xc9, 0x00, 0xd7, 0x00, 0x2b, 0x00, 0xb0, 0x00, 0xb3, 0x02, 0xb6, 0x00,
+ 0xb2, 0x00, 0xb5, 0x00, 0xb8, 0xff, 0xb1, 0x00, 0xb4, 0x00, 0xb7, 0x7f,
+ 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0xff, 0x54, 0x00, 0x55, 0x00, 0x56,
+ 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0xdc,
+ 0x00, 0xe2, 0x00, 0xdd, 0x00, 0xd8, 0x02, 0xd9, 0x00, 0xda, 0x00, 0xdb,
+ 0x00, 0xdf, 0x00, 0x29, 0x00, 0x30, 0x00, 0xbd, 0x00, 0xff, 0x70, 0xef,
+ 0x62, 0x00, 0x00, 0x71, 0x10, 0x62, 0x00, 0x08, 0x62, 0x01, 0x92, 0x70,
+ 0xef, 0x62, 0x04, 0x17, 0x71, 0x10, 0x62, 0x04, 0x14, 0x62, 0x05, 0xa8,
+ 0x70, 0xef, 0x62, 0x08, 0x00, 0x71, 0x10, 0x62, 0x08, 0x00, 0x62, 0x09,
+ 0x28, 0x70, 0xef, 0x62, 0x0c, 0x00, 0x71, 0x10, 0x62, 0x0c, 0x00, 0x62,
+ 0x0d, 0x00, 0x70, 0xef, 0x62, 0x10, 0x00, 0x71, 0x10, 0x62, 0x10, 0x00,
+ 0x62, 0x11, 0x00, 0x70, 0xef, 0x62, 0x01, 0x00, 0x62, 0x05, 0x00, 0x62,
+ 0x09, 0x00, 0x62, 0x0d, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef, 0x7f, 0x13,
+ 0xba, 0x55, 0x02, 0x00, 0x55, 0x03, 0x17, 0x55, 0x04, 0x00, 0x7c, 0x02,
+ 0x81, 0x7c, 0x02, 0x1a, 0x7f, 0x10, 0x70, 0xef, 0x50, 0x00, 0x67, 0x50,
+ 0x01, 0x57, 0x72, 0x7c, 0x02, 0x9c, 0x50, 0x01, 0x67, 0x50, 0x01, 0x57,
+ 0xf3, 0x7c, 0x02, 0x9c, 0x70, 0xef, 0x20, 0x7f, 0x38, 0x02, 0x10, 0x08,
+ 0x4f, 0x56, 0xfc, 0x00, 0xd0, 0x04, 0x56, 0xfc, 0x01, 0x18, 0x20, 0x70,
+ 0xef, 0x62, 0xe3, 0x00, 0x10, 0x08, 0x28, 0x39, 0xff, 0xa0, 0x1f, 0x4f,
+ 0x48, 0xfc, 0x01, 0xa0, 0x03, 0x71, 0x10, 0x54, 0xfd, 0x18, 0x20, 0x75,
+ 0x09, 0x00, 0x10, 0x08, 0x28, 0x4f, 0x59, 0xfd, 0x61, 0x00, 0x18, 0x20,
+ 0x75, 0x09, 0x00, 0x8f, 0xd7, 0x38, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42,
+ 0x43, 0x44, 0x45, 0x46, 0x2e, 0x02, 0x08, 0x51, 0x02, 0x60, 0x00, 0x71,
+ 0x10, 0x41, 0x01, 0xf7, 0x43, 0x00, 0x08, 0x70, 0xef, 0x7f, 0x62, 0xd0,
+ 0x00, 0x53, 0x00, 0x71, 0x10, 0x5d, 0xe0, 0x08, 0x21, 0xf8, 0x29, 0x00,
+ 0x70, 0xfe, 0x60, 0xe0, 0x70, 0xef, 0x4b, 0x4b, 0x4b, 0x4b, 0x51, 0x02,
+ 0x21, 0xf7, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05,
+ 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00,
+ 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01,
+ 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08,
+ 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x47, 0x00, 0x00, 0x49,
+ 0x01, 0x00, 0x29, 0x08, 0x60, 0x00, 0x57, 0x01, 0x79, 0xbf, 0xfe, 0x18,
+ 0x71, 0x10, 0x60, 0xe0, 0x70, 0xef, 0x71, 0x01, 0x7f, 0x08, 0x67, 0x67,
+ 0x67, 0x67, 0x21, 0x0f, 0xff, 0x2e, 0x9f, 0x4e, 0x18, 0x21, 0x0f, 0xff,
+ 0x27, 0x9f, 0x47, 0x7f, 0x08, 0x10, 0x28, 0xa0, 0x0b, 0x9f, 0x3f, 0x20,
+ 0x18, 0x75, 0xdf, 0xf5, 0x74, 0x8f, 0xf2, 0x38, 0xfe, 0x7f, 0x52, 0x00,
+ 0xa0, 0x08, 0x10, 0x9f, 0x2d, 0x20, 0x75, 0x8f, 0xf6, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x50, 0x0d, 0x9f, 0x20, 0x50, 0x0a, 0x9f, 0x1c, 0x7f, 0x70,
+ 0xbf, 0x62, 0xd3, 0x03, 0x4f, 0x52, 0xfb, 0xa0, 0x15, 0x7b, 0xfb, 0x52,
+ 0xfc, 0x59, 0xfd, 0x60, 0xd3, 0x52, 0x00, 0x9f, 0x05, 0x4f, 0x62, 0xd3,
+ 0x03, 0x77, 0xfd, 0x8f, 0xe9, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x3d, 0xfa,
+ 0x00, 0xb0, 0x06, 0x3d, 0xfb, 0x00, 0xa0, 0x18, 0x10, 0x52, 0xfc, 0x59,
+ 0xfd, 0x28, 0x9e, 0xe6, 0x20, 0x07, 0xfd, 0x01, 0x0f, 0xfc, 0x00, 0x17,
+ 0xfb, 0x01, 0x1f, 0xfa, 0x00, 0x8f, 0xe0, 0x7f, 0x7e, 0x50, 0x01, 0x80,
+ 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03,
+ 0xef, 0x80, 0x04, 0x2e, 0x03, 0x10, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03,
+ 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xfb,
+ 0x80, 0x04, 0x2e, 0x03, 0x04, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x10, 0x70, 0x3f, 0x71,
+ 0x80, 0x5d, 0xd3, 0x08, 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x51, 0x08,
+ 0x60, 0xd3, 0x2e, 0x05, 0x80, 0x49, 0xd7, 0x08, 0xa0, 0x09, 0x26, 0x05,
+ 0xf0, 0x2e, 0x05, 0x00, 0x80, 0x0b, 0x49, 0xd7, 0x20, 0xa0, 0x06, 0x41,
+ 0xd7, 0xdf, 0x80, 0xac, 0x51, 0x05, 0x21, 0x0e, 0xe0, 0x01, 0x80, 0x11,
+ 0x80, 0x6d, 0x80, 0x7f, 0x80, 0x4d, 0x80, 0x9c, 0x80, 0x9a, 0x80, 0x98,
+ 0x80, 0x96, 0x80, 0x9d, 0x5d, 0xd8, 0x21, 0xfe, 0x39, 0x40, 0xa0, 0x06,
+ 0x62, 0xd7, 0x00, 0x80, 0x90, 0x49, 0xd8, 0x01, 0xb0, 0x15, 0x55, 0x0c,
+ 0x02, 0x26, 0x07, 0x00, 0x26, 0x06, 0x00, 0x26, 0x05, 0xf0, 0x2e, 0x05,
+ 0x04, 0x62, 0xd7, 0x10, 0x80, 0x77, 0x55, 0x0c, 0x01, 0x26, 0x05, 0xf0,
+ 0x2e, 0x05, 0x06, 0x5f, 0x07, 0x06, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52,
+ 0x00, 0x60, 0xd8, 0x76, 0x07, 0x62, 0xd7, 0x14, 0x80, 0x5b, 0x51, 0x0a,
+ 0x78, 0x3a, 0x07, 0xc0, 0x0f, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00,
+ 0x60, 0xd8, 0x76, 0x07, 0x2e, 0x05, 0x20, 0x60, 0xd8, 0x62, 0xd7, 0x04,
+ 0x80, 0x3f, 0x5d, 0xd8, 0x3a, 0x0a, 0xd0, 0x2b, 0xa0, 0x29, 0x53, 0x07,
+ 0x53, 0x06, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x80, 0x18, 0x51, 0x0b,
+ 0x78, 0x3a, 0x07, 0xc0, 0x16, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x5d, 0xd8,
+ 0x54, 0x00, 0x2e, 0x05, 0x10, 0x76, 0x07, 0x80, 0x01, 0x62, 0xd7, 0x10,
+ 0x80, 0x0f, 0x62, 0xd7, 0x00, 0x80, 0x0a, 0x26, 0x05, 0xf0, 0x2e, 0x05,
+ 0x00, 0x55, 0x0c, 0x00, 0x18, 0x60, 0xd0, 0x18, 0x60, 0xd3, 0x20, 0x18,
+ 0x7e, 0x62, 0xc8, 0x00, 0x55, 0x0c, 0x00, 0x90, 0x0e, 0x90, 0x18, 0x7f,
+ 0x62, 0xd0, 0x00, 0x51, 0x05, 0x21, 0xb0, 0x26, 0x05, 0x4f, 0x7f, 0x08,
+ 0x5d, 0xe0, 0x21, 0x7f, 0x60, 0xe0, 0x43, 0xe0, 0x80, 0x18, 0x7f, 0x43,
+ 0xd6, 0x31, 0x7f, 0x62, 0xd0, 0x00, 0x4f, 0x52, 0xfd, 0x53, 0x0a, 0x52,
+ 0xfc, 0x53, 0x0b, 0x52, 0xfb, 0x53, 0x09, 0x52, 0xfa, 0x53, 0x08, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x02, 0x08, 0x02, 0x20, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x05, 0x08, 0x5d, 0xa4, 0x04, 0x1b, 0x5d, 0xa5, 0x0c,
+ 0x1a, 0x55, 0x1c, 0x01, 0x18, 0x7e, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70,
+ 0xbf, 0x53, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x5b, 0x62, 0xd3,
+ 0x00, 0x13, 0x4b, 0x62, 0xd3, 0x00, 0x54, 0x4f, 0x62, 0xd3, 0x00, 0x52,
+ 0x5a, 0x62, 0xd3, 0x00, 0x1b, 0x4a, 0x62, 0xd3, 0x00, 0x54, 0x4e, 0x48,
+ 0x4e, 0x80, 0xb0, 0x33, 0x3d, 0x4e, 0x00, 0xb0, 0x77, 0x51, 0x0d, 0x3b,
+ 0x4f, 0xc0, 0x71, 0x52, 0x4f, 0x58, 0x1e, 0x01, 0x00, 0x6d, 0x62, 0xd3,
+ 0x00, 0x05, 0x41, 0xc0, 0x09, 0x51, 0x0f, 0x3b, 0x41, 0xd0, 0x12, 0xa0,
+ 0x10, 0x56, 0x41, 0x00, 0x5b, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x07, 0x4b,
+ 0x01, 0x0f, 0x4a, 0x00, 0x80, 0x3d, 0x3d, 0x4e, 0xff, 0xb0, 0x09, 0x50,
+ 0xff, 0x12, 0x0e, 0x3b, 0x4f, 0xc0, 0x1c, 0x62, 0xd3, 0x00, 0x56, 0x4f,
+ 0x00, 0x56, 0x4e, 0x00, 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x48,
+ 0x78, 0x54, 0x48, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c, 0x62, 0xd3,
+ 0x00, 0x52, 0x5b, 0x62, 0xd3, 0x00, 0x54, 0x4b, 0x62, 0xd3, 0x00, 0x52,
+ 0x5a, 0x62, 0xd3, 0x00, 0x54, 0x4a, 0x51, 0x1e, 0x64, 0x5c, 0x62, 0xd3,
+ 0x00, 0x56, 0x4f, 0x00, 0x56, 0x4e, 0x00, 0x5b, 0x67, 0x5c, 0x62, 0xd3,
+ 0x00, 0x51, 0x12, 0x54, 0x48, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0xbf,
+ 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x08, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x43,
+ 0x53, 0x19, 0x55, 0x18, 0x00, 0x18, 0x08, 0x90, 0x7e, 0x62, 0xd3, 0x00,
+ 0x23, 0x45, 0xb0, 0x2c, 0x51, 0x10, 0x04, 0x19, 0x0e, 0x18, 0x00, 0x18,
+ 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x4f, 0x12, 0x19, 0x52, 0x4e, 0x1a,
+ 0x18, 0xc0, 0x39, 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x46, 0x78,
+ 0x54, 0x46, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x3e, 0x80, 0x18, 0x51,
+ 0x10, 0x14, 0x19, 0x1e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3, 0x00,
+ 0x52, 0x4f, 0x12, 0x19, 0x52, 0x4e, 0x1a, 0x18, 0xc0, 0x0e, 0x5b, 0x67,
+ 0x90, 0x31, 0x62, 0xd3, 0x00, 0x2d, 0x45, 0x50, 0x01, 0x80, 0x24, 0x5b,
+ 0x67, 0x08, 0x90, 0x23, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x45, 0x62, 0xd3,
+ 0x00, 0x20, 0x51, 0x11, 0x54, 0x46, 0x50, 0x00, 0x80, 0x0d, 0x5b, 0x67,
+ 0x90, 0x0d, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x45, 0x50, 0x00, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x08, 0x67, 0x67, 0x67, 0x5c, 0x18, 0x21, 0x07, 0xf0,
+ 0x01, 0x7f, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x70, 0xbf,
+ 0x70, 0xbf, 0x62, 0xd3, 0x00, 0x50, 0x02, 0x78, 0x08, 0x5c, 0x56, 0x43,
+ 0x28, 0x18, 0x78, 0xdf, 0xf8, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x91,
+ 0x7a, 0x70, 0xbf, 0x18, 0x08, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x5b,
+ 0x62, 0xd3, 0x00, 0x54, 0x4b, 0x62, 0xd3, 0x00, 0x52, 0x5a, 0x62, 0xd3,
+ 0x00, 0x54, 0x4a, 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x62, 0xd0, 0x00, 0x55, 0x14, 0x00, 0x50, 0x02, 0x78, 0x08, 0x9f, 0x0e,
+ 0x39, 0x01, 0xb0, 0x04, 0x55, 0x14, 0x01, 0x18, 0x78, 0xdf, 0xf3, 0x51,
+ 0x14, 0x7f, 0x50, 0x02, 0x78, 0x08, 0x9e, 0x42, 0x18, 0x78, 0xdf, 0xfa,
+ 0x7f, 0x98, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0xd8, 0xd9,
+ 0xda, 0xdb, 0xdf, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
+ 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x62, 0xd3, 0x00, 0x57, 0x00, 0x56, 0x45,
+ 0x00, 0x79, 0xdf, 0xfb, 0x62, 0xd3, 0x00, 0x50, 0x32, 0x57, 0x01, 0x54,
+ 0x48, 0x79, 0xdf, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x55, 0x0d, 0x1e, 0x55,
+ 0x0e, 0x05, 0x55, 0x0f, 0x32, 0x55, 0x10, 0x01, 0x55, 0x11, 0x01, 0x55,
+ 0x12, 0x32, 0x55, 0x22, 0x04, 0x55, 0x1f, 0x32, 0x43, 0x61, 0x0d, 0x57,
+ 0x00, 0x50, 0x02, 0x90, 0x82, 0x50, 0x04, 0xff, 0xa4, 0x29, 0x00, 0x60,
+ 0xa9, 0x62, 0xa0, 0x08, 0x43, 0xa2, 0x04, 0x62, 0xa3, 0x70, 0x43, 0x7a,
+ 0x01, 0x43, 0xdf, 0x01, 0x50, 0x01, 0x57, 0x0d, 0x90, 0x12, 0x90, 0x4d,
+ 0x7f, 0x53, 0x22, 0xff, 0x84, 0x29, 0x00, 0x60, 0xa9, 0x51, 0x21, 0x58,
+ 0x20, 0x90, 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21, 0x03, 0x53, 0x21, 0x64,
+ 0x64, 0x64, 0x64, 0x64, 0x29, 0x80, 0x60, 0xa1, 0x5b, 0x78, 0x21, 0x0f,
+ 0x29, 0x08, 0x74, 0x53, 0x20, 0x12, 0x22, 0x02, 0x21, 0x5c, 0x50, 0x00,
+ 0x53, 0x1d, 0x53, 0x23, 0x29, 0x01, 0x79, 0xa0, 0x08, 0x64, 0x6b, 0x1d,
+ 0x6b, 0x23, 0x8f, 0xf5, 0x60, 0xb5, 0x51, 0x1d, 0x60, 0xb4, 0x7f, 0x62,
+ 0xd0, 0x00, 0x53, 0x1f, 0x7f, 0x50, 0x02, 0x78, 0x08, 0x90, 0x07, 0x90,
+ 0x39, 0x18, 0x78, 0xdf, 0xf8, 0x7f, 0x64, 0x5c, 0xfd, 0x4e, 0x4b, 0x74,
+ 0xfd, 0x4a, 0x7f, 0x62, 0xd0, 0x00, 0x53, 0x1d, 0x10, 0x5b, 0x64, 0x64,
+ 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x2a, 0x1d, 0x61, 0x01, 0x36, 0x1d, 0xff,
+ 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x36, 0x1d, 0xff, 0x18, 0xff, 0x0e,
+ 0x5c, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef, 0x7f, 0x62, 0xd0,
+ 0x00, 0x10, 0x73, 0x53, 0x1d, 0x71, 0x10, 0x5b, 0xfe, 0xf8, 0x5c, 0x5e,
+ 0x00, 0x22, 0x1d, 0x61, 0x00, 0x70, 0xef, 0x18, 0x64, 0x64, 0x5c, 0x71,
+ 0x10, 0x5e, 0x01, 0x22, 0x1d, 0x61, 0x01, 0x36, 0x1d, 0xff, 0x5e, 0x00,
+ 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00,
+ 0x53, 0x1e, 0x50, 0x00, 0x53, 0x1a, 0x53, 0x1b, 0x43, 0xa0, 0x01, 0x51,
+ 0x1f, 0x60, 0xfd, 0x41, 0xa3, 0xdf, 0x51, 0x1e, 0x9f, 0x84, 0x9f, 0x8b,
+ 0x58, 0x23, 0x55, 0x1c, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x43,
+ 0xb3, 0x01, 0x51, 0x1c, 0xaf, 0xfd, 0x79, 0xdf, 0xee, 0x51, 0x1e, 0x9f,
+ 0x69, 0x9f, 0x9b, 0x43, 0xa3, 0x20, 0x41, 0xa0, 0xfe, 0x62, 0xfd, 0x00,
+ 0x50, 0xff, 0x4c, 0x1b, 0x14, 0x1b, 0x51, 0x20, 0x11, 0x08, 0xfe, 0x8f,
+ 0x4c, 0x1a, 0x1c, 0x1a, 0xd0, 0x07, 0x55, 0x1a, 0x00, 0x55, 0x1b, 0x00,
+ 0x51, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x1b, 0x54, 0x5b, 0x51,
+ 0x1a, 0x54, 0x5a, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x9f, 0x90, 0x18,
+ 0x78, 0xdf, 0xfa, 0x7f, 0x10, 0x7c, 0x04, 0x50, 0x7c, 0x04, 0x2d, 0x20,
+ 0x7c, 0x0e, 0xdd, 0x62, 0xe3, 0x38, 0x10, 0x7c, 0x02, 0xec, 0x20, 0x43,
+ 0x00, 0x08, 0x62, 0xd0, 0x00, 0x55, 0x24, 0x08, 0x55, 0x25, 0x04, 0x55,
+ 0x26, 0x03, 0x55, 0x28, 0x55, 0x55, 0x29, 0x02, 0x10, 0x50, 0x00, 0x08,
+ 0x50, 0x24, 0x08, 0x50, 0x05, 0x08, 0x50, 0x12, 0x08, 0x7c, 0x05, 0x7f,
+ 0x38, 0xfc, 0x7c, 0x05, 0x59, 0x7c, 0x05, 0x6f, 0x20, 0x71, 0x01, 0x10,
+ 0x7c, 0x07, 0x8c, 0x7c, 0x07, 0x12, 0x20, 0x90, 0xea, 0x80, 0xe5, 0x7c,
+ 0x10, 0x2e, 0x62, 0xe3, 0x38, 0x92, 0x61, 0x62, 0xd0, 0x00, 0x3c, 0x6f,
+ 0x01, 0xb0, 0x09, 0x50, 0x00, 0x08, 0x7c, 0x11, 0xae, 0x38, 0xff, 0x62,
+ 0xe3, 0x38, 0x10, 0x7c, 0x07, 0x50, 0x20, 0x39, 0x00, 0xa0, 0x86, 0x62,
+ 0xd0, 0x00, 0x51, 0x63, 0x11, 0x94, 0x51, 0x62, 0x19, 0x02, 0xd0, 0x12,
+ 0x7c, 0x0e, 0xef, 0x39, 0xe1, 0xa0, 0x10, 0x62, 0xd0, 0x00, 0x76, 0x63,
+ 0x0e, 0x62, 0x00, 0x80, 0x06, 0x7c, 0x13, 0x92, 0x90, 0xa1, 0x62, 0xd0,
+ 0x00, 0x3c, 0x72, 0xf0, 0xd0, 0x06, 0x62, 0xd0, 0x00, 0x76, 0x72, 0x62,
+ 0xd0, 0x00, 0x51, 0x72, 0x62, 0xd0, 0x00, 0x3a, 0x29, 0xb0, 0x82, 0x7c,
+ 0x0e, 0xef, 0x62, 0xd0, 0x00, 0x53, 0x73, 0x3c, 0x73, 0xe1, 0xa0, 0x35,
+ 0x62, 0xd0, 0x00, 0x55, 0x67, 0x00, 0x55, 0x66, 0x00, 0x62, 0xd0, 0x00,
+ 0x51, 0x73, 0x62, 0xd0, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x06, 0x3f,
+ 0x66, 0x7c, 0x13, 0x05, 0x50, 0x08, 0x3f, 0x3f, 0x7c, 0x13, 0xb3, 0x7c,
+ 0x0f, 0x2a, 0x62, 0xd0, 0x00, 0x55, 0x71, 0x01, 0x62, 0xd0, 0x00, 0x55,
+ 0x6e, 0x03, 0x80, 0x41, 0x62, 0xd0, 0x00, 0x55, 0x72, 0x00, 0x80, 0x39,
+ 0x7c, 0x13, 0x92, 0x7c, 0x13, 0xa3, 0xb0, 0x31, 0x62, 0xd0, 0x00, 0x7a,
+ 0x6e, 0x3c, 0x6e, 0x00, 0xb0, 0x27, 0x7c, 0x0f, 0xb2, 0x62, 0xd0, 0x00,
+ 0x55, 0x71, 0x00, 0x62, 0xd0, 0x00, 0x51, 0x73, 0x62, 0xd0, 0x00, 0x53,
+ 0x3f, 0x55, 0x40, 0x00, 0x06, 0x3f, 0x66, 0x7c, 0x13, 0x05, 0x50, 0x00,
+ 0x3f, 0x3f, 0x62, 0xd0, 0x00, 0x55, 0x72, 0x00, 0x7c, 0x10, 0x9b, 0x8f,
+ 0x1b, 0x8f, 0xff, 0x10, 0x4f, 0x38, 0x16, 0x10, 0x62, 0xd0, 0x00, 0x51,
+ 0x68, 0x7c, 0x08, 0x33, 0x20, 0x10, 0x50, 0x00, 0x7c, 0x08, 0xa7, 0x20,
+ 0x56, 0x0d, 0x00, 0x80, 0x86, 0x56, 0x00, 0x00, 0x80, 0x7a, 0x7c, 0x12,
+ 0xdb, 0x06, 0x3f, 0x68, 0x7c, 0x12, 0xf4, 0x10, 0x7c, 0x08, 0x33, 0x20,
+ 0x10, 0x52, 0x00, 0x7c, 0x08, 0xa7, 0x20, 0x10, 0x7c, 0x05, 0x64, 0x62,
+ 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x55, 0x40, 0x03, 0x5a, 0x3f,
+ 0x06, 0x3f, 0x01, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00, 0x08, 0x51, 0x3d,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x12, 0x8e, 0x38, 0xfc,
+ 0x7c, 0x13, 0x0d, 0x53, 0x40, 0x52, 0x0d, 0x7c, 0x13, 0x47, 0x51, 0x3d,
+ 0x02, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x53, 0x40, 0x52, 0x00,
+ 0x7c, 0x13, 0x47, 0x06, 0x3d, 0x5a, 0x0e, 0x3e, 0x00, 0x51, 0x3e, 0x60,
+ 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x51, 0x40, 0x60,
+ 0xd5, 0x51, 0x3e, 0x3f, 0x3f, 0x51, 0x3d, 0x3f, 0x3f, 0x77, 0x00, 0x3d,
+ 0x00, 0x02, 0xcf, 0x83, 0x77, 0x0d, 0x3d, 0x0d, 0x03, 0xcf, 0x77, 0x56,
+ 0x00, 0x00, 0x80, 0xd0, 0x62, 0xd0, 0x00, 0x55, 0x40, 0x03, 0x5a, 0x3f,
+ 0x06, 0x3f, 0x01, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00, 0x08, 0x51, 0x3d,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x12, 0x8e, 0x38, 0xfc,
+ 0x97, 0xef, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x54, 0x0e, 0x3e, 0x3f, 0x54,
+ 0x0f, 0x5a, 0x3f, 0x06, 0x3f, 0x03, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00,
+ 0x08, 0x51, 0x3d, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x12,
+ 0x8e, 0x38, 0xfc, 0x97, 0xc8, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x54, 0x10,
+ 0x3e, 0x3f, 0x54, 0x11, 0x5a, 0x3f, 0x06, 0x3f, 0x05, 0x52, 0x00, 0x53,
+ 0x3d, 0x50, 0x00, 0x08, 0x51, 0x3d, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06,
+ 0x08, 0x7c, 0x12, 0x8e, 0x38, 0xfc, 0x97, 0xa1, 0x40, 0x60, 0xd4, 0x3e,
+ 0x3f, 0x54, 0x12, 0x3e, 0x3f, 0x54, 0x13, 0x50, 0x03, 0x08, 0x5a, 0x3f,
+ 0x06, 0x3f, 0x0e, 0x08, 0x51, 0x3f, 0x08, 0x7c, 0x10, 0xe0, 0x38, 0xfd,
+ 0x62, 0xd0, 0x00, 0x51, 0x3f, 0x54, 0x15, 0x51, 0x40, 0x54, 0x14, 0x97,
+ 0x3a, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x97, 0x62, 0x40, 0x97, 0x9d, 0x40,
+ 0x06, 0x3f, 0x4a, 0x97, 0x60, 0x40, 0x7c, 0x13, 0xaa, 0x97, 0x24, 0x40,
+ 0x51, 0x3f, 0x01, 0x52, 0x97, 0x4c, 0x40, 0x97, 0x87, 0x40, 0x51, 0x3f,
+ 0x01, 0x56, 0x97, 0x42, 0x40, 0x97, 0x7d, 0x40, 0x06, 0x3f, 0x5e, 0x97,
+ 0x40, 0x40, 0x97, 0xe2, 0x40, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x2d,
+ 0x38, 0xea, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x06, 0x62, 0xd0, 0x00, 0x55,
+ 0x70, 0x00, 0x10, 0x62, 0xd0, 0x00, 0x51, 0x68, 0x7c, 0x08, 0x33, 0x20,
+ 0x10, 0x50, 0x00, 0x7c, 0x08, 0xa7, 0x20, 0x56, 0x00, 0x00, 0x80, 0x24,
+ 0x96, 0xe5, 0x40, 0x06, 0x3f, 0x68, 0x96, 0xf8, 0x40, 0x10, 0x7c, 0x08,
+ 0x33, 0x20, 0x10, 0x52, 0x00, 0x7c, 0x08, 0xa7, 0x20, 0x10, 0x7c, 0x05,
+ 0x64, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x77, 0x00, 0x3d,
+ 0x00, 0x02, 0xcf, 0xd9, 0x56, 0x00, 0x00, 0x81, 0xcf, 0x97, 0x79, 0x40,
+ 0xa0, 0xb6, 0x62, 0xd0, 0x00, 0x96, 0xa4, 0x40, 0x51, 0x3f, 0x01, 0x4a,
+ 0x96, 0x8c, 0x40, 0x06, 0x3f, 0x5a, 0x96, 0xae, 0x40, 0x53, 0x3f, 0x51,
+ 0x3d, 0x12, 0x3f, 0x51, 0x3e, 0x1a, 0x40, 0xd0, 0x19, 0x62, 0xd0, 0x00,
+ 0x96, 0x85, 0x40, 0x51, 0x3f, 0x01, 0x4a, 0x96, 0x6d, 0x40, 0x06, 0x3f,
+ 0x5a, 0x96, 0x8f, 0x40, 0x97, 0x22, 0x40, 0x80, 0x17, 0x62, 0xd0, 0x00,
+ 0x96, 0x6d, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x96, 0x55, 0x40, 0x06, 0x3f,
+ 0x4a, 0x96, 0x77, 0x40, 0x97, 0x0a, 0x40, 0x50, 0x90, 0x13, 0x03, 0x50,
+ 0x01, 0x1b, 0x02, 0xc0, 0x58, 0x62, 0xd0, 0x00, 0x96, 0x4d, 0x40, 0x51,
+ 0x3f, 0x01, 0x5e, 0x96, 0x35, 0x40, 0x06, 0x3f, 0x5a, 0x96, 0x57, 0x40,
+ 0x53, 0x3f, 0x51, 0x3d, 0x12, 0x3f, 0x51, 0x3e, 0x1a, 0x40, 0xd0, 0x19,
+ 0x62, 0xd0, 0x00, 0x96, 0x2e, 0x40, 0x51, 0x3f, 0x01, 0x5e, 0x96, 0x16,
+ 0x40, 0x06, 0x3f, 0x5a, 0x96, 0x38, 0x40, 0x96, 0xc0, 0x40, 0x80, 0x17,
+ 0x62, 0xd0, 0x00, 0x96, 0x16, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x95, 0xfe,
+ 0x40, 0x06, 0x3f, 0x5e, 0x96, 0x20, 0x40, 0x96, 0xa8, 0x40, 0x50, 0x90,
+ 0x13, 0x05, 0x50, 0x01, 0x1b, 0x04, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x76,
+ 0x70, 0x81, 0x13, 0x62, 0xd0, 0x00, 0x95, 0xef, 0x40, 0x51, 0x3f, 0x01,
+ 0x56, 0x95, 0xd7, 0x40, 0x06, 0x3f, 0x52, 0x96, 0x18, 0x40, 0x96, 0x30,
+ 0x40, 0x95, 0xdc, 0x40, 0x51, 0x3f, 0x01, 0x5e, 0x95, 0xc4, 0x40, 0x06,
+ 0x3f, 0x56, 0x96, 0x05, 0x40, 0x96, 0x1d, 0x40, 0x95, 0xc9, 0x40, 0x51,
+ 0x3f, 0x01, 0x5a, 0x95, 0xb1, 0x40, 0x06, 0x3f, 0x5e, 0x95, 0xf2, 0x40,
+ 0x96, 0x0a, 0x40, 0x95, 0xb6, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x95, 0xde,
+ 0x40, 0x53, 0x3e, 0x96, 0x40, 0x40, 0x53, 0x3b, 0x08, 0x51, 0x3c, 0x53,
+ 0x3a, 0x18, 0x53, 0x39, 0x65, 0x39, 0x6b, 0x3a, 0x06, 0x3f, 0x56, 0x95,
+ 0xad, 0x40, 0x53, 0x3f, 0x51, 0x39, 0x04, 0x3f, 0x51, 0x3a, 0x0c, 0x40,
+ 0x51, 0x3b, 0x04, 0x3f, 0x51, 0x3c, 0x0c, 0x40, 0x70, 0xfb, 0x6e, 0x40,
+ 0x6e, 0x3f, 0x95, 0xd5, 0x40, 0x10, 0x52, 0x00, 0x7c, 0x05, 0xb2, 0x20,
+ 0x62, 0xd0, 0x00, 0x95, 0x6e, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x95, 0x56,
+ 0x40, 0x06, 0x3f, 0x4a, 0x95, 0x78, 0x40, 0x53, 0x3f, 0x51, 0x3d, 0x12,
+ 0x3f, 0x51, 0x3e, 0x1a, 0x40, 0xd0, 0x1b, 0x95, 0x5e, 0x40, 0x06, 0x3f,
+ 0x6c, 0x95, 0x71, 0x40, 0x7a, 0x3f, 0x53, 0x3e, 0x06, 0x3e, 0x01, 0x51,
+ 0x40, 0x60, 0xd5, 0x51, 0x3e, 0x3f, 0x3f, 0x80, 0x0e, 0x95, 0x44, 0x40,
+ 0x06, 0x3f, 0x6c, 0x95, 0x68, 0x40, 0x50, 0x00, 0x3f, 0x3f, 0x95, 0x37,
+ 0x40, 0x06, 0x3f, 0x6c, 0x95, 0x4a, 0x40, 0x53, 0x40, 0x50, 0x05, 0x3a,
+ 0x40, 0xd0, 0x3b, 0x62, 0xd0, 0x00, 0x95, 0x17, 0x40, 0x51, 0x3f, 0x01,
+ 0x4a, 0x95, 0x3f, 0x40, 0x53, 0x3e, 0x06, 0x3f, 0x5a, 0x95, 0x1f, 0x40,
+ 0x53, 0x3f, 0x51, 0x3e, 0x95, 0x97, 0x40, 0x02, 0x3f, 0x53, 0x3f, 0x51,
+ 0x3c, 0x0a, 0x40, 0x53, 0x40, 0x95, 0x4e, 0x40, 0x52, 0x00, 0x53, 0x3f,
+ 0x55, 0x40, 0x00, 0x06, 0x3f, 0x6c, 0x95, 0x1d, 0x40, 0x50, 0x00, 0x3f,
+ 0x3f, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0x2e, 0x95, 0xa6, 0x40, 0xb0,
+ 0x9b, 0x56, 0x00, 0x00, 0x80, 0x91, 0x62, 0xd0, 0x00, 0x94, 0xcc, 0x40,
+ 0x51, 0x3f, 0x01, 0x5a, 0x94, 0xb4, 0x40, 0x06, 0x3f, 0x2e, 0x94, 0xf5,
+ 0x40, 0x95, 0x0d, 0x40, 0x94, 0xb9, 0x40, 0x51, 0x3f, 0x01, 0x4a, 0x94,
+ 0xa1, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x53, 0x3b, 0x51, 0x40, 0x95, 0x29,
+ 0x40, 0x51, 0x3d, 0x12, 0x3b, 0x51, 0x3e, 0x1a, 0x3c, 0xd0, 0x30, 0x62,
+ 0xd0, 0x00, 0x52, 0x00, 0x95, 0x0d, 0x40, 0x51, 0x3d, 0x01, 0x4a, 0x53,
+ 0x3b, 0x51, 0x3e, 0x95, 0x0c, 0x40, 0x06, 0x3d, 0x5a, 0x0e, 0x3e, 0x00,
+ 0x51, 0x3e, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x12, 0x3b,
+ 0x54, 0x03, 0x51, 0x3e, 0x1a, 0x3c, 0x54, 0x02, 0x80, 0x07, 0x56, 0x03,
+ 0x00, 0x56, 0x02, 0x00, 0x62, 0xd0, 0x00, 0x06, 0x3f, 0x2a, 0x94, 0x95,
+ 0x40, 0x52, 0x02, 0x3f, 0x3f, 0x52, 0x03, 0x3f, 0x3f, 0x94, 0x54, 0x40,
+ 0x51, 0x3f, 0x01, 0x4a, 0x94, 0x3c, 0x40, 0x06, 0x3f, 0x32, 0x94, 0x7d,
+ 0x40, 0x94, 0x95, 0x40, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x6c, 0x95,
+ 0x07, 0x40, 0xa0, 0x1a, 0x62, 0xd0, 0x00, 0x3c, 0x70, 0x00, 0xa0, 0x12,
+ 0x50, 0x75, 0x08, 0x50, 0x30, 0x08, 0x90, 0x0d, 0x38, 0xfe, 0x9b, 0xa7,
+ 0x10, 0x7c, 0x07, 0x6a, 0x20, 0x38, 0xfa, 0x20, 0x7f, 0x10, 0x4f, 0x80,
+ 0x02, 0x40, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53, 0x3f, 0x52, 0xfb, 0x53,
+ 0x40, 0x51, 0x3f, 0x11, 0x01, 0x54, 0xfc, 0x51, 0x40, 0x19, 0x00, 0x54,
+ 0xfb, 0x3c, 0x40, 0x00, 0xbf, 0xe4, 0x3c, 0x3f, 0x00, 0xbf, 0xdf, 0x20,
+ 0x7f, 0x10, 0x7c, 0x04, 0x50, 0x7c, 0x04, 0x2d, 0x20, 0x7f, 0x10, 0x7c,
+ 0x04, 0x4c, 0x7c, 0x04, 0x29, 0x20, 0x7f, 0x62, 0xd0, 0x00, 0x50, 0x28,
+ 0x12, 0x4f, 0x50, 0x00, 0x1a, 0x4e, 0xd0, 0x15, 0x62, 0xd0, 0x00, 0x50,
+ 0x28, 0x12, 0x51, 0x50, 0x00, 0x1a, 0x50, 0xd0, 0x08, 0x62, 0xd0, 0x00,
+ 0x50, 0xe1, 0x80, 0x1a, 0x62, 0xd0, 0x00, 0x51, 0x51, 0x12, 0x4f, 0x51,
+ 0x50, 0x1a, 0x4e, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50, 0x00, 0x80, 0x06,
+ 0x62, 0xd0, 0x00, 0x50, 0x01, 0x7f, 0x10, 0x4f, 0x38, 0x01, 0x70, 0xfe,
+ 0x62, 0xd0, 0x00, 0x51, 0x73, 0x01, 0x01, 0x62, 0xd0, 0x00, 0x53, 0x24,
+ 0x71, 0x01, 0x62, 0xd0, 0x00, 0x3c, 0x71, 0x00, 0xb0, 0x69, 0x62, 0xe3,
+ 0x38, 0x10, 0x7c, 0x05, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7,
+ 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x05, 0x64, 0x62, 0xd0, 0x00,
+ 0x20, 0x53, 0x40, 0x47, 0x40, 0x20, 0xa0, 0x03, 0x80, 0x12, 0x50, 0x00,
+ 0x08, 0x50, 0x14, 0x08, 0x9f, 0x43, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00,
+ 0xc8, 0xcf, 0xdf, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x05, 0x64,
+ 0x62, 0xd0, 0x00, 0x20, 0x53, 0x40, 0x47, 0x40, 0x20, 0xb0, 0x03, 0x80,
+ 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9f, 0x1c, 0x38, 0xfe, 0x77,
+ 0x00, 0x3d, 0x00, 0x1e, 0xcf, 0xdf, 0x62, 0xd0, 0x00, 0x51, 0x24, 0x29,
+ 0x08, 0x53, 0x24, 0x43, 0x00, 0x08, 0x38, 0xff, 0x20, 0x7f, 0x10, 0x4f,
+ 0x38, 0x01, 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x51, 0x73, 0x01, 0x09, 0x62,
+ 0xd0, 0x00, 0x53, 0x24, 0x71, 0x01, 0x93, 0xdb, 0x40, 0xb0, 0x60, 0x62,
+ 0xe3, 0x38, 0x10, 0x7c, 0x05, 0x64, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00,
+ 0xf7, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x05, 0x64, 0x62, 0xd0,
+ 0x00, 0x20, 0x53, 0x40, 0x47, 0x40, 0x20, 0xa0, 0x03, 0x80, 0x12, 0x50,
+ 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0xbe, 0x38, 0xfe, 0x77, 0x00, 0x3d,
+ 0x00, 0xc8, 0xcf, 0xdf, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x05,
+ 0x64, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x40, 0x47, 0x40, 0x20, 0xb0, 0x03,
+ 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0x97, 0x38, 0xfe,
+ 0x77, 0x00, 0x3d, 0x00, 0x1e, 0xcf, 0xdf, 0x43, 0x00, 0x08, 0x38, 0xff,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x01, 0x62, 0xd0, 0x00, 0x51, 0x24, 0x54,
+ 0x00, 0x3d, 0x00, 0x01, 0xb0, 0x17, 0x93, 0x73, 0x40, 0x93, 0x60, 0x40,
+ 0xa0, 0x0a, 0x62, 0xd0, 0x00, 0x55, 0x67, 0x00, 0x55, 0x66, 0x00, 0x93,
+ 0x0d, 0x40, 0x80, 0x44, 0x3d, 0x00, 0x02, 0xb0, 0x1b, 0x62, 0xd0, 0x00,
+ 0x55, 0x75, 0x01, 0x62, 0xd0, 0x00, 0x55, 0x74, 0x00, 0x62, 0xd0, 0x00,
+ 0x55, 0x67, 0x08, 0x55, 0x66, 0x08, 0x92, 0xee, 0x40, 0x80, 0x25, 0x52,
+ 0x00, 0x21, 0xf0, 0x39, 0x40, 0xb0, 0x0c, 0x62, 0xd0, 0x00, 0x55, 0x6f,
+ 0x02, 0x92, 0xdb, 0x40, 0x80, 0x12, 0x52, 0x00, 0x21, 0xf0, 0x39, 0x50,
+ 0xb0, 0x0a, 0x62, 0xd0, 0x00, 0x55, 0x6f, 0x01, 0x92, 0xc8, 0x40, 0x38,
+ 0xff, 0x20, 0x7f, 0x62, 0xd0, 0x00, 0x3c, 0x75, 0x00, 0xa0, 0x13, 0x9e,
+ 0x38, 0x62, 0xd0, 0x00, 0x3c, 0x74, 0x00, 0xb0, 0x33, 0x55, 0x74, 0x01,
+ 0x7c, 0x0a, 0x53, 0x80, 0x2b, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x66,
+ 0xd0, 0x08, 0x10, 0x7c, 0x04, 0x50, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04,
+ 0x4c, 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x67, 0xd0, 0x08, 0x10,
+ 0x7c, 0x04, 0x2d, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0x29, 0x20, 0x7f,
+ 0x10, 0x4f, 0x38, 0x03, 0x56, 0x02, 0x00, 0x56, 0x01, 0x00, 0x56, 0x00,
+ 0x00, 0x80, 0x41, 0x62, 0xd0, 0x00, 0x91, 0xdb, 0x40, 0x52, 0xfc, 0x04,
+ 0x3f, 0x52, 0xfb, 0x0c, 0x40, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53,
+ 0x40, 0x3e, 0x3f, 0x53, 0x3f, 0x52, 0x02, 0x12, 0x3f, 0x52, 0x01, 0x1a,
+ 0x40, 0xd0, 0x1b, 0x62, 0xd0, 0x00, 0x91, 0xb7, 0x40, 0x52, 0xfc, 0x04,
+ 0x3f, 0x52, 0xfb, 0x0c, 0x40, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x54,
+ 0x01, 0x3e, 0x3f, 0x54, 0x02, 0x77, 0x00, 0x52, 0x00, 0x3b, 0xfa, 0xcf,
+ 0xbb, 0x62, 0xd0, 0x00, 0x52, 0x02, 0x53, 0x3f, 0x52, 0x01, 0x53, 0x40,
+ 0x38, 0xfd, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x71, 0x10, 0x41, 0x01,
+ 0xf7, 0x43, 0x00, 0x08, 0x70, 0xcf, 0x43, 0x00, 0x08, 0x50, 0x00, 0x08,
+ 0x50, 0x64, 0x08, 0x9d, 0x58, 0x71, 0x10, 0x41, 0x01, 0xf7, 0x41, 0x00,
+ 0xf7, 0x70, 0xcf, 0x43, 0x00, 0x08, 0x50, 0x00, 0x08, 0x50, 0x64, 0x08,
+ 0x9d, 0x43, 0x38, 0xfc, 0x5d, 0x00, 0x62, 0xd0, 0x00, 0x53, 0x40, 0x26,
+ 0x40, 0x08, 0x3c, 0x40, 0x08, 0xb0, 0x09, 0x56, 0x01, 0x00, 0x56, 0x00,
+ 0x00, 0x80, 0x07, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x52, 0x01, 0x62,
+ 0xd0, 0x00, 0x53, 0x6f, 0x71, 0x10, 0x43, 0x00, 0x08, 0x41, 0x01, 0xf7,
+ 0x70, 0xcf, 0x3c, 0x6f, 0x00, 0xb0, 0x04, 0x43, 0x00, 0x08, 0x38, 0xfe,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x01, 0x62, 0xe3, 0x38, 0x10, 0x50, 0x02,
+ 0x7c, 0x02, 0xfe, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x02, 0xfe, 0x20, 0x10,
+ 0x50, 0xff, 0x7c, 0x02, 0xfe, 0x20, 0x10, 0x50, 0x04, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x5a, 0x08, 0x7c, 0x03, 0xe3, 0x38, 0xfd, 0x20, 0x56, 0x00,
+ 0x00, 0x80, 0x6f, 0x62, 0xd0, 0x00, 0x90, 0xeb, 0x40, 0x51, 0x3f, 0x01,
+ 0x4a, 0x90, 0xd3, 0x40, 0x06, 0x3f, 0x5a, 0x90, 0xf5, 0x40, 0x53, 0x3f,
+ 0x51, 0x3d, 0x12, 0x3f, 0x51, 0x3e, 0x1a, 0x40, 0xd0, 0x40, 0x62, 0xd0,
+ 0x00, 0x90, 0xcc, 0x40, 0x51, 0x3f, 0x01, 0x4a, 0x90, 0xb4, 0x40, 0x06,
+ 0x3f, 0x5a, 0x90, 0xd6, 0x40, 0x91, 0x74, 0x40, 0x51, 0x40, 0x10, 0x7c,
+ 0x02, 0xfe, 0x20, 0x62, 0xd0, 0x00, 0x90, 0xaf, 0x40, 0x51, 0x3f, 0x01,
+ 0x4a, 0x90, 0x97, 0x40, 0x06, 0x3f, 0x5a, 0x90, 0xb9, 0x40, 0x91, 0x57,
+ 0x40, 0x26, 0x40, 0x00, 0x51, 0x3f, 0x10, 0x7c, 0x02, 0xfe, 0x20, 0x80,
+ 0x0f, 0x10, 0x50, 0x00, 0x7c, 0x02, 0xfe, 0x20, 0x10, 0x50, 0x00, 0x7c,
+ 0x02, 0xfe, 0x20, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x8e, 0x10, 0x50,
+ 0x00, 0x7c, 0x02, 0xfe, 0x20, 0x10, 0x50, 0x01, 0x7c, 0x02, 0xfe, 0x20,
+ 0x10, 0x50, 0x00, 0x7c, 0x02, 0xfe, 0x20, 0x10, 0x50, 0x01, 0x7c, 0x02,
+ 0xfe, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x02, 0xfe, 0x20, 0x10, 0x50, 0xff,
+ 0x7c, 0x02, 0xfe, 0x7c, 0x03, 0xda, 0x20, 0x50, 0x13, 0x08, 0x50, 0x88,
+ 0x08, 0x9c, 0x2e, 0x38, 0xfe, 0x38, 0xff, 0x20, 0x7f, 0x7f, 0x10, 0x4f,
+ 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50, 0x00, 0x53, 0x38, 0x53, 0x37,
+ 0x55, 0x36, 0x10, 0x6f, 0xf9, 0x6f, 0xfa, 0xd0, 0x09, 0x52, 0xfc, 0x04,
+ 0x38, 0x52, 0xfb, 0x0c, 0x37, 0x66, 0xfc, 0x6c, 0xfb, 0x7a, 0x36, 0xbf,
+ 0xeb, 0x18, 0x60, 0xd0, 0x20, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x53, 0x3d,
+ 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d,
+ 0x53, 0x3d, 0x7f, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f,
+ 0x6b, 0x40, 0x7f, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40,
+ 0x00, 0x7f, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53,
+ 0x40, 0x3e, 0x3f, 0x7f, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e,
+ 0x3f, 0x7f, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x7f, 0x0e, 0x40, 0x00,
+ 0x51, 0x40, 0x60, 0xd5, 0x7f, 0x51, 0x38, 0x53, 0x3d, 0x51, 0x37, 0x53,
+ 0x3e, 0x51, 0x3d, 0x02, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x7f,
+ 0x51, 0x3e, 0x3f, 0x3f, 0x51, 0x3d, 0x3f, 0x3f, 0x7f, 0x70, 0xfb, 0x6e,
+ 0x40, 0x6e, 0x3f, 0x51, 0x3e, 0x60, 0xd5, 0x51, 0x40, 0x3f, 0x3d, 0x51,
+ 0x3f, 0x3f, 0x3d, 0x7f, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x3d, 0x52, 0x15,
+ 0x3f, 0x3d, 0x7f, 0x53, 0x3d, 0x55, 0x3e, 0x00, 0x65, 0x3d, 0x6b, 0x3e,
+ 0x7f, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3b, 0x53, 0x3c, 0x3e, 0x3b, 0x53,
+ 0x3b, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x24, 0x00, 0x7f, 0x60, 0xd4, 0x3e,
+ 0x3d, 0x53, 0x3c, 0x3e, 0x3d, 0x16, 0x3d, 0x02, 0x7f, 0x12, 0x3d, 0x54,
+ 0x05, 0x51, 0x40, 0x1a, 0x3e, 0x54, 0x04, 0x7f, 0x12, 0x3d, 0x54, 0x03,
+ 0x51, 0x40, 0x1a, 0x3e, 0x54, 0x02, 0x7f, 0x53, 0x3f, 0x51, 0x3d, 0x14,
+ 0x3f, 0x51, 0x3e, 0x1c, 0x40, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x63, 0x00,
+ 0x55, 0x62, 0x00, 0x7f, 0x62, 0xd0, 0x00, 0x3c, 0x6f, 0x02, 0x7f, 0x62,
+ 0xd0, 0x00, 0x3c, 0x71, 0x01, 0x7f, 0x52, 0x14, 0x3f, 0x3f, 0x52, 0x15,
+ 0x3f, 0x3f, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x75, 0x00, 0x7f, 0x00, 0x24,
+ 0x00, 0x12, 0x00, 0x52, 0x00, 0x08, 0x00, 0x5e, 0x00, 0x07, 0x00, 0x65,
+ 0x05, 0x01, 0x08, 0x08, 0x64, 0x5a, 0x00, 0x6a, 0x00, 0x04, 0x00, 0x6e,
+ 0x01, 0x03, 0x00, 0x6f, 0x00, 0x05, 0x00, 0x74, 0x02, 0x01, 0x01, 0xff,
+ 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_Q1.h b/drivers/input/keyboard/cypressbln/touchkey_fw_Q1.h
new file mode 100644
index 0000000..3c882b8
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_Q1.h
@@ -0,0 +1,747 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x00, 0x68,
+ 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x03, 0x64, 0x7e, 0x7e, 0x30,
+ 0x30, 0x30, 0x7d, 0x04, 0xb7, 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30,
+ 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x40, 0x71, 0x10, 0x62, 0xe3, 0x06, 0x70,
+ 0xef, 0x62, 0xe3, 0x38, 0x50, 0x80, 0x4e, 0x62, 0xe3, 0x38, 0x5d,
+ 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55, 0xfa, 0x01, 0x40, 0x4f, 0x5b,
+ 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a, 0x50, 0x06, 0x00, 0x40,
+ 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8, 0x70, 0xef, 0x18, 0x60,
+ 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00, 0x71, 0x10, 0x62, 0xe0,
+ 0x1a, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x71, 0x10, 0x41, 0xe1, 0xfe,
+ 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1, 0x03, 0x50, 0x80, 0x4e,
+ 0x62, 0xd3, 0x03, 0x62, 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4,
+ 0x00, 0x71, 0xc0, 0x7c, 0x02, 0xb3, 0x62, 0xd0, 0x00, 0x50, 0x02,
+ 0x57, 0x5c, 0x08, 0x28, 0x53, 0x48, 0x18, 0x75, 0x09, 0x00, 0x28,
+ 0x4b, 0x51, 0x48, 0x80, 0x04, 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00,
+ 0x08, 0x28, 0x60, 0xd5, 0x74, 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00,
+ 0x08, 0x28, 0x53, 0x48, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xa0,
+ 0x1c, 0x53, 0x47, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x3f, 0x48,
+ 0x47, 0x48, 0xff, 0xb0, 0x06, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x18,
+ 0x7a, 0x47, 0xbf, 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09, 0x00, 0x08,
+ 0x28, 0x53, 0x47, 0x50, 0x00, 0x3f, 0x48, 0x47, 0x48, 0xff, 0xb0,
+ 0x08, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x47, 0xbf,
+ 0xef, 0x18, 0x8f, 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71,
+ 0x10, 0x62, 0xe0, 0x1a, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x17,
+ 0x9a, 0x8f, 0xff, 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x01, 0x80, 0x03, 0x00, 0x06,
+ 0x00, 0x0b, 0xff, 0x1b, 0x33, 0x2f, 0xff, 0x5f, 0xff, 0xbf, 0xff,
+ 0x01, 0x66, 0x02, 0xcc, 0x05, 0x99, 0x0b, 0x32, 0x16, 0x66, 0x2c,
+ 0xcc, 0x59, 0x98, 0xb3, 0x32, 0x01, 0x4c, 0x02, 0x99, 0x05, 0x33,
+ 0x0a, 0x65, 0x14, 0xcc, 0x29, 0x98, 0x53, 0x32, 0xa6, 0x65, 0x01,
+ 0x33, 0x02, 0x66, 0x04, 0xcc, 0x09, 0x99, 0x13, 0x33, 0x26, 0x65,
+ 0x4c, 0xcc, 0x99, 0x99, 0x61, 0x00, 0xfd, 0x00, 0xcd, 0x00, 0xce,
+ 0x00, 0xa5, 0x00, 0xa4, 0x00, 0xa0, 0x00, 0xa1, 0x80, 0xa2, 0xc0,
+ 0xa3, 0x0c, 0xa8, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0x7c, 0x33, 0x7a,
+ 0x00, 0x7b, 0x00, 0x79, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00,
+ 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e,
+ 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00,
+ 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49,
+ 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00,
+ 0x4f, 0x00, 0xca, 0x20, 0xd6, 0x44, 0xcf, 0x00, 0xcb, 0x00, 0xc8,
+ 0x00, 0xcc, 0x00, 0xc9, 0x00, 0xd7, 0x00, 0xa9, 0x00, 0x2b, 0x00,
+ 0xb0, 0x00, 0xb3, 0x02, 0xb6, 0x00, 0xb2, 0x00, 0xb5, 0x00, 0xb8,
+ 0x00, 0xb1, 0x00, 0xb4, 0x00, 0xb7, 0x00, 0x33, 0x00, 0x34, 0x00,
+ 0x35, 0x00, 0xff, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00,
+ 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0xdc, 0x00, 0xe2,
+ 0x00, 0xdd, 0x00, 0xd8, 0x02, 0xd9, 0x00, 0xda, 0x28, 0xdb, 0x00,
+ 0xdf, 0x00, 0x29, 0x00, 0x30, 0x00, 0xbd, 0x00, 0xff, 0x1a, 0x69,
+ 0x70, 0xef, 0x62, 0x00, 0x08, 0x71, 0x10, 0x62, 0x00, 0x00, 0x62,
+ 0x01, 0x92, 0x70, 0xef, 0x62, 0x04, 0x03, 0x71, 0x10, 0x62, 0x04,
+ 0x17, 0x62, 0x05, 0xab, 0x70, 0xef, 0x62, 0x08, 0x00, 0x71, 0x10,
+ 0x62, 0x08, 0x00, 0x62, 0x09, 0x28, 0x70, 0xef, 0x62, 0x0c, 0x00,
+ 0x71, 0x10, 0x62, 0x0c, 0x00, 0x62, 0x0d, 0x00, 0x70, 0xef, 0x62,
+ 0x10, 0x00, 0x71, 0x10, 0x62, 0x10, 0x00, 0x62, 0x11, 0x00, 0x70,
+ 0xef, 0x62, 0x01, 0x00, 0x62, 0x05, 0x00, 0x62, 0x09, 0x00, 0x62,
+ 0x0d, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef, 0x7f, 0x55, 0x00, 0x08,
+ 0x55, 0x01, 0x03, 0x55, 0x02, 0x00, 0x7c, 0x02, 0xc3, 0x7c, 0x02,
+ 0x5e, 0x7f, 0x10, 0x70, 0xef, 0x50, 0x00, 0x67, 0x50, 0x01, 0x57,
+ 0xb2, 0x7c, 0x02, 0xde, 0x50, 0x01, 0x67, 0x50, 0x02, 0x57, 0x35,
+ 0x7c, 0x02, 0xde, 0x70, 0xef, 0x20, 0x7f, 0x38, 0x02, 0x10, 0x08,
+ 0x4f, 0x56, 0xfc, 0x00, 0xd0, 0x04, 0x56, 0xfc, 0x01, 0x18, 0x20,
+ 0x70, 0xef, 0x62, 0xe3, 0x00, 0x10, 0x08, 0x28, 0x39, 0xff, 0xa0,
+ 0x1f, 0x4f, 0x48, 0xfc, 0x01, 0xa0, 0x03, 0x71, 0x10, 0x54, 0xfd,
+ 0x18, 0x20, 0x75, 0x09, 0x00, 0x10, 0x08, 0x28, 0x4f, 0x59, 0xfd,
+ 0x61, 0x00, 0x18, 0x20, 0x75, 0x09, 0x00, 0x8f, 0xd7, 0x38, 0xfc,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00,
+ 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x01, 0xef, 0x80,
+ 0x04, 0x2e, 0x01, 0x10, 0x51, 0x01, 0x60, 0x04, 0x70, 0x3f, 0x71,
+ 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01, 0x80, 0x03,
+ 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x01,
+ 0xfb, 0x80, 0x04, 0x2e, 0x01, 0x04, 0x51, 0x01, 0x60, 0x04, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x10,
+ 0x70, 0x3f, 0x71, 0x80, 0x5d, 0xd3, 0x08, 0x5d, 0xd0, 0x08, 0x62,
+ 0xd0, 0x00, 0x51, 0x06, 0x60, 0xd3, 0x2e, 0x03, 0x80, 0x49, 0xd7,
+ 0x08, 0xa0, 0x09, 0x26, 0x03, 0xf0, 0x2e, 0x03, 0x00, 0x80, 0x08,
+ 0x49, 0xd7, 0x20, 0xa0, 0x03, 0x80, 0xac, 0x51, 0x03, 0x21, 0x0e,
+ 0xe0, 0x01, 0x80, 0x11, 0x80, 0x6d, 0x80, 0x7f, 0x80, 0x4d, 0x80,
+ 0x9c, 0x80, 0x9a, 0x80, 0x98, 0x80, 0x96, 0x80, 0x9d, 0x5d, 0xd8,
+ 0x21, 0xfe, 0x39, 0x40, 0xa0, 0x06, 0x62, 0xd7, 0x00, 0x80, 0x90,
+ 0x49, 0xd8, 0x01, 0xb0, 0x15, 0x55, 0x0a, 0x02, 0x26, 0x05, 0x00,
+ 0x26, 0x04, 0x00, 0x26, 0x03, 0xf0, 0x2e, 0x03, 0x04, 0x62, 0xd7,
+ 0x10, 0x80, 0x77, 0x55, 0x0a, 0x01, 0x26, 0x03, 0xf0, 0x2e, 0x03,
+ 0x06, 0x5f, 0x05, 0x04, 0x51, 0x07, 0x02, 0x05, 0x5c, 0x52, 0x00,
+ 0x60, 0xd8, 0x76, 0x05, 0x62, 0xd7, 0x14, 0x80, 0x5b, 0x51, 0x08,
+ 0x78, 0x3a, 0x05, 0xc0, 0x0f, 0x51, 0x07, 0x02, 0x05, 0x5c, 0x52,
+ 0x00, 0x60, 0xd8, 0x76, 0x05, 0x2e, 0x03, 0x20, 0x60, 0xd8, 0x62,
+ 0xd7, 0x04, 0x80, 0x3f, 0x5d, 0xd8, 0x3a, 0x08, 0xd0, 0x2b, 0xa0,
+ 0x29, 0x53, 0x05, 0x53, 0x04, 0x26, 0x03, 0xf0, 0x2e, 0x03, 0x04,
+ 0x80, 0x18, 0x51, 0x09, 0x78, 0x3a, 0x05, 0xc0, 0x16, 0x51, 0x07,
+ 0x02, 0x05, 0x5c, 0x5d, 0xd8, 0x54, 0x00, 0x2e, 0x03, 0x10, 0x76,
+ 0x05, 0x80, 0x01, 0x62, 0xd7, 0x10, 0x80, 0x0f, 0x62, 0xd7, 0x00,
+ 0x80, 0x0a, 0x26, 0x03, 0xf0, 0x2e, 0x03, 0x00, 0x55, 0x0a, 0x00,
+ 0x18, 0x60, 0xd0, 0x18, 0x60, 0xd3, 0x20, 0x18, 0x7e, 0x62, 0xd0,
+ 0x00, 0x71, 0x10, 0x41, 0x04, 0xfc, 0x43, 0x05, 0x03, 0x70, 0xef,
+ 0x26, 0x01, 0xfc, 0x51, 0x01, 0x60, 0x04, 0x55, 0x0a, 0x00, 0x90,
+ 0x28, 0x90, 0x2d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x00, 0x53,
+ 0x04, 0x71, 0x10, 0x43, 0x04, 0x03, 0x43, 0x05, 0x03, 0x70, 0xef,
+ 0x2e, 0x01, 0x03, 0x51, 0x01, 0x60, 0x04, 0x7f, 0x62, 0xd0, 0x00,
+ 0x51, 0x03, 0x21, 0xb0, 0x26, 0x03, 0x4f, 0x7f, 0x41, 0xe0, 0x7f,
+ 0x43, 0xe0, 0x80, 0x7f, 0x43, 0xd6, 0x31, 0x7f, 0x41, 0xe0, 0x7f,
+ 0x41, 0xd6, 0xfe, 0x7f, 0x62, 0xd0, 0x00, 0x4f, 0x52, 0xfd, 0x53,
+ 0x08, 0x52, 0xfc, 0x53, 0x09, 0x52, 0xfb, 0x53, 0x07, 0x52, 0xfa,
+ 0x53, 0x06, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x5d, 0xa4, 0x04,
+ 0x19, 0x5d, 0xa5, 0x0c, 0x18, 0x55, 0x1a, 0x01, 0x18, 0x7e, 0x70,
+ 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x53, 0x1c, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x52, 0x87, 0x62, 0xd3, 0x00, 0x13, 0x6b, 0x62, 0xd3,
+ 0x00, 0x54, 0x6f, 0x62, 0xd3, 0x00, 0x52, 0x86, 0x62, 0xd3, 0x00,
+ 0x1b, 0x6a, 0x62, 0xd3, 0x00, 0x54, 0x6e, 0x48, 0x6e, 0x80, 0xb0,
+ 0x33, 0x3d, 0x6e, 0x00, 0xb0, 0x7b, 0x51, 0x0b, 0x3b, 0x6f, 0xc0,
+ 0x75, 0x52, 0x6f, 0x58, 0x1c, 0x01, 0x00, 0x6d, 0x62, 0xd3, 0x00,
+ 0x05, 0x49, 0xc0, 0x09, 0x51, 0x0d, 0x3b, 0x49, 0xd0, 0x12, 0xa0,
+ 0x10, 0x56, 0x49, 0x00, 0x5b, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x07,
+ 0x6b, 0x01, 0x0f, 0x6a, 0x00, 0x80, 0x41, 0x3d, 0x6e, 0xff, 0xb0,
+ 0x09, 0x50, 0xff, 0x12, 0x0c, 0x3b, 0x6f, 0xc0, 0x20, 0x62, 0xd3,
+ 0x00, 0x56, 0x6f, 0x00, 0x56, 0x6e, 0x00, 0x5b, 0x67, 0x5c, 0x62,
+ 0xd3, 0x00, 0x52, 0x50, 0x78, 0xd0, 0x03, 0x50, 0x00, 0x54, 0x50,
+ 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c, 0x62, 0xd3, 0x00, 0x52,
+ 0x87, 0x62, 0xd3, 0x00, 0x54, 0x6b, 0x62, 0xd3, 0x00, 0x52, 0x86,
+ 0x62, 0xd3, 0x00, 0x54, 0x6a, 0x51, 0x1c, 0x64, 0x5c, 0x62, 0xd3,
+ 0x00, 0x56, 0x6f, 0x00, 0x56, 0x6e, 0x00, 0x5b, 0x67, 0x5c, 0x62,
+ 0xd3, 0x00, 0x51, 0x10, 0x54, 0x50, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x08, 0x5c, 0x62, 0xd3,
+ 0x00, 0x52, 0x4b, 0x53, 0x17, 0x55, 0x16, 0x00, 0x18, 0x08, 0x90,
+ 0x7e, 0x62, 0xd3, 0x00, 0x23, 0x4d, 0xb0, 0x2c, 0x51, 0x0e, 0x04,
+ 0x17, 0x0e, 0x16, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52,
+ 0x6f, 0x12, 0x17, 0x52, 0x6e, 0x1a, 0x16, 0xc0, 0x39, 0x5b, 0x67,
+ 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x4e, 0x78, 0x54, 0x4e, 0x08, 0x5b,
+ 0x64, 0x5c, 0x18, 0xb0, 0x3e, 0x80, 0x18, 0x51, 0x0e, 0x14, 0x17,
+ 0x1e, 0x16, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x6f,
+ 0x12, 0x17, 0x52, 0x6e, 0x1a, 0x16, 0xc0, 0x0e, 0x5b, 0x67, 0x90,
+ 0x31, 0x62, 0xd3, 0x00, 0x2d, 0x4d, 0x50, 0x01, 0x80, 0x24, 0x5b,
+ 0x67, 0x08, 0x90, 0x23, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x4d, 0x62,
+ 0xd3, 0x00, 0x20, 0x51, 0x0f, 0x54, 0x4e, 0x50, 0x00, 0x80, 0x0d,
+ 0x5b, 0x67, 0x90, 0x0d, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x4d, 0x50,
+ 0x00, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x67, 0x67, 0x67, 0x5c,
+ 0x18, 0x21, 0x07, 0xf0, 0x01, 0x7f, 0x01, 0x02, 0x04, 0x08, 0x10,
+ 0x20, 0x40, 0x80, 0x70, 0xbf, 0x70, 0xbf, 0x62, 0xd3, 0x00, 0x50,
+ 0x02, 0x78, 0x08, 0x5c, 0x56, 0x4b, 0x1e, 0x18, 0x78, 0xdf, 0xf8,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x91, 0xb2, 0x70, 0xbf, 0x18,
+ 0x08, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x87, 0x62, 0xd3, 0x00,
+ 0x54, 0x6b, 0x62, 0xd3, 0x00, 0x52, 0x86, 0x62, 0xd3, 0x00, 0x54,
+ 0x6a, 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62,
+ 0xd0, 0x00, 0x55, 0x12, 0x00, 0x50, 0x02, 0x78, 0x08, 0x9f, 0x0e,
+ 0x39, 0x01, 0xb0, 0x04, 0x55, 0x12, 0x01, 0x18, 0x78, 0xdf, 0xf3,
+ 0x51, 0x12, 0x7f, 0x50, 0x02, 0x78, 0x08, 0x9e, 0x3e, 0x18, 0x78,
+ 0xdf, 0xfa, 0x7f, 0x98, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0xd8, 0xd9, 0xda, 0xdb, 0xdf, 0x00, 0x01, 0x03, 0x07, 0x0f,
+ 0x1f, 0x3f, 0x7f, 0xff, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x62, 0xd3,
+ 0x00, 0x57, 0x00, 0x56, 0x4d, 0x00, 0x79, 0xdf, 0xfb, 0x62, 0xd3,
+ 0x00, 0x57, 0x01, 0x50, 0x03, 0x54, 0x4e, 0x79, 0xdf, 0xfc, 0x62,
+ 0xd3, 0x00, 0x50, 0x32, 0x57, 0x01, 0x54, 0x50, 0x79, 0xdf, 0xfc,
+ 0x70, 0x3f, 0x71, 0xc0, 0x55, 0x0b, 0x19, 0x55, 0x0c, 0x05, 0x55,
+ 0x0d, 0x14, 0x55, 0x0e, 0x01, 0x55, 0x0f, 0x03, 0x55, 0x10, 0x32,
+ 0x55, 0x20, 0x04, 0x55, 0x1d, 0x14, 0x43, 0x61, 0x0d, 0x57, 0x00,
+ 0x50, 0x02, 0x90, 0xae, 0x50, 0x04, 0xff, 0x98, 0x29, 0x00, 0x60,
+ 0xa9, 0x62, 0xa0, 0x08, 0x43, 0xa2, 0x04, 0x62, 0xa3, 0x70, 0x43,
+ 0x7a, 0x01, 0x43, 0xaa, 0x02, 0x43, 0xdf, 0x01, 0x50, 0x01, 0x57,
+ 0x09, 0x90, 0x20, 0x90, 0x55, 0x57, 0x01, 0x50, 0xb3, 0x91, 0x5d,
+ 0x50, 0x00, 0x57, 0x0d, 0x90, 0x12, 0x90, 0x47, 0x7f, 0x53, 0x20,
+ 0xff, 0x67, 0x29, 0x00, 0x60, 0xa9, 0x51, 0x1f, 0x58, 0x1e, 0x90,
+ 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21, 0x03, 0x53, 0x1f, 0x64, 0x64,
+ 0x64, 0x64, 0x64, 0x29, 0x80, 0x60, 0xa1, 0x5b, 0x78, 0x21, 0x0f,
+ 0x29, 0x08, 0x74, 0x53, 0x1e, 0x12, 0x20, 0x02, 0x1f, 0x5c, 0x50,
+ 0x00, 0x53, 0x1b, 0x53, 0x21, 0x29, 0x01, 0x79, 0xa0, 0x08, 0x64,
+ 0x6b, 0x1b, 0x6b, 0x21, 0x8f, 0xf5, 0x60, 0xb5, 0x51, 0x1b, 0x60,
+ 0xb4, 0x7f, 0x50, 0x02, 0x78, 0x08, 0x90, 0x28, 0x90, 0x5a, 0x18,
+ 0x78, 0xdf, 0xf8, 0x7f, 0x41, 0xdf, 0xfe, 0x71, 0x10, 0x41, 0xd8,
+ 0xfd, 0x70, 0xef, 0x41, 0x61, 0xf3, 0x41, 0xa2, 0xfb, 0x41, 0xa0,
+ 0xf7, 0x62, 0xa3, 0x00, 0x62, 0xa9, 0x00, 0x41, 0xaa, 0xfd, 0x7f,
+ 0x02, 0x20, 0x02, 0x08, 0x64, 0x5c, 0xff, 0xf8, 0x4b, 0x74, 0xff,
+ 0xf4, 0x7f, 0x62, 0xd0, 0x00, 0x53, 0x1b, 0x10, 0x5b, 0x64, 0x64,
+ 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x2a, 0x1b, 0x61, 0x01, 0x36, 0x1b,
+ 0xff, 0x5e, 0x00, 0x22, 0x1b, 0x61, 0x00, 0x36, 0x1b, 0xff, 0x18,
+ 0xfe, 0xd6, 0x5c, 0x5e, 0x00, 0x2a, 0x1b, 0x61, 0x00, 0x70, 0xef,
+ 0x7f, 0x62, 0xd0, 0x00, 0x10, 0x73, 0x53, 0x1b, 0x71, 0x10, 0x5b,
+ 0xfe, 0xc0, 0x5c, 0x5e, 0x00, 0x22, 0x1b, 0x61, 0x00, 0x70, 0xef,
+ 0x18, 0x64, 0x64, 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x22, 0x1b, 0x61,
+ 0x01, 0x36, 0x1b, 0xff, 0x5e, 0x00, 0x2a, 0x1b, 0x61, 0x00, 0x70,
+ 0xef, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53, 0x1c, 0x50, 0x00,
+ 0x53, 0x18, 0x53, 0x19, 0x51, 0x1c, 0x5c, 0x62, 0xd3, 0x00, 0x52,
+ 0x22, 0x53, 0x1d, 0x43, 0xa0, 0x01, 0x51, 0x1d, 0x60, 0xfd, 0x41,
+ 0xa3, 0xdf, 0x51, 0x1c, 0x9f, 0x7a, 0x9f, 0x81, 0x58, 0x21, 0x55,
+ 0x1a, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x43, 0xb3, 0x01,
+ 0x51, 0x1a, 0xaf, 0xfd, 0x79, 0xdf, 0xee, 0x51, 0x1c, 0x9f, 0x5f,
+ 0x9f, 0x91, 0x43, 0xa3, 0x20, 0x41, 0xa0, 0xfe, 0x62, 0xfd, 0x00,
+ 0x50, 0xff, 0x4c, 0x19, 0x14, 0x19, 0x51, 0x1e, 0x11, 0x08, 0xfe,
+ 0x4d, 0x4c, 0x18, 0x1c, 0x18, 0xd0, 0x07, 0x55, 0x18, 0x00, 0x55,
+ 0x19, 0x00, 0x51, 0x1c, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x19,
+ 0x54, 0x87, 0x51, 0x18, 0x54, 0x86, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x08, 0x9f, 0x86, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x70, 0xbf, 0x62,
+ 0xd0, 0x00, 0x53, 0x25, 0x5a, 0x24, 0x55, 0x1c, 0x01, 0x62, 0xd3,
+ 0x00, 0x58, 0x1c, 0x56, 0x22, 0x80, 0x55, 0x27, 0x08, 0x55, 0x26,
+ 0x80, 0x51, 0x1c, 0x9f, 0x63, 0x51, 0x1c, 0x9f, 0x5f, 0x70, 0xbf,
+ 0x58, 0x1c, 0x62, 0xd3, 0x00, 0x51, 0x19, 0x3a, 0x25, 0x51, 0x18,
+ 0x1a, 0x24, 0xd0, 0x06, 0x51, 0x26, 0x73, 0x25, 0x22, 0x68, 0x26,
+ 0x26, 0x26, 0x7f, 0x51, 0x26, 0x2d, 0x22, 0x7a, 0x27, 0xbf, 0xd6,
+ 0x7a, 0x1c, 0xdf, 0xc4, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62, 0xd0,
+ 0x00, 0x51, 0x8b, 0x11, 0xb0, 0x51, 0x8a, 0x19, 0x04, 0xd0, 0x12,
+ 0x7c, 0x13, 0x75, 0x39, 0x0f, 0xa0, 0x16, 0x62, 0xd0, 0x00, 0x76,
+ 0x8b, 0x0e, 0x8a, 0x00, 0x80, 0x0c, 0x62, 0xd0, 0x00, 0x55, 0x8b,
+ 0x00, 0x55, 0x8a, 0x00, 0x90, 0xa1, 0x7f, 0x62, 0xd0, 0x00, 0x3c,
+ 0x94, 0xf0, 0xd0, 0x03, 0x76, 0x94, 0x62, 0xd0, 0x00, 0x51, 0x2d,
+ 0x21, 0x7f, 0x53, 0x48, 0x51, 0x94, 0x3a, 0x48, 0xb0, 0x50, 0x7c,
+ 0x13, 0x75, 0x62, 0xd0, 0x00, 0x53, 0x95, 0x3c, 0x95, 0x0f, 0xa0,
+ 0x3d, 0x3c, 0x8c, 0x00, 0xb0, 0x1c, 0x55, 0x82, 0x00, 0x55, 0x83,
+ 0x00, 0x51, 0x95, 0x53, 0x47, 0x55, 0x48, 0x00, 0x06, 0x47, 0x82,
+ 0x0e, 0x48, 0x00, 0x51, 0x48, 0x60, 0xd5, 0x50, 0x08, 0x3f, 0x47,
+ 0x62, 0xd0, 0x00, 0x55, 0x8f, 0x00, 0x3c, 0x93, 0x00, 0xb0, 0x0a,
+ 0x7c, 0x14, 0x06, 0x62, 0xd0, 0x00, 0x55, 0x93, 0x01, 0x62, 0xd0,
+ 0x00, 0x55, 0x8e, 0x03, 0x80, 0x07, 0x62, 0xd0, 0x00, 0x55, 0x94,
+ 0x00, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x8b, 0x00, 0x55, 0x8a, 0x00,
+ 0x3c, 0x93, 0x01, 0xb0, 0x29, 0x7a, 0x8e, 0x3c, 0x8e, 0x00, 0xb0,
+ 0x22, 0x7c, 0x14, 0xa2, 0x62, 0xd0, 0x00, 0x55, 0x93, 0x00, 0x3c,
+ 0x8c, 0x00, 0xb0, 0x0e, 0x51, 0x95, 0x53, 0x47, 0x55, 0x48, 0x00,
+ 0x06, 0x47, 0x82, 0x7c, 0x1a, 0x37, 0x62, 0xd0, 0x00, 0x55, 0x94,
+ 0x00, 0x7f, 0x10, 0x4f, 0x38, 0x16, 0x62, 0xd0, 0x00, 0x3c, 0x91,
+ 0x00, 0xb0, 0x05, 0x51, 0x7a, 0x53, 0x22, 0x56, 0x0d, 0x00, 0x81,
+ 0x09, 0x56, 0x00, 0x00, 0x80, 0xfd, 0x62, 0xd0, 0x00, 0x3c, 0x91,
+ 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x47, 0x55, 0x48, 0x00, 0x06,
+ 0x47, 0x7a, 0x7c, 0x19, 0x0f, 0x52, 0x00, 0x53, 0x45, 0x55, 0x46,
+ 0x00, 0x06, 0x45, 0x22, 0x7c, 0x1a, 0x01, 0x10, 0x52, 0x00, 0x7c,
+ 0x07, 0xf6, 0x20, 0x10, 0x7c, 0x04, 0x81, 0x62, 0xd0, 0x00, 0x20,
+ 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00, 0x00, 0xb0, 0x3a, 0x7c, 0x18,
+ 0xb9, 0x7c, 0x18, 0xe1, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x51,
+ 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46, 0x50, 0x00, 0x08, 0x50,
+ 0x07, 0x08, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x7c, 0x18, 0x45,
+ 0x18, 0x53, 0x45, 0x18, 0x53, 0x46, 0x38, 0xfe, 0x7c, 0x18, 0xf7,
+ 0x3d, 0x00, 0x01, 0xb0, 0x3d, 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9,
+ 0x7c, 0x18, 0xe1, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x03, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x51, 0x40,
+ 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46, 0x50, 0x00, 0x08, 0x50, 0x07,
+ 0x08, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x7c, 0x18, 0x45, 0x18,
+ 0x53, 0x45, 0x18, 0x53, 0x46, 0x38, 0xfe, 0x7c, 0x18, 0xf7, 0x62,
+ 0xd0, 0x00, 0x55, 0x48, 0x03, 0x5a, 0x47, 0x06, 0x47, 0x01, 0x52,
+ 0x00, 0x53, 0x45, 0x50, 0x00, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x7c, 0x19,
+ 0x9e, 0x53, 0x48, 0x52, 0x0d, 0x53, 0x45, 0x55, 0x46, 0x00, 0x65,
+ 0x45, 0x6b, 0x46, 0x7c, 0x19, 0xb1, 0x53, 0x48, 0x7c, 0x19, 0xf5,
+ 0x06, 0x45, 0x86, 0x0e, 0x46, 0x00, 0x51, 0x46, 0x7c, 0x19, 0x04,
+ 0x7c, 0x18, 0xf7, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x00, 0x77,
+ 0x0d, 0x3d, 0x0d, 0x03, 0xce, 0xf4, 0x56, 0x00, 0x00, 0x80, 0xc0,
+ 0x62, 0xd0, 0x00, 0x55, 0x48, 0x03, 0x5a, 0x47, 0x06, 0x47, 0x01,
+ 0x52, 0x00, 0x53, 0x45, 0x50, 0x00, 0x08, 0x51, 0x45, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x7c,
+ 0x19, 0x9e, 0x60, 0xd4, 0x3e, 0x47, 0x54, 0x0e, 0x3e, 0x47, 0x54,
+ 0x0f, 0x5a, 0x47, 0x06, 0x47, 0x03, 0x52, 0x00, 0x53, 0x45, 0x50,
+ 0x00, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08,
+ 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x7c, 0x19, 0x9e, 0x60, 0xd4, 0x3e,
+ 0x47, 0x54, 0x10, 0x3e, 0x47, 0x54, 0x11, 0x5a, 0x47, 0x06, 0x47,
+ 0x05, 0x52, 0x00, 0x53, 0x45, 0x50, 0x00, 0x08, 0x51, 0x45, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc,
+ 0x7c, 0x19, 0x9e, 0x60, 0xd4, 0x3e, 0x47, 0x54, 0x12, 0x3e, 0x47,
+ 0x54, 0x13, 0x50, 0x03, 0x08, 0x5a, 0x47, 0x06, 0x47, 0x0e, 0x08,
+ 0x51, 0x47, 0x08, 0x7c, 0x17, 0x38, 0x38, 0xfd, 0x62, 0xd0, 0x00,
+ 0x51, 0x47, 0x54, 0x15, 0x51, 0x48, 0x54, 0x14, 0x7c, 0x18, 0xb9,
+ 0x7c, 0x19, 0x93, 0x7c, 0x19, 0xda, 0x06, 0x47, 0x6a, 0x7c, 0x19,
+ 0xe5, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x62, 0x7c, 0x19, 0xbc,
+ 0x51, 0x47, 0x01, 0x52, 0x7c, 0x19, 0xbc, 0x06, 0x47, 0x5a, 0x7c,
+ 0x19, 0xe5, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x3d, 0x38, 0xea,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x16, 0x62, 0xd0, 0x00, 0x50, 0x01,
+ 0x10, 0x08, 0x57, 0x8a, 0x28, 0x53, 0x48, 0x18, 0x75, 0x09, 0x00,
+ 0x28, 0x53, 0x47, 0x20, 0x10, 0x51, 0x48, 0x08, 0x51, 0x47, 0x20,
+ 0x7c, 0x08, 0x75, 0x20, 0x62, 0xd0, 0x00, 0x3c, 0x91, 0x01, 0xb0,
+ 0x0b, 0x51, 0x22, 0x53, 0x2e, 0x51, 0x23, 0x53, 0x2f, 0x80, 0x0c,
+ 0x62, 0xd0, 0x00, 0x51, 0x7a, 0x53, 0x22, 0x51, 0x7b, 0x53, 0x23,
+ 0x10, 0x50, 0x00, 0x7c, 0x07, 0xf6, 0x20, 0x56, 0x0d, 0x00, 0x81,
+ 0x09, 0x56, 0x00, 0x00, 0x80, 0xfd, 0x62, 0xd0, 0x00, 0x3c, 0x91,
+ 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x47, 0x55, 0x48, 0x00, 0x06,
+ 0x47, 0x7a, 0x7c, 0x19, 0x0f, 0x52, 0x00, 0x53, 0x45, 0x55, 0x46,
+ 0x00, 0x06, 0x45, 0x22, 0x7c, 0x1a, 0x01, 0x10, 0x52, 0x00, 0x7c,
+ 0x07, 0xf6, 0x20, 0x10, 0x7c, 0x04, 0x81, 0x62, 0xd0, 0x00, 0x20,
+ 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00, 0x00, 0xb0, 0x3a, 0x7c, 0x18,
+ 0xb9, 0x7c, 0x18, 0xe1, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x51,
+ 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46, 0x50, 0x00, 0x08, 0x50,
+ 0x07, 0x08, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x7c, 0x18, 0x45,
+ 0x18, 0x53, 0x45, 0x18, 0x53, 0x46, 0x38, 0xfe, 0x7c, 0x18, 0xf7,
+ 0x3d, 0x00, 0x01, 0xb0, 0x3d, 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9,
+ 0x7c, 0x18, 0xe1, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x03, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x51, 0x40,
+ 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46, 0x50, 0x00, 0x08, 0x50, 0x07,
+ 0x08, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08, 0x7c, 0x18, 0x45, 0x18,
+ 0x53, 0x45, 0x18, 0x53, 0x46, 0x38, 0xfe, 0x7c, 0x18, 0xf7, 0x62,
+ 0xd0, 0x00, 0x55, 0x48, 0x03, 0x5a, 0x47, 0x06, 0x47, 0x01, 0x52,
+ 0x00, 0x53, 0x45, 0x50, 0x00, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00,
+ 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x7c, 0x19,
+ 0x9e, 0x53, 0x48, 0x52, 0x0d, 0x53, 0x45, 0x55, 0x46, 0x00, 0x65,
+ 0x45, 0x6b, 0x46, 0x7c, 0x19, 0xb1, 0x53, 0x48, 0x7c, 0x19, 0xf5,
+ 0x06, 0x45, 0x86, 0x0e, 0x46, 0x00, 0x51, 0x46, 0x7c, 0x19, 0x04,
+ 0x7c, 0x18, 0xf7, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x00, 0x77,
+ 0x0d, 0x3d, 0x0d, 0x03, 0xce, 0xf4, 0x56, 0x00, 0x00, 0x80, 0xc0,
+ 0x62, 0xd0, 0x00, 0x55, 0x48, 0x03, 0x5a, 0x47, 0x06, 0x47, 0x01,
+ 0x52, 0x00, 0x53, 0x45, 0x50, 0x00, 0x08, 0x51, 0x45, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x7c,
+ 0x19, 0x9e, 0x60, 0xd4, 0x3e, 0x47, 0x54, 0x0e, 0x3e, 0x47, 0x54,
+ 0x0f, 0x5a, 0x47, 0x06, 0x47, 0x03, 0x52, 0x00, 0x53, 0x45, 0x50,
+ 0x00, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08,
+ 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x7c, 0x19, 0x9e, 0x60, 0xd4, 0x3e,
+ 0x47, 0x54, 0x10, 0x3e, 0x47, 0x54, 0x11, 0x5a, 0x47, 0x06, 0x47,
+ 0x05, 0x52, 0x00, 0x53, 0x45, 0x50, 0x00, 0x08, 0x51, 0x45, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x18, 0x89, 0x38, 0xfc,
+ 0x7c, 0x19, 0x9e, 0x60, 0xd4, 0x3e, 0x47, 0x54, 0x12, 0x3e, 0x47,
+ 0x54, 0x13, 0x50, 0x03, 0x08, 0x5a, 0x47, 0x06, 0x47, 0x0e, 0x08,
+ 0x51, 0x47, 0x08, 0x7c, 0x17, 0x38, 0x38, 0xfd, 0x62, 0xd0, 0x00,
+ 0x51, 0x47, 0x54, 0x15, 0x51, 0x48, 0x54, 0x14, 0x7c, 0x18, 0xb9,
+ 0x7c, 0x19, 0x93, 0x7c, 0x19, 0xda, 0x06, 0x47, 0x6a, 0x7c, 0x19,
+ 0xe5, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x62, 0x7c, 0x19, 0xbc,
+ 0x51, 0x47, 0x01, 0x52, 0x7c, 0x19, 0xbc, 0x06, 0x47, 0x5a, 0x7c,
+ 0x19, 0xe5, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x3d, 0x56, 0x00,
+ 0x00, 0x80, 0x19, 0x7c, 0x18, 0xd6, 0x06, 0x47, 0x22, 0x7c, 0x19,
+ 0x0f, 0x52, 0x00, 0x53, 0x45, 0x55, 0x46, 0x00, 0x06, 0x45, 0x2e,
+ 0x7c, 0x1a, 0x01, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0xe4, 0x38,
+ 0xea, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x0a, 0x62, 0xd0, 0x00, 0x55,
+ 0x8d, 0x00, 0x3c, 0x91, 0x00, 0xb0, 0x05, 0x51, 0x7a, 0x53, 0x22,
+ 0x10, 0x50, 0x00, 0x7c, 0x07, 0xf6, 0x20, 0x56, 0x00, 0x00, 0x80,
+ 0xb7, 0x62, 0xd0, 0x00, 0x3c, 0x91, 0x00, 0xb0, 0x1b, 0x52, 0x00,
+ 0x53, 0x47, 0x55, 0x48, 0x00, 0x06, 0x47, 0x7a, 0x7c, 0x19, 0x0f,
+ 0x52, 0x00, 0x53, 0x45, 0x55, 0x46, 0x00, 0x06, 0x45, 0x22, 0x7c,
+ 0x1a, 0x01, 0x10, 0x52, 0x00, 0x7c, 0x07, 0xf6, 0x20, 0x10, 0x7c,
+ 0x04, 0x81, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x3d,
+ 0x00, 0x00, 0xb0, 0x3a, 0x7c, 0x18, 0xb9, 0x7c, 0x18, 0xe1, 0x51,
+ 0x46, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08,
+ 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f,
+ 0x53, 0x46, 0x50, 0x00, 0x08, 0x50, 0x07, 0x08, 0x51, 0x46, 0x08,
+ 0x51, 0x45, 0x08, 0x7c, 0x18, 0x45, 0x18, 0x53, 0x45, 0x18, 0x53,
+ 0x46, 0x38, 0xfe, 0x7c, 0x18, 0xf7, 0x3d, 0x00, 0x01, 0xb0, 0x3d,
+ 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9, 0x7c, 0x18, 0xe1, 0x51, 0x46,
+ 0x08, 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x7c,
+ 0x18, 0x89, 0x38, 0xfc, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53,
+ 0x46, 0x50, 0x00, 0x08, 0x50, 0x07, 0x08, 0x51, 0x46, 0x08, 0x51,
+ 0x45, 0x08, 0x7c, 0x18, 0x45, 0x18, 0x53, 0x45, 0x18, 0x53, 0x46,
+ 0x38, 0xfe, 0x7c, 0x18, 0xf7, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf,
+ 0x46, 0x56, 0x00, 0x00, 0x82, 0xf8, 0x62, 0xd0, 0x00, 0x3c, 0x96,
+ 0x02, 0xa0, 0x9f, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x6a, 0x7c,
+ 0x18, 0xc5, 0x06, 0x47, 0x86, 0x7c, 0x19, 0x0f, 0x7c, 0x19, 0xcd,
+ 0xd0, 0x16, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x6a, 0x7c, 0x18,
+ 0xc5, 0x06, 0x47, 0x86, 0x7c, 0x19, 0x0f, 0x7c, 0x1a, 0x50, 0x80,
+ 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86,
+ 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x6a, 0x7c, 0x19, 0x0f, 0x7c, 0x1a,
+ 0x50, 0x50, 0x90, 0x13, 0x07, 0x50, 0x01, 0x1b, 0x06, 0xc0, 0x4e,
+ 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x5a, 0x7c,
+ 0x18, 0xc5, 0x06, 0x47, 0x86, 0x7c, 0x19, 0x0f, 0x7c, 0x19, 0xcd,
+ 0xd0, 0x16, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x5a, 0x7c, 0x18,
+ 0xc5, 0x06, 0x47, 0x86, 0x7c, 0x19, 0x0f, 0x7c, 0x1a, 0x43, 0x80,
+ 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86,
+ 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x5a, 0x7c, 0x19, 0x0f, 0x7c, 0x1a,
+ 0x43, 0x50, 0x90, 0x13, 0x09, 0x50, 0x01, 0x1b, 0x08, 0xd0, 0x08,
+ 0x62, 0xd0, 0x00, 0x76, 0x8d, 0x82, 0x50, 0x62, 0xd0, 0x00, 0x7c,
+ 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86, 0x7c, 0x18, 0xc5, 0x06, 0x47,
+ 0x5a, 0x7c, 0x19, 0x0f, 0x7c, 0x19, 0xcd, 0xd0, 0x7e, 0x7c, 0x18,
+ 0xb9, 0x7c, 0x18, 0xe1, 0x06, 0x45, 0x01, 0x0e, 0x46, 0x00, 0x7c,
+ 0x18, 0xf7, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86, 0x7c, 0x18,
+ 0xc5, 0x06, 0x47, 0x5a, 0x7c, 0x19, 0x0f, 0x7c, 0x19, 0xcd, 0xd1,
+ 0x01, 0x7c, 0x18, 0xb9, 0x7c, 0x18, 0xe1, 0x06, 0x45, 0x01, 0x0e,
+ 0x46, 0x00, 0x7c, 0x18, 0xf7, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01,
+ 0x86, 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x5a, 0x7c, 0x19, 0x0f, 0x7c,
+ 0x19, 0xcd, 0xd0, 0xdd, 0x7c, 0x18, 0xb9, 0x7c, 0x18, 0xe1, 0x06,
+ 0x45, 0x01, 0x0e, 0x46, 0x00, 0x7c, 0x18, 0xf7, 0x7c, 0x18, 0xb9,
+ 0x51, 0x47, 0x01, 0x86, 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x5a, 0x7c,
+ 0x19, 0x0f, 0x7c, 0x19, 0xcd, 0xd0, 0xb9, 0x7c, 0x18, 0xb9, 0x7c,
+ 0x18, 0xe1, 0x06, 0x45, 0x01, 0x0e, 0x46, 0x00, 0x7c, 0x18, 0xf7,
+ 0x80, 0xa8, 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01,
+ 0x86, 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x5a, 0x7c, 0x19, 0x0f, 0x3e,
+ 0x47, 0x12, 0x45, 0x51, 0x48, 0x1a, 0x46, 0xd0, 0x8b, 0x7c, 0x18,
+ 0xb9, 0x7c, 0x18, 0xe1, 0x16, 0x45, 0x01, 0x1e, 0x46, 0x00, 0x7c,
+ 0x18, 0xf7, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86, 0x7c, 0x18,
+ 0xc5, 0x06, 0x47, 0x5a, 0x7c, 0x19, 0x0f, 0x3e, 0x47, 0x12, 0x45,
+ 0x51, 0x48, 0x1a, 0x46, 0xd0, 0x62, 0x7c, 0x18, 0xb9, 0x7c, 0x18,
+ 0xe1, 0x16, 0x45, 0x01, 0x1e, 0x46, 0x00, 0x7c, 0x18, 0xf7, 0x7c,
+ 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86, 0x7c, 0x18, 0xc5, 0x06, 0x47,
+ 0x5a, 0x7c, 0x19, 0x0f, 0x3e, 0x47, 0x12, 0x45, 0x51, 0x48, 0x1a,
+ 0x46, 0xd0, 0x39, 0x7c, 0x18, 0xb9, 0x7c, 0x18, 0xe1, 0x16, 0x45,
+ 0x01, 0x1e, 0x46, 0x00, 0x7c, 0x18, 0xf7, 0x7c, 0x18, 0xb9, 0x51,
+ 0x47, 0x01, 0x86, 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x5a, 0x7c, 0x19,
+ 0x0f, 0x3e, 0x47, 0x12, 0x45, 0x51, 0x48, 0x1a, 0x46, 0xd0, 0x10,
+ 0x7c, 0x18, 0xb9, 0x7c, 0x18, 0xe1, 0x16, 0x45, 0x01, 0x1e, 0x46,
+ 0x00, 0x7c, 0x18, 0xf7, 0x62, 0xd0, 0x00, 0x7c, 0x18, 0xb9, 0x51,
+ 0x47, 0x01, 0x52, 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x62, 0x0e, 0x48,
+ 0x00, 0x7c, 0x18, 0xf7, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x5a,
+ 0x7c, 0x18, 0xc5, 0x06, 0x47, 0x52, 0x0e, 0x48, 0x00, 0x7c, 0x18,
+ 0xf7, 0x7c, 0x18, 0xb9, 0x51, 0x47, 0x01, 0x86, 0x7c, 0x18, 0xc5,
+ 0x06, 0x47, 0x5a, 0x0e, 0x48, 0x00, 0x7c, 0x18, 0xf7, 0x97, 0xf6,
+ 0x40, 0x7c, 0x19, 0x93, 0x53, 0x46, 0x7c, 0x1a, 0x5d, 0x53, 0x43,
+ 0x08, 0x51, 0x44, 0x53, 0x42, 0x18, 0x53, 0x41, 0x65, 0x41, 0x6b,
+ 0x42, 0x06, 0x47, 0x52, 0x7c, 0x19, 0x0f, 0x3e, 0x47, 0x53, 0x47,
+ 0x51, 0x41, 0x04, 0x47, 0x51, 0x42, 0x0c, 0x48, 0x51, 0x43, 0x04,
+ 0x47, 0x51, 0x44, 0x0c, 0x48, 0x70, 0xfb, 0x6e, 0x48, 0x6e, 0x47,
+ 0x7c, 0x1a, 0x24, 0x10, 0x52, 0x00, 0x7c, 0x04, 0xc5, 0x20, 0x62,
+ 0xd0, 0x00, 0x97, 0xb0, 0x40, 0x51, 0x47, 0x01, 0x86, 0x97, 0xb5,
+ 0x40, 0x06, 0x47, 0x6a, 0x97, 0xf9, 0x40, 0x7c, 0x19, 0xcd, 0xd0,
+ 0x25, 0x52, 0x00, 0x53, 0x47, 0x55, 0x48, 0x00, 0x06, 0x47, 0x76,
+ 0x0e, 0x48, 0x00, 0x51, 0x48, 0x60, 0xd4, 0x3e, 0x47, 0x7a, 0x47,
+ 0x53, 0x46, 0x06, 0x46, 0x01, 0x51, 0x48, 0x60, 0xd5, 0x51, 0x46,
+ 0x3f, 0x47, 0x80, 0x0a, 0x97, 0x94, 0x40, 0x06, 0x47, 0x76, 0x7c,
+ 0x1a, 0x37, 0x97, 0x8b, 0x40, 0x06, 0x47, 0x76, 0x97, 0xbe, 0x40,
+ 0x50, 0x05, 0x3a, 0x48, 0xd0, 0x41, 0x97, 0x5f, 0x40, 0x51, 0x47,
+ 0x01, 0x6a, 0x53, 0x45, 0x51, 0x48, 0x09, 0x00, 0x53, 0x46, 0x06,
+ 0x47, 0x86, 0x97, 0xa3, 0x40, 0x3e, 0x47, 0x53, 0x47, 0x51, 0x46,
+ 0x7c, 0x1a, 0x5d, 0x02, 0x47, 0x53, 0x47, 0x51, 0x44, 0x0a, 0x48,
+ 0x53, 0x48, 0x7c, 0x1a, 0x24, 0x52, 0x00, 0x53, 0x47, 0x55, 0x48,
+ 0x00, 0x06, 0x47, 0x76, 0x0e, 0x48, 0x00, 0x51, 0x48, 0x60, 0xd5,
+ 0x50, 0x00, 0x3f, 0x47, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcd, 0x05,
+ 0x62, 0xd0, 0x00, 0x3c, 0x96, 0x02, 0xb1, 0x40, 0x56, 0x00, 0x00,
+ 0x81, 0x36, 0x3d, 0x00, 0x00, 0xb0, 0x99, 0x62, 0xd0, 0x00, 0x97,
+ 0x03, 0x40, 0x51, 0x47, 0x01, 0x86, 0x97, 0x08, 0x40, 0x51, 0x46,
+ 0x08, 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x07, 0x08, 0x7c,
+ 0x18, 0x89, 0x38, 0xfc, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53,
+ 0x46, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x51, 0x46, 0x08, 0x51,
+ 0x45, 0x08, 0x7c, 0x18, 0x45, 0x18, 0x53, 0x45, 0x18, 0x53, 0x46,
+ 0x38, 0xfe, 0x06, 0x47, 0x36, 0x0e, 0x48, 0x00, 0x97, 0x01, 0x40,
+ 0x96, 0xc0, 0x40, 0x51, 0x47, 0x01, 0x6a, 0x96, 0xc5, 0x40, 0x51,
+ 0x46, 0x08, 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x07, 0x08,
+ 0x7c, 0x18, 0x89, 0x38, 0xfc, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f,
+ 0x53, 0x46, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x51, 0x46, 0x08,
+ 0x51, 0x45, 0x08, 0x7c, 0x18, 0x45, 0x18, 0x53, 0x45, 0x18, 0x53,
+ 0x46, 0x38, 0xfe, 0x06, 0x47, 0x3a, 0x0e, 0x48, 0x00, 0x96, 0xbe,
+ 0x40, 0x96, 0x7d, 0x40, 0x51, 0x47, 0x01, 0x6a, 0x96, 0x82, 0x40,
+ 0x96, 0xd5, 0x40, 0x80, 0x97, 0x62, 0xd0, 0x00, 0x96, 0x6b, 0x40,
+ 0x51, 0x47, 0x01, 0x86, 0x96, 0x70, 0x40, 0x51, 0x46, 0x08, 0x51,
+ 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x07, 0x08, 0x7c, 0x18, 0x89,
+ 0x38, 0xfc, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46, 0x50,
+ 0x00, 0x08, 0x50, 0x03, 0x08, 0x51, 0x46, 0x08, 0x51, 0x45, 0x08,
+ 0x7c, 0x18, 0x45, 0x18, 0x53, 0x45, 0x18, 0x53, 0x46, 0x38, 0xfe,
+ 0x06, 0x47, 0x36, 0x0e, 0x48, 0x00, 0x96, 0x69, 0x40, 0x96, 0x28,
+ 0x40, 0x51, 0x47, 0x01, 0x6a, 0x96, 0x2d, 0x40, 0x51, 0x46, 0x08,
+ 0x51, 0x45, 0x08, 0x50, 0x00, 0x08, 0x50, 0x07, 0x08, 0x7c, 0x18,
+ 0x89, 0x38, 0xfc, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46,
+ 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x51, 0x46, 0x08, 0x51, 0x45,
+ 0x08, 0x7c, 0x18, 0x45, 0x18, 0x53, 0x45, 0x18, 0x53, 0x46, 0x38,
+ 0xfe, 0x06, 0x47, 0x3a, 0x0e, 0x48, 0x00, 0x96, 0x26, 0x40, 0x95,
+ 0xe5, 0x40, 0x51, 0x47, 0x01, 0x6a, 0x95, 0xea, 0x40, 0x96, 0x3d,
+ 0x40, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0xc7, 0x62, 0xd0, 0x00,
+ 0x3c, 0x96, 0x02, 0xa0, 0x18, 0x3c, 0x8d, 0x00, 0xa0, 0x13, 0x50,
+ 0x75, 0x08, 0x50, 0x30, 0x08, 0x90, 0x0e, 0x38, 0xfe, 0x7c, 0x09,
+ 0x8d, 0x10, 0x7c, 0x06, 0x81, 0x20, 0x38, 0xf6, 0x20, 0x7f, 0x10,
+ 0x4f, 0x80, 0x02, 0x40, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53, 0x47,
+ 0x52, 0xfb, 0x53, 0x48, 0x51, 0x47, 0x11, 0x01, 0x54, 0xfc, 0x51,
+ 0x48, 0x19, 0x00, 0x54, 0xfb, 0x3c, 0x48, 0x00, 0xbf, 0xe4, 0x3c,
+ 0x47, 0x00, 0xbf, 0xdf, 0x20, 0x7f, 0x10, 0x7c, 0x03, 0x45, 0x7c,
+ 0x03, 0x22, 0x20, 0x7f, 0x10, 0x7c, 0x03, 0x41, 0x7c, 0x03, 0x1e,
+ 0x20, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0x4b, 0x12, 0x6f, 0x50, 0x00,
+ 0x1a, 0x6e, 0xd0, 0x0f, 0x51, 0x4c, 0x12, 0x71, 0x50, 0x00, 0x1a,
+ 0x70, 0xd0, 0x05, 0x50, 0x0f, 0x80, 0x17, 0x62, 0xd0, 0x00, 0x51,
+ 0x6f, 0x12, 0x71, 0x51, 0x6e, 0x1a, 0x70, 0xd0, 0x05, 0x50, 0x00,
+ 0x80, 0x06, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x7f, 0x10, 0x4f, 0x38,
+ 0x05, 0x62, 0xd0, 0x00, 0x51, 0x6f, 0x54, 0x02, 0x51, 0x6e, 0x54,
+ 0x01, 0x56, 0x04, 0x00, 0x56, 0x00, 0x00, 0x56, 0x03, 0x00, 0x80,
+ 0x5d, 0x95, 0x45, 0x40, 0x06, 0x47, 0x4b, 0x0e, 0x48, 0x00, 0x51,
+ 0x48, 0x60, 0xd4, 0x3e, 0x47, 0x53, 0x47, 0x96, 0x53, 0x40, 0x06,
+ 0x45, 0x6e, 0x0e, 0x46, 0x00, 0x51, 0x46, 0x95, 0x57, 0x40, 0x51,
+ 0x47, 0x12, 0x45, 0x50, 0x00, 0x1a, 0x46, 0xd0, 0x03, 0x77, 0x03,
+ 0x62, 0xd0, 0x00, 0x94, 0xfa, 0x40, 0x06, 0x47, 0x6e, 0x95, 0x4a,
+ 0x40, 0x3e, 0x47, 0x13, 0x02, 0x51, 0x48, 0x1b, 0x01, 0xd0, 0x1a,
+ 0x94, 0xe7, 0x40, 0x06, 0x47, 0x6e, 0x0e, 0x48, 0x00, 0x51, 0x48,
+ 0x60, 0xd4, 0x3e, 0x47, 0x54, 0x01, 0x3e, 0x47, 0x54, 0x02, 0x52,
+ 0x00, 0x54, 0x04, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0xa0, 0x50,
+ 0x01, 0x3b, 0x03, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50, 0x0f, 0x80,
+ 0x06, 0x52, 0x04, 0x62, 0xd0, 0x00, 0x38, 0xfb, 0x20, 0x7f, 0x10,
+ 0x4f, 0x38, 0x02, 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x26, 0x28, 0xf0,
+ 0x51, 0x95, 0x01, 0x01, 0x53, 0x48, 0x51, 0x28, 0x2a, 0x48, 0x53,
+ 0x28, 0x71, 0x01, 0x62, 0xe3, 0x38, 0x10, 0x7c, 0x04, 0x81, 0x62,
+ 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56, 0x01, 0x00, 0x56, 0x00,
+ 0x00, 0x80, 0x21, 0x10, 0x7c, 0x04, 0x81, 0x62, 0xd0, 0x00, 0x20,
+ 0x53, 0x48, 0x47, 0x48, 0x20, 0xa0, 0x03, 0x80, 0x1a, 0x50, 0x00,
+ 0x08, 0x50, 0x14, 0x08, 0x9e, 0xba, 0x38, 0xfe, 0x77, 0x01, 0x0f,
+ 0x00, 0x00, 0x52, 0x01, 0x11, 0x2c, 0x52, 0x00, 0x19, 0x01, 0xcf,
+ 0xd7, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21, 0x10, 0x7c,
+ 0x04, 0x81, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x48, 0x47, 0x48, 0x20,
+ 0xb0, 0x03, 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e,
+ 0x88, 0x38, 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01, 0x11,
+ 0x3c, 0x52, 0x00, 0x19, 0x00, 0xcf, 0xd7, 0x62, 0xd0, 0x00, 0x51,
+ 0x28, 0x29, 0x08, 0x53, 0x28, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20,
+ 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x26,
+ 0x28, 0xf0, 0x51, 0x95, 0x01, 0x09, 0x53, 0x48, 0x51, 0x28, 0x2a,
+ 0x48, 0x53, 0x28, 0x71, 0x01, 0x62, 0xe3, 0x38, 0x10, 0x7c, 0x04,
+ 0x81, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56, 0x01, 0x00,
+ 0x56, 0x00, 0x00, 0x80, 0x21, 0x10, 0x7c, 0x04, 0x81, 0x62, 0xd0,
+ 0x00, 0x20, 0x53, 0x48, 0x47, 0x48, 0x20, 0xa0, 0x03, 0x80, 0x1a,
+ 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e, 0x1e, 0x38, 0xfe, 0x77,
+ 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01, 0x11, 0x2c, 0x52, 0x00, 0x19,
+ 0x01, 0xcf, 0xd7, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21,
+ 0x10, 0x7c, 0x04, 0x81, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x48, 0x47,
+ 0x48, 0x20, 0xb0, 0x03, 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x14,
+ 0x08, 0x9d, 0xec, 0x38, 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52,
+ 0x01, 0x11, 0x3c, 0x52, 0x00, 0x19, 0x00, 0xcf, 0xd7, 0x43, 0x00,
+ 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x04, 0x62, 0xd0,
+ 0x00, 0x51, 0x28, 0x21, 0xf0, 0x54, 0x00, 0x51, 0x2b, 0x54, 0x01,
+ 0x3d, 0x00, 0x10, 0xb0, 0x12, 0x55, 0x8f, 0x00, 0x55, 0x82, 0x00,
+ 0x55, 0x83, 0x00, 0x56, 0x00, 0x00, 0x26, 0x28, 0x0f, 0x81, 0x94,
+ 0x3d, 0x00, 0x20, 0xb0, 0x18, 0x62, 0xd0, 0x00, 0x55, 0x8f, 0x01,
+ 0x55, 0x90, 0x00, 0x55, 0x82, 0x08, 0x55, 0x83, 0x08, 0x56, 0x00,
+ 0x00, 0x26, 0x28, 0x0f, 0x81, 0x78, 0x3d, 0x00, 0x40, 0xb0, 0x0f,
+ 0x62, 0xd0, 0x00, 0x55, 0x96, 0x02, 0x56, 0x00, 0x00, 0x26, 0x28,
+ 0x0f, 0x81, 0x65, 0x3d, 0x00, 0x50, 0xb0, 0xa7, 0x52, 0x01, 0x54,
+ 0x03, 0x56, 0x02, 0x00, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03,
+ 0x01, 0xa0, 0x21, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x02,
+ 0xa0, 0x28, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x04, 0xa0,
+ 0x36, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x08, 0xa0, 0x48,
+ 0x80, 0x62, 0x62, 0xd0, 0x00, 0x55, 0x91, 0x01, 0x51, 0x2d, 0x29,
+ 0x80, 0x53, 0x2d, 0x7c, 0x0b, 0x7c, 0x80, 0x51, 0x62, 0xd0, 0x00,
+ 0x51, 0x29, 0x53, 0x4b, 0x51, 0x29, 0x53, 0x4c, 0x51, 0x29, 0x53,
+ 0x2c, 0x51, 0x2a, 0x53, 0x0c, 0x55, 0x0b, 0x00, 0x80, 0x39, 0x62,
+ 0xd0, 0x00, 0x51, 0x29, 0x53, 0x2d, 0x3c, 0x91, 0x00, 0xa0, 0x09,
+ 0x51, 0x2d, 0x29, 0x80, 0x53, 0x2d, 0x80, 0x25, 0x62, 0xd0, 0x00,
+ 0x26, 0x2d, 0x7f, 0x80, 0x1d, 0x62, 0xd0, 0x00, 0x55, 0x91, 0x00,
+ 0x26, 0x2d, 0x7f, 0x51, 0x7a, 0x53, 0x22, 0x51, 0x22, 0x53, 0x2e,
+ 0x51, 0x7b, 0x53, 0x23, 0x51, 0x23, 0x53, 0x2f, 0x7c, 0x0b, 0x7c,
+ 0x56, 0x00, 0x00, 0x62, 0xd0, 0x00, 0x26, 0x28, 0x0f, 0x55, 0x29,
+ 0x12, 0x55, 0x2a, 0x11, 0x55, 0x2b, 0x00, 0x80, 0xba, 0x3d, 0x00,
+ 0x60, 0xb0, 0x0f, 0x62, 0xd0, 0x00, 0x55, 0x8c, 0x01, 0x56, 0x00,
+ 0x00, 0x26, 0x28, 0x0f, 0x80, 0xa7, 0x3d, 0x00, 0x70, 0xb0, 0x0f,
+ 0x62, 0xd0, 0x00, 0x55, 0x8c, 0x00, 0x56, 0x00, 0x00, 0x26, 0x28,
+ 0x0f, 0x80, 0x94, 0x3d, 0x00, 0x80, 0xb0, 0x8f, 0x56, 0x00, 0x00,
+ 0x62, 0xd0, 0x00, 0x26, 0x28, 0x0f, 0x9c, 0xc5, 0x10, 0x7c, 0x03,
+ 0x45, 0x7c, 0x03, 0x22, 0x7c, 0x07, 0x74, 0x7c, 0x04, 0x97, 0x20,
+ 0x93, 0x91, 0x40, 0x70, 0xfe, 0x71, 0x10, 0x43, 0x00, 0x08, 0x43,
+ 0x01, 0x08, 0x70, 0xcf, 0x43, 0x00, 0x08, 0x62, 0xda, 0x00, 0x71,
+ 0x10, 0x41, 0xdc, 0xfe, 0x70, 0xcf, 0x43, 0x01, 0x08, 0x43, 0x00,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x1e, 0x08, 0x9c, 0x65, 0x38, 0xfe,
+ 0x71, 0x01, 0x43, 0xe0, 0x10, 0x41, 0x7a, 0xef, 0x41, 0x7a, 0xfe,
+ 0x71, 0x10, 0x41, 0xdc, 0xfd, 0x41, 0xec, 0xfd, 0x43, 0xe0, 0x40,
+ 0x41, 0xe0, 0xdf, 0x70, 0xcf, 0x43, 0xff, 0x08, 0x43, 0x7a, 0x10,
+ 0x43, 0x7a, 0x01, 0x70, 0xfe, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x10, 0x7c, 0x06, 0xa3, 0x7c, 0x04, 0x4b, 0x7c, 0x04, 0x8c,
+ 0x20, 0x93, 0x2d, 0x40, 0x71, 0x01, 0x62, 0xe3, 0x38, 0x56, 0x00,
+ 0x00, 0x62, 0xd0, 0x00, 0x26, 0x28, 0x0f, 0x38, 0xfc, 0x20, 0x7f,
+ 0x62, 0xd0, 0x00, 0x3c, 0x8f, 0x00, 0xa0, 0x13, 0x9c, 0x34, 0x62,
+ 0xd0, 0x00, 0x3c, 0x90, 0x00, 0xb0, 0x33, 0x55, 0x90, 0x01, 0x7c,
+ 0x09, 0x8d, 0x80, 0x2b, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x82,
+ 0xd0, 0x08, 0x10, 0x7c, 0x03, 0x45, 0x20, 0x80, 0x06, 0x10, 0x7c,
+ 0x03, 0x41, 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x83, 0xd0,
+ 0x08, 0x10, 0x7c, 0x03, 0x22, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x03,
+ 0x1e, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x03, 0x56, 0x02, 0x00, 0x56,
+ 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x3e, 0x62, 0xd0, 0x00, 0x91,
+ 0x6d, 0x40, 0x52, 0xfc, 0x04, 0x47, 0x52, 0xfb, 0x0c, 0x48, 0x51,
+ 0x48, 0x60, 0xd4, 0x3e, 0x47, 0x53, 0x48, 0x3e, 0x47, 0x53, 0x47,
+ 0x52, 0x02, 0x12, 0x47, 0x52, 0x01, 0x1a, 0x48, 0xd0, 0x18, 0x91,
+ 0x4c, 0x40, 0x52, 0xfc, 0x04, 0x47, 0x52, 0xfb, 0x0c, 0x48, 0x51,
+ 0x48, 0x60, 0xd4, 0x3e, 0x47, 0x54, 0x01, 0x3e, 0x47, 0x54, 0x02,
+ 0x77, 0x00, 0x52, 0x00, 0x3b, 0xfa, 0xcf, 0xbe, 0x62, 0xd0, 0x00,
+ 0x52, 0x02, 0x53, 0x47, 0x52, 0x01, 0x53, 0x48, 0x38, 0xfd, 0x20,
+ 0x7f, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x91, 0x00, 0x55, 0x8c, 0x01,
+ 0x10, 0x7c, 0x03, 0x45, 0x7c, 0x03, 0x22, 0x20, 0x9b, 0x84, 0x71,
+ 0x10, 0x41, 0x00, 0xf7, 0x41, 0x01, 0xf7, 0x70, 0xcf, 0x43, 0x00,
+ 0x08, 0x43, 0x00, 0x08, 0x62, 0xd0, 0x00, 0x55, 0x28, 0x08, 0x55,
+ 0x29, 0x12, 0x55, 0x2a, 0x11, 0x55, 0x2c, 0x1e, 0x55, 0x2d, 0x02,
+ 0x3c, 0x91, 0x00, 0xa0, 0x09, 0x51, 0x2d, 0x29, 0x80, 0x53, 0x2d,
+ 0x80, 0x07, 0x62, 0xd0, 0x00, 0x26, 0x2d, 0x7f, 0x10, 0x50, 0x00,
+ 0x08, 0x50, 0x28, 0x08, 0x50, 0x06, 0x08, 0x50, 0x16, 0x08, 0x7c,
+ 0x04, 0x9e, 0x38, 0xfc, 0x7c, 0x04, 0x4b, 0x7c, 0x04, 0x8c, 0x20,
+ 0x71, 0x10, 0x41, 0x04, 0xfe, 0x41, 0x05, 0xfe, 0x41, 0x04, 0xfd,
+ 0x41, 0x05, 0xfd, 0x70, 0xcf, 0x43, 0x04, 0x01, 0x43, 0x04, 0x02,
+ 0x71, 0x01, 0x10, 0x7c, 0x06, 0xa3, 0x7c, 0x06, 0x29, 0x20, 0x7c,
+ 0x0b, 0x7c, 0x80, 0x22, 0x62, 0xe3, 0x38, 0x7c, 0x0d, 0xc4, 0x10,
+ 0x7c, 0x06, 0x67, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xa0, 0x09,
+ 0x7c, 0x08, 0xc3, 0x7c, 0x08, 0xed, 0x80, 0x04, 0x7c, 0x09, 0x56,
+ 0x9c, 0xf6, 0x9e, 0xb2, 0x8f, 0xde, 0x8f, 0xff, 0x10, 0x4f, 0x7c,
+ 0x18, 0x50, 0x20, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x5d, 0xd0, 0x08,
+ 0x62, 0xd0, 0x00, 0x50, 0x00, 0x53, 0x3f, 0x53, 0x40, 0x55, 0x3e,
+ 0x10, 0x66, 0xfc, 0x6c, 0xfb, 0x6b, 0x3f, 0x6b, 0x40, 0x51, 0x3f,
+ 0x1b, 0xfa, 0x51, 0x40, 0x1b, 0xf9, 0xc0, 0x09, 0x53, 0x40, 0x52,
+ 0xfa, 0x1c, 0x3f, 0x77, 0xfc, 0x7a, 0x3e, 0xbf, 0xe3, 0x51, 0x3f,
+ 0x54, 0xfa, 0x51, 0x40, 0x54, 0xf9, 0x18, 0x60, 0xd0, 0x7f, 0x10,
+ 0x4f, 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50, 0x00, 0x53, 0x40,
+ 0x53, 0x3f, 0x55, 0x3e, 0x10, 0x6f, 0xf9, 0x6f, 0xfa, 0xd0, 0x09,
+ 0x52, 0xfc, 0x04, 0x40, 0x52, 0xfb, 0x0c, 0x3f, 0x66, 0xfc, 0x6c,
+ 0xfb, 0x7a, 0x3e, 0xbf, 0xeb, 0x18, 0x60, 0xd0, 0x20, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x52, 0x00, 0x53, 0x47, 0x55, 0x48, 0x00, 0x65,
+ 0x47, 0x6b, 0x48, 0x7f, 0x53, 0x45, 0x51, 0x48, 0x09, 0x00, 0x60,
+ 0xd4, 0x3e, 0x45, 0x53, 0x46, 0x3e, 0x45, 0x53, 0x45, 0x7f, 0x62,
+ 0xd0, 0x00, 0x52, 0x00, 0x53, 0x47, 0x55, 0x48, 0x00, 0x7f, 0x06,
+ 0x47, 0x86, 0x0e, 0x48, 0x00, 0x51, 0x48, 0x60, 0xd4, 0x3e, 0x47,
+ 0x53, 0x46, 0x3e, 0x47, 0x16, 0x47, 0x02, 0x53, 0x45, 0x7f, 0x51,
+ 0x48, 0x60, 0xd5, 0x51, 0x46, 0x3f, 0x47, 0x51, 0x45, 0x3f, 0x47,
+ 0x7f, 0x60, 0xd4, 0x3e, 0x45, 0x53, 0x46, 0x3e, 0x45, 0x53, 0x45,
+ 0x7f, 0x0e, 0x48, 0x00, 0x51, 0x48, 0x60, 0xd4, 0x3e, 0x47, 0x53,
+ 0x48, 0x7f, 0x51, 0x47, 0x01, 0x86, 0x53, 0x43, 0x51, 0x48, 0x09,
+ 0x00, 0x60, 0xd4, 0x3e, 0x43, 0x53, 0x44, 0x3e, 0x43, 0x53, 0x43,
+ 0x51, 0x45, 0x12, 0x43, 0x51, 0x46, 0x1a, 0x44, 0xd0, 0x3f, 0x62,
+ 0xd0, 0x00, 0x52, 0x00, 0x53, 0x45, 0x55, 0x46, 0x00, 0x65, 0x45,
+ 0x6b, 0x46, 0x51, 0x45, 0x01, 0x6a, 0x53, 0x43, 0x51, 0x46, 0x09,
+ 0x00, 0x60, 0xd4, 0x3e, 0x43, 0x53, 0x44, 0x3e, 0x43, 0x53, 0x43,
+ 0x06, 0x45, 0x86, 0x0e, 0x46, 0x00, 0x51, 0x46, 0x60, 0xd4, 0x3e,
+ 0x45, 0x53, 0x46, 0x3e, 0x45, 0x12, 0x43, 0x54, 0x07, 0x51, 0x46,
+ 0x1a, 0x44, 0x54, 0x06, 0x80, 0x07, 0x56, 0x07, 0x00, 0x56, 0x06,
+ 0x00, 0x62, 0xd0, 0x00, 0x06, 0x47, 0x32, 0x0e, 0x48, 0x00, 0x51,
+ 0x48, 0x60, 0xd5, 0x52, 0x06, 0x3f, 0x47, 0x52, 0x07, 0x3f, 0x47,
+ 0x7f, 0x51, 0x47, 0x01, 0x86, 0x53, 0x45, 0x51, 0x48, 0x09, 0x00,
+ 0x7f, 0x51, 0x40, 0x53, 0x45, 0x51, 0x3f, 0x53, 0x46, 0x51, 0x45,
+ 0x02, 0x47, 0x53, 0x47, 0x51, 0x46, 0x0a, 0x48, 0x7f, 0x51, 0x45,
+ 0x02, 0x47, 0x53, 0x47, 0x51, 0x46, 0x0a, 0x48, 0x7f, 0x53, 0x45,
+ 0x51, 0x48, 0x09, 0x00, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x45, 0x52,
+ 0x15, 0x3f, 0x45, 0x7f, 0x3e, 0x47, 0x53, 0x47, 0x51, 0x45, 0x12,
+ 0x47, 0x51, 0x46, 0x1a, 0x48, 0x7f, 0x60, 0xd5, 0x52, 0x14, 0x3f,
+ 0x45, 0x52, 0x15, 0x3f, 0x45, 0x7f, 0x0e, 0x48, 0x00, 0x51, 0x48,
+ 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x47, 0x52, 0x15, 0x3f, 0x47, 0x7f,
+ 0x52, 0x00, 0x53, 0x45, 0x55, 0x46, 0x00, 0x65, 0x45, 0x6b, 0x46,
+ 0x7f, 0x0e, 0x46, 0x00, 0x51, 0x46, 0x60, 0xd5, 0x51, 0x48, 0x3f,
+ 0x45, 0x7f, 0x71, 0x10, 0x43, 0x04, 0x01, 0x43, 0x05, 0x01, 0x43,
+ 0x04, 0x02, 0x43, 0x05, 0x02, 0x70, 0xcf, 0x43, 0x04, 0x01, 0x43,
+ 0x04, 0x02, 0x7f, 0x70, 0xfb, 0x6e, 0x48, 0x6e, 0x47, 0x51, 0x46,
+ 0x60, 0xd5, 0x51, 0x48, 0x3f, 0x45, 0x51, 0x47, 0x3f, 0x45, 0x7f,
+ 0x0e, 0x48, 0x00, 0x51, 0x48, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x47,
+ 0x7f, 0x3e, 0x47, 0x12, 0x45, 0x54, 0x09, 0x51, 0x48, 0x1a, 0x46,
+ 0x54, 0x08, 0x7f, 0x3e, 0x47, 0x12, 0x45, 0x54, 0x07, 0x51, 0x48,
+ 0x1a, 0x46, 0x54, 0x06, 0x7f, 0x60, 0xd4, 0x3e, 0x45, 0x53, 0x44,
+ 0x3e, 0x45, 0x16, 0x45, 0x02, 0x7f, 0x00, 0x28, 0x00, 0x16, 0x00,
+ 0x52, 0x00, 0x18, 0x00, 0x72, 0x00, 0x08, 0x00, 0x7a, 0x04, 0x2e,
+ 0x18, 0x0d, 0x0f, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x82, 0x04, 0x08,
+ 0x08, 0x08, 0x08, 0x00, 0x8a, 0x09, 0x00, 0x00, 0x01, 0x00, 0x03,
+ 0x01, 0x01, 0x00, 0x02, 0x00, 0x93, 0x00, 0x04, 0xff, 0x00, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_T0.h b/drivers/input/keyboard/cypressbln/touchkey_fw_T0.h
new file mode 100644
index 0000000..671d265
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_T0.h
@@ -0,0 +1,770 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x00, 0x68,
+ 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x04, 0xae, 0x7e, 0x7e, 0x30,
+ 0x30, 0x30, 0x7d, 0x05, 0xfb, 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x40, 0x71, 0x10, 0x62, 0xe3,
+ 0x06, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x50, 0x80, 0x4e, 0x62, 0xe3,
+ 0x38, 0x5d, 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55,
+ 0xfa, 0x01, 0x40, 0x4f, 0x5b, 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a,
+ 0x50, 0x06, 0x00, 0x40, 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8,
+ 0x70, 0xef, 0x18, 0x60, 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00,
+ 0x71, 0x10, 0x62, 0xe0, 0x1a, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x71,
+ 0x10, 0x41, 0xe1, 0xfe, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1,
+ 0x03, 0x50, 0x80, 0x4e, 0x62, 0xd3, 0x03, 0x62,
+ 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4, 0x00, 0x71, 0xc0, 0x7c, 0x03,
+ 0x1b, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x57, 0xc2, 0x08, 0x28, 0x53,
+ 0x51, 0x18, 0x75, 0x09, 0x00, 0x28, 0x4b, 0x51, 0x51, 0x80, 0x04,
+ 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00, 0x08, 0x28, 0x60, 0xd5, 0x74,
+ 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x53, 0x51, 0x18,
+ 0x75, 0x09, 0x00, 0x08, 0x28, 0xa0, 0x1c, 0x53,
+ 0x50, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x3f, 0x51, 0x47, 0x51, 0xff,
+ 0xb0, 0x06, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x18, 0x7a, 0x50, 0xbf,
+ 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x53, 0x50,
+ 0x50, 0x00, 0x3f, 0x51, 0x47, 0x51, 0xff, 0xb0, 0x08, 0x5d, 0xd5,
+ 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x50, 0xbf, 0xef, 0x18, 0x8f,
+ 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71, 0x10,
+ 0x62, 0xe0, 0x1a, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x1b, 0x4b,
+ 0x8f, 0xff, 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x01, 0x99, 0x03, 0x33, 0x06, 0x66,
+ 0x0c, 0xcc, 0x19, 0x99, 0x33, 0x33, 0x66, 0x66,
+ 0xcc, 0xcc, 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, 0x0b, 0xff, 0x18, 0x00,
+ 0x2f, 0xff, 0x5f, 0xff, 0xbf, 0xff, 0x01, 0x66, 0x02, 0xcc, 0x05,
+ 0x99, 0x0b, 0x32, 0x16, 0x66, 0x2c, 0xcc, 0x59, 0x98, 0xb3, 0x32,
+ 0x01, 0x4c, 0x02, 0x99, 0x05, 0x33, 0x0a, 0x65, 0x14, 0xcc, 0x29,
+ 0x98, 0x53, 0x32, 0xa6, 0x65, 0x01, 0x33, 0x02, 0x66, 0x04, 0xcc,
+ 0x09, 0x99, 0x13, 0x33, 0x26, 0x65, 0x4c, 0xcc,
+ 0x99, 0x99, 0x1d, 0xea, 0x70, 0xef, 0x62, 0x61, 0x00, 0x62, 0xfd, 0x00,
+ 0x62, 0xcd, 0x00, 0x62, 0xce, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4,
+ 0x00, 0x62, 0xa0, 0x00, 0x62, 0xa1, 0x80, 0x62, 0xa2, 0xc0, 0x62,
+ 0xa3, 0x0c, 0x62, 0xa8, 0x00, 0x62, 0xa6, 0x00, 0x62, 0xa7, 0x00,
+ 0x62, 0x7c, 0x33, 0x62, 0x7a, 0x00, 0x62, 0x7b, 0x00, 0x62, 0x79,
+ 0x00, 0x62, 0x36, 0x00, 0x62, 0x37, 0x00, 0x62,
+ 0x38, 0x00, 0x62, 0x39, 0x00, 0x62, 0x3a, 0x00, 0x62, 0x3b, 0x00, 0x62,
+ 0x3c, 0x00, 0x62, 0x3d, 0x00, 0x62, 0x3e, 0x00, 0x62, 0x3f, 0x00,
+ 0x62, 0x40, 0x00, 0x62, 0x41, 0x00, 0x62, 0x42, 0x00, 0x62, 0x43,
+ 0x00, 0x62, 0x44, 0x00, 0x62, 0x45, 0x00, 0x62, 0x46, 0x00, 0x62,
+ 0x47, 0x00, 0x62, 0x48, 0x00, 0x62, 0x49, 0x00, 0x62, 0x4a, 0x00,
+ 0x62, 0x4b, 0x00, 0x62, 0x4c, 0x00, 0x62, 0x4d,
+ 0x00, 0x62, 0x4e, 0x00, 0x62, 0x4f, 0x00, 0x62, 0xca, 0x20, 0x62, 0xd6,
+ 0x44, 0x62, 0xcf, 0x00, 0x62, 0xcb, 0x00, 0x62, 0xc8, 0x00, 0x62,
+ 0xcc, 0x00, 0x62, 0xc9, 0x00, 0x62, 0xd7, 0x00, 0x62, 0xa9, 0x00,
+ 0x62, 0x2b, 0x00, 0x62, 0xb0, 0x00, 0x62, 0xb3, 0x02, 0x62, 0xb6,
+ 0x00, 0x62, 0xb2, 0x00, 0x62, 0xb5, 0x00, 0x62, 0xb8, 0x00, 0x62,
+ 0xb1, 0x00, 0x62, 0xb4, 0x00, 0x62, 0xb7, 0x00,
+ 0x62, 0x33, 0x00, 0x62, 0x34, 0x00, 0x62, 0x35, 0x00, 0x71, 0x10, 0x62,
+ 0x54, 0x00, 0x62, 0x55, 0x00, 0x62, 0x56, 0x00, 0x62, 0x57, 0x00,
+ 0x62, 0x58, 0x00, 0x62, 0x59, 0x00, 0x62, 0x5a, 0x00, 0x62, 0x5b,
+ 0x00, 0x62, 0xdc, 0x00, 0x62, 0xe2, 0x00, 0x62, 0xdd, 0x00, 0x62,
+ 0xd8, 0x02, 0x62, 0xd9, 0x00, 0x62, 0xda, 0x28, 0x62, 0xdb, 0x00,
+ 0x62, 0xdf, 0x00, 0x62, 0x29, 0x00, 0x62, 0x30,
+ 0x00, 0x62, 0xbd, 0x00, 0x70, 0xef, 0x70, 0xef, 0x62, 0x00, 0x08, 0x71,
+ 0x10, 0x62, 0x00, 0x08, 0x62, 0x01, 0x92, 0x70, 0xef, 0x62, 0x04,
+ 0x17, 0x71, 0x10, 0x62, 0x04, 0x17, 0x62, 0x05, 0xab, 0x70, 0xef,
+ 0x62, 0x08, 0x00, 0x71, 0x10, 0x62, 0x08, 0x00, 0x62, 0x09, 0x28,
+ 0x70, 0xef, 0x62, 0x0c, 0x00, 0x71, 0x10, 0x62, 0x0c, 0x00, 0x62,
+ 0x0d, 0x00, 0x70, 0xef, 0x62, 0x10, 0x00, 0x71,
+ 0x10, 0x62, 0x10, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef, 0x62, 0x01, 0x00,
+ 0x62, 0x05, 0x00, 0x62, 0x09, 0x00, 0x62, 0x0d, 0x00, 0x62, 0x11,
+ 0x00, 0x70, 0xef, 0x7f, 0x55, 0x02, 0x08, 0x55, 0x03, 0x17, 0x55,
+ 0x04, 0x00, 0x7c, 0x03, 0x28, 0x7f, 0x7c, 0x01, 0xc4, 0x70, 0xef,
+ 0x7f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x62, 0xd0,
+ 0x00, 0x53, 0x00, 0x71, 0x10, 0x5d, 0xe0, 0x08, 0x21, 0xf8, 0x29, 0x00,
+ 0x70, 0xfe, 0x60, 0xe0, 0x70, 0xef, 0x4b, 0x4b, 0x4b, 0x4b, 0x51,
+ 0x02, 0x21, 0xf7, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0,
+ 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0,
+ 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80,
+ 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00,
+ 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x47, 0x00, 0x00, 0x49, 0x01, 0x00, 0x29, 0x08, 0x60, 0x00, 0x57,
+ 0x01, 0x79, 0xbf, 0xfe, 0x18, 0x71, 0x10, 0x60, 0xe0, 0x70, 0xef,
+ 0x71, 0x01, 0x7f, 0x08, 0x67, 0x67, 0x67, 0x67, 0x21, 0x0f, 0xff,
+ 0x40, 0x9f, 0x4e, 0x18, 0x21, 0x0f, 0xff, 0x39, 0x9f, 0x47, 0x7f,
+ 0x08, 0x10, 0x28, 0xa0, 0x0b, 0x9f, 0x3f, 0x20,
+ 0x18, 0x75, 0xdf, 0xf5, 0x74, 0x8f, 0xf2, 0x38, 0xfe, 0x7f, 0x52, 0x00,
+ 0xa0, 0x08, 0x10, 0x9f, 0x2d, 0x20, 0x75, 0x8f, 0xf6, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x50, 0x0d, 0x9f, 0x20, 0x50, 0x0a, 0x9f, 0x1c,
+ 0x7f, 0x70, 0xbf, 0x62, 0xd3, 0x03, 0x4f, 0x52, 0xfb, 0xa0, 0x15,
+ 0x7b, 0xfb, 0x52, 0xfc, 0x59, 0xfd, 0x60, 0xd3, 0x52, 0x00, 0x9f,
+ 0x05, 0x4f, 0x62, 0xd3, 0x03, 0x77, 0xfd, 0x8f,
+ 0xe9, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x3d, 0xfa, 0x00, 0xb0, 0x06, 0x3d,
+ 0xfb, 0x00, 0xa0, 0x18, 0x10, 0x52, 0xfc, 0x59, 0xfd, 0x28, 0x9e,
+ 0xe6, 0x20, 0x07, 0xfd, 0x01, 0x0f, 0xfc, 0x00, 0x17, 0xfb, 0x01,
+ 0x1f, 0xfa, 0x00, 0x8f, 0xe0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50,
+ 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xef,
+ 0x80, 0x04, 0x2e, 0x03, 0x10, 0x51, 0x03, 0x60,
+ 0x04, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50,
+ 0x01, 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0,
+ 0x06, 0x26, 0x03, 0xfb, 0x80, 0x04, 0x2e, 0x03, 0x04, 0x51, 0x03,
+ 0x60, 0x04, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0x3f, 0x71, 0xc0,
+ 0x7f, 0x08, 0x10, 0x70, 0x3f, 0x71, 0x80, 0x5d, 0xd3, 0x08, 0x5d,
+ 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x51, 0x08, 0x60,
+ 0xd3, 0x2e, 0x05, 0x80, 0x49, 0xd7, 0x08, 0xa0, 0x09, 0x26, 0x05, 0xf0,
+ 0x2e, 0x05, 0x00, 0x80, 0x08, 0x49, 0xd7, 0x20, 0xa0, 0x03, 0x80,
+ 0xa6, 0x51, 0x05, 0x21, 0x0e, 0xe0, 0x01, 0x80, 0x11, 0x80, 0x67,
+ 0x80, 0x79, 0x80, 0x47, 0x80, 0x96, 0x80, 0x94, 0x80, 0x92, 0x80,
+ 0x90, 0x80, 0x97, 0x5d, 0xd8, 0x21, 0xfe, 0x39, 0x40, 0xa0, 0x06,
+ 0x62, 0xd7, 0x00, 0x80, 0x8a, 0x49, 0xd8, 0x01,
+ 0xb0, 0x0f, 0x55, 0x0c, 0x02, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x02, 0x62,
+ 0xd7, 0x10, 0x80, 0x77, 0x55, 0x0c, 0x01, 0x26, 0x05, 0xf0, 0x2e,
+ 0x05, 0x06, 0x5f, 0x07, 0x06, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52,
+ 0x00, 0x60, 0xd8, 0x76, 0x07, 0x62, 0xd7, 0x14, 0x80, 0x5b, 0x51,
+ 0x0a, 0x78, 0x3a, 0x07, 0xc0, 0x0f, 0x51, 0x09, 0x02, 0x07, 0x5c,
+ 0x52, 0x00, 0x60, 0xd8, 0x76, 0x07, 0x2e, 0x05,
+ 0x20, 0x60, 0xd8, 0x62, 0xd7, 0x04, 0x80, 0x3f, 0x5d, 0xd8, 0x3a, 0x0a,
+ 0xd0, 0x2b, 0xa0, 0x29, 0x53, 0x07, 0x53, 0x06, 0x26, 0x05, 0xf0,
+ 0x2e, 0x05, 0x04, 0x80, 0x18, 0x51, 0x0b, 0x78, 0x3a, 0x07, 0xc0,
+ 0x16, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x5d, 0xd8, 0x54, 0x00, 0x2e,
+ 0x05, 0x10, 0x76, 0x07, 0x80, 0x01, 0x62, 0xd7, 0x10, 0x80, 0x0f,
+ 0x62, 0xd7, 0x00, 0x80, 0x0a, 0x26, 0x05, 0xf0,
+ 0x2e, 0x05, 0x00, 0x55, 0x0c, 0x00, 0x18, 0x60, 0xd0, 0x18, 0x60, 0xd3,
+ 0x20, 0x18, 0x7e, 0x62, 0xd0, 0x00, 0x71, 0x10, 0x41, 0x04, 0xfc,
+ 0x43, 0x05, 0x03, 0x70, 0xef, 0x26, 0x03, 0xfc, 0x51, 0x03, 0x60,
+ 0x04, 0x55, 0x0c, 0x00, 0x90, 0x28, 0x90, 0x2d, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x50, 0x00, 0x53, 0x06, 0x71, 0x10, 0x43, 0x04, 0x03,
+ 0x43, 0x05, 0x03, 0x70, 0xef, 0x2e, 0x03, 0x03,
+ 0x51, 0x03, 0x60, 0x04, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0x05, 0x21, 0xb0,
+ 0x26, 0x05, 0x4f, 0x7f, 0x41, 0xe0, 0x7f, 0x43, 0xe0, 0x80, 0x7f,
+ 0x43, 0xd6, 0x31, 0x7f, 0x41, 0xe0, 0x7f, 0x41, 0xd6, 0xfe, 0x7f,
+ 0x62, 0xd0, 0x00, 0x4f, 0x52, 0xfd, 0x53, 0x0a, 0x52, 0xfc, 0x53,
+ 0x0b, 0x52, 0xfb, 0x53, 0x09, 0x52, 0xfa, 0x53, 0x08, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x08, 0x5d, 0xa4, 0x04, 0x1b,
+ 0x5d, 0xa5, 0x0c, 0x1a, 0x55, 0x1c, 0x01, 0x18, 0x7e, 0x70, 0xbf, 0x62,
+ 0xd0, 0x00, 0x70, 0xbf, 0x53, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00,
+ 0x52, 0x8d, 0x62, 0xd3, 0x00, 0x13, 0x63, 0x62, 0xd3, 0x00, 0x54,
+ 0x67, 0x62, 0xd3, 0x00, 0x52, 0x8c, 0x62, 0xd3, 0x00, 0x1b, 0x62,
+ 0x62, 0xd3, 0x00, 0x54, 0x66, 0x48, 0x66, 0x80, 0xb0, 0x33, 0x3d,
+ 0x66, 0x00, 0xb0, 0x7b, 0x51, 0x0d, 0x3b, 0x67,
+ 0xc0, 0x75, 0x52, 0x67, 0x58, 0x1e, 0x01, 0x00, 0x6d, 0x62, 0xd3, 0x00,
+ 0x05, 0x40, 0xc0, 0x09, 0x51, 0x0f, 0x3b, 0x40, 0xd0, 0x12, 0xa0,
+ 0x10, 0x56, 0x40, 0x00, 0x5b, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x07,
+ 0x63, 0x01, 0x0f, 0x62, 0x00, 0x80, 0x41, 0x3d, 0x66, 0xff, 0xb0,
+ 0x09, 0x50, 0xff, 0x12, 0x0e, 0x3b, 0x67, 0xc0, 0x20, 0x62, 0xd3,
+ 0x00, 0x56, 0x67, 0x00, 0x56, 0x66, 0x00, 0x5b,
+ 0x67, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x47, 0x78, 0xd0, 0x03, 0x50, 0x00,
+ 0x54, 0x47, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c, 0x62, 0xd3,
+ 0x00, 0x52, 0x8d, 0x62, 0xd3, 0x00, 0x54, 0x63, 0x62, 0xd3, 0x00,
+ 0x52, 0x8c, 0x62, 0xd3, 0x00, 0x54, 0x62, 0x51, 0x1e, 0x64, 0x5c,
+ 0x62, 0xd3, 0x00, 0x56, 0x67, 0x00, 0x56, 0x66, 0x00, 0x5b, 0x67,
+ 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x12, 0x54, 0x47,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf,
+ 0x08, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x42, 0x53, 0x19, 0x55, 0x18,
+ 0x00, 0x18, 0x08, 0x90, 0x7e, 0x62, 0xd3, 0x00, 0x23, 0x44, 0xb0,
+ 0x2c, 0x51, 0x10, 0x04, 0x19, 0x0e, 0x18, 0x00, 0x18, 0x64, 0x5c,
+ 0x62, 0xd3, 0x00, 0x52, 0x67, 0x12, 0x19, 0x52, 0x66, 0x1a, 0x18,
+ 0xc0, 0x39, 0x5b, 0x67, 0x5c, 0x62, 0xd3, 0x00,
+ 0x52, 0x45, 0x78, 0x54, 0x45, 0x08, 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x3e,
+ 0x80, 0x18, 0x51, 0x10, 0x14, 0x19, 0x1e, 0x18, 0x00, 0x18, 0x64,
+ 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x67, 0x12, 0x19, 0x52, 0x66, 0x1a,
+ 0x18, 0xc0, 0x0e, 0x5b, 0x67, 0x90, 0x31, 0x62, 0xd3, 0x00, 0x2d,
+ 0x44, 0x50, 0x01, 0x80, 0x24, 0x5b, 0x67, 0x08, 0x90, 0x23, 0x73,
+ 0x62, 0xd3, 0x00, 0x25, 0x44, 0x62, 0xd3, 0x00,
+ 0x20, 0x51, 0x11, 0x54, 0x45, 0x50, 0x00, 0x80, 0x0d, 0x5b, 0x67, 0x90,
+ 0x0d, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x44, 0x50, 0x00, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x08, 0x67, 0x67, 0x67, 0x5c, 0x18, 0x21, 0x07,
+ 0xf0, 0x01, 0x7f, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x70, 0xbf, 0x70, 0xbf, 0x62, 0xd3, 0x00, 0x50, 0x02, 0x78, 0x08,
+ 0x5c, 0x56, 0x42, 0x1e, 0x18, 0x78, 0xdf, 0xf8,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x91, 0xb2, 0x70, 0xbf, 0x18, 0x08,
+ 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x8d, 0x62, 0xd3, 0x00, 0x54,
+ 0x63, 0x62, 0xd3, 0x00, 0x52, 0x8c, 0x62, 0xd3, 0x00, 0x54, 0x62,
+ 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62, 0xd0,
+ 0x00, 0x55, 0x14, 0x00, 0x50, 0x02, 0x78, 0x08, 0x9f, 0x0e, 0x39,
+ 0x01, 0xb0, 0x04, 0x55, 0x14, 0x01, 0x18, 0x78,
+ 0xdf, 0xf3, 0x51, 0x14, 0x7f, 0x50, 0x02, 0x78, 0x08, 0x9e, 0x3e, 0x18,
+ 0x78, 0xdf, 0xfa, 0x7f, 0x98, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95,
+ 0x96, 0x97, 0xd8, 0xd9, 0xda, 0xdb, 0xdf, 0x00, 0x01, 0x03, 0x07,
+ 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x62,
+ 0xd3, 0x00, 0x57, 0x00, 0x56, 0x44, 0x00, 0x79, 0xdf, 0xfb, 0x62,
+ 0xd3, 0x00, 0x57, 0x01, 0x50, 0x03, 0x54, 0x45,
+ 0x79, 0xdf, 0xfc, 0x62, 0xd3, 0x00, 0x50, 0x14, 0x57, 0x01, 0x54, 0x47,
+ 0x79, 0xdf, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x55, 0x0d, 0x19, 0x55,
+ 0x0e, 0x05, 0x55, 0x0f, 0x14, 0x55, 0x10, 0x01, 0x55, 0x11, 0x03,
+ 0x55, 0x12, 0x14, 0x55, 0x22, 0x04, 0x55, 0x1f, 0x14, 0x43, 0x61,
+ 0x0d, 0x57, 0x00, 0x50, 0x02, 0x90, 0xae, 0x50, 0x04, 0xff, 0x98,
+ 0x29, 0x00, 0x60, 0xa9, 0x62, 0xa0, 0x08, 0x43,
+ 0xa2, 0x04, 0x62, 0xa3, 0x70, 0x43, 0x7a, 0x01, 0x43, 0xaa, 0x02, 0x43,
+ 0xdf, 0x01, 0x50, 0x01, 0x57, 0x09, 0x90, 0x20, 0x90, 0x55, 0x57,
+ 0x01, 0x50, 0xb3, 0x91, 0x5d, 0x50, 0x01, 0x57, 0x0e, 0x90, 0x12,
+ 0x90, 0x47, 0x7f, 0x53, 0x22, 0xff, 0x67, 0x29, 0x00, 0x60, 0xa9,
+ 0x51, 0x21, 0x58, 0x20, 0x90, 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21,
+ 0x03, 0x53, 0x21, 0x64, 0x64, 0x64, 0x64, 0x64,
+ 0x29, 0x80, 0x60, 0xa1, 0x5b, 0x78, 0x21, 0x0f, 0x29, 0x08, 0x74, 0x53,
+ 0x20, 0x12, 0x22, 0x02, 0x21, 0x5c, 0x50, 0x00, 0x53, 0x1d, 0x53,
+ 0x23, 0x29, 0x01, 0x79, 0xa0, 0x08, 0x64, 0x6b, 0x1d, 0x6b, 0x23,
+ 0x8f, 0xf5, 0x60, 0xb5, 0x51, 0x1d, 0x60, 0xb4, 0x7f, 0x50, 0x02,
+ 0x78, 0x08, 0x90, 0x28, 0x90, 0x5a, 0x18, 0x78, 0xdf, 0xf8, 0x7f,
+ 0x41, 0xdf, 0xfe, 0x71, 0x10, 0x41, 0xd8, 0xfd,
+ 0x70, 0xef, 0x41, 0x61, 0xf3, 0x41, 0xa2, 0xfb, 0x41, 0xa0, 0xf7, 0x62,
+ 0xa3, 0x00, 0x62, 0xa9, 0x00, 0x41, 0xaa, 0xfd, 0x7f, 0x02, 0x08,
+ 0x02, 0x20, 0x64, 0x5c, 0xff, 0xf8, 0x4b, 0x74, 0xff, 0xf4, 0x7f,
+ 0x62, 0xd0, 0x00, 0x53, 0x1d, 0x10, 0x5b, 0x64, 0x64, 0x5c, 0x71,
+ 0x10, 0x5e, 0x01, 0x2a, 0x1d, 0x61, 0x01, 0x36, 0x1d, 0xff, 0x5e,
+ 0x00, 0x22, 0x1d, 0x61, 0x00, 0x36, 0x1d, 0xff,
+ 0x18, 0xfe, 0xd6, 0x5c, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef,
+ 0x7f, 0x62, 0xd0, 0x00, 0x10, 0x73, 0x53, 0x1d, 0x71, 0x10, 0x5b,
+ 0xfe, 0xc0, 0x5c, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x70, 0xef,
+ 0x18, 0x64, 0x64, 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x22, 0x1d, 0x61,
+ 0x01, 0x36, 0x1d, 0xff, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70,
+ 0xef, 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53,
+ 0x1e, 0x50, 0x00, 0x53, 0x1a, 0x53, 0x1b, 0x51, 0x1e, 0x5c, 0x62, 0xd3,
+ 0x00, 0x52, 0x24, 0x53, 0x1f, 0x43, 0xa0, 0x01, 0x51, 0x1f, 0x60,
+ 0xfd, 0x41, 0xa3, 0xdf, 0x51, 0x1e, 0x9f, 0x7a, 0x9f, 0x81, 0x58,
+ 0x23, 0x55, 0x1c, 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x43,
+ 0xb3, 0x01, 0x51, 0x1c, 0xaf, 0xfd, 0x79, 0xdf, 0xee, 0x51, 0x1e,
+ 0x9f, 0x5f, 0x9f, 0x91, 0x43, 0xa3, 0x20, 0x41,
+ 0xa0, 0xfe, 0x62, 0xfd, 0x00, 0x50, 0xff, 0x4c, 0x1b, 0x14, 0x1b, 0x51,
+ 0x20, 0x11, 0x08, 0xfe, 0x4d, 0x4c, 0x1a, 0x1c, 0x1a, 0xd0, 0x07,
+ 0x55, 0x1a, 0x00, 0x55, 0x1b, 0x00, 0x51, 0x1e, 0x64, 0x5c, 0x62,
+ 0xd3, 0x00, 0x51, 0x1b, 0x54, 0x8d, 0x51, 0x1a, 0x54, 0x8c, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x9f, 0x86, 0x18, 0x78, 0xdf, 0xfa,
+ 0x7f, 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53, 0x27,
+ 0x5a, 0x26, 0x55, 0x1e, 0x01, 0x62, 0xd3, 0x00, 0x58, 0x1e, 0x56, 0x24,
+ 0x80, 0x55, 0x29, 0x08, 0x55, 0x28, 0x80, 0x51, 0x1e, 0x9f, 0x63,
+ 0x51, 0x1e, 0x9f, 0x5f, 0x70, 0xbf, 0x58, 0x1e, 0x62, 0xd3, 0x00,
+ 0x51, 0x1b, 0x3a, 0x27, 0x51, 0x1a, 0x1a, 0x26, 0xd0, 0x06, 0x51,
+ 0x28, 0x73, 0x25, 0x24, 0x68, 0x28, 0x26, 0x28, 0x7f, 0x51, 0x28,
+ 0x2d, 0x24, 0x7a, 0x29, 0xbf, 0xd6, 0x7a, 0x1e,
+ 0xdf, 0xc4, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0xa5,
+ 0x11, 0xdc, 0x51, 0xa4, 0x19, 0x05, 0xd0, 0x12, 0x7c, 0x16, 0xe7,
+ 0x39, 0x0f, 0xa0, 0x16, 0x62, 0xd0, 0x00, 0x76, 0xa5, 0x0e, 0xa4,
+ 0x00, 0x80, 0x0c, 0x62, 0xd0, 0x00, 0x55, 0xa5, 0x00, 0x55, 0xa4,
+ 0x00, 0x90, 0xbe, 0x7f, 0x62, 0xd0, 0x00, 0x3c, 0xaf, 0xf0, 0xd0,
+ 0x03, 0x76, 0xaf, 0x62, 0xd0, 0x00, 0x51, 0x2f,
+ 0x21, 0x7f, 0x53, 0x51, 0x51, 0xaf, 0x3a, 0x51, 0xb0, 0x55, 0x7c, 0x16,
+ 0xe7, 0x62, 0xd0, 0x00, 0x53, 0xb0, 0x3c, 0xb0, 0x0f, 0xa0, 0x3d,
+ 0x3c, 0xab, 0x00, 0xb0, 0x1c, 0x55, 0x94, 0x00, 0x55, 0x95, 0x00,
+ 0x51, 0xb0, 0x53, 0x50, 0x55, 0x51, 0x00, 0x06, 0x50, 0x94, 0x0e,
+ 0x51, 0x00, 0x51, 0x51, 0x60, 0xd5, 0x50, 0x08, 0x3f, 0x50, 0x62,
+ 0xd0, 0x00, 0x55, 0xa7, 0x00, 0x3c, 0xae, 0x00,
+ 0xb0, 0x0a, 0x7c, 0x17, 0x7c, 0x62, 0xd0, 0x00, 0x55, 0xae, 0x01, 0x62,
+ 0xd0, 0x00, 0x55, 0xa6, 0x03, 0x80, 0x0c, 0x62, 0xd0, 0x00, 0x3c,
+ 0xa9, 0x00, 0xb0, 0x04, 0x55, 0xa9, 0x01, 0x7f, 0x62, 0xd0, 0x00,
+ 0x55, 0xa5, 0x00, 0x55, 0xa4, 0x00, 0x3c, 0xae, 0x01, 0xb0, 0x33,
+ 0x7a, 0xa6, 0x3c, 0xa6, 0x00, 0xb0, 0x3a, 0x3c, 0xae, 0x01, 0xb0,
+ 0x0a, 0x7c, 0x18, 0x0f, 0x62, 0xd0, 0x00, 0x55,
+ 0xae, 0x00, 0x62, 0xd0, 0x00, 0x3c, 0xab, 0x00, 0xb0, 0x0e, 0x51, 0xb0,
+ 0x53, 0x50, 0x55, 0x51, 0x00, 0x06, 0x50, 0x94, 0x7c, 0x1d, 0xb9,
+ 0x62, 0xd0, 0x00, 0x55, 0xaf, 0x00, 0x80, 0x0f, 0x62, 0xd0, 0x00,
+ 0x3c, 0xa9, 0x01, 0xb0, 0x07, 0x55, 0xa9, 0x00, 0x55, 0xaf, 0x00,
+ 0x7f, 0x10, 0x4f, 0x38, 0x16, 0x62, 0xd0, 0x00, 0x3c, 0xaa, 0x00,
+ 0xb0, 0x05, 0x51, 0x9c, 0x53, 0x24, 0x56, 0x0d,
+ 0x00, 0x80, 0xff, 0x56, 0x00, 0x00, 0x80, 0xf3, 0x62, 0xd0, 0x00, 0x3c,
+ 0xaa, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x50, 0x55, 0x51, 0x00,
+ 0x06, 0x50, 0x9c, 0x7c, 0x1d, 0x06, 0x52, 0x00, 0x53, 0x4e, 0x55,
+ 0x4f, 0x00, 0x06, 0x4e, 0x24, 0x7c, 0x1d, 0xa1, 0x10, 0x52, 0x00,
+ 0x7c, 0x09, 0x3a, 0x20, 0x10, 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00,
+ 0x20, 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00, 0x00,
+ 0xb0, 0x12, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x55, 0x4c, 0x01, 0x7c,
+ 0x1c, 0x2a, 0x7c, 0x1c, 0x88, 0x80, 0x80, 0x3d, 0x00, 0x01, 0xb0,
+ 0x2a, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x65,
+ 0x4e, 0x6b, 0x4f, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x4f,
+ 0x08, 0x51, 0x4e, 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18,
+ 0x53, 0x4f, 0x38, 0xfe, 0x7c, 0x1c, 0x88, 0x80,
+ 0x52, 0x3d, 0x00, 0x02, 0xb0, 0x21, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60,
+ 0x7c, 0x1c, 0x95, 0x55, 0x4c, 0x03, 0x7c, 0x1c, 0x2a, 0x70, 0xfb,
+ 0x6e, 0x4f, 0x6e, 0x4e, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0x7c,
+ 0x1c, 0x88, 0x80, 0x2d, 0x3d, 0x00, 0x03, 0xb0, 0x28, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x65, 0x4e, 0x6b, 0x4f,
+ 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x4f,
+ 0x08, 0x51, 0x4e, 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18, 0x53,
+ 0x4f, 0x38, 0xfe, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x6c, 0x7c, 0x1c,
+ 0xc1, 0x52, 0x0d, 0x7c, 0x1d, 0xad, 0x02, 0x50, 0x53, 0x50, 0x51,
+ 0x4f, 0x0a, 0x51, 0x53, 0x51, 0x7c, 0x1d, 0x6f, 0x06, 0x4e, 0x8c,
+ 0x0e, 0x4f, 0x00, 0x51, 0x4f, 0x7c, 0x1c, 0xab, 0x7c, 0x1c, 0x88,
+ 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x0a, 0x77,
+ 0x0d, 0x3d, 0x0d, 0x03, 0xce, 0xfe, 0x56, 0x00, 0x00, 0x81, 0x06, 0x7c,
+ 0x1c, 0x6c, 0x7c, 0x1c, 0xc1, 0x51, 0x51, 0x60, 0xd4, 0x3e, 0x50,
+ 0x54, 0x0e, 0x3e, 0x50, 0x54, 0x0f, 0x52, 0x00, 0x53, 0x50, 0x55,
+ 0x51, 0x00, 0x55, 0x4e, 0x06, 0x55, 0x4f, 0x00, 0x55, 0x4b, 0x00,
+ 0x55, 0x4a, 0x00, 0x3c, 0x4f, 0x00, 0xb0, 0x06, 0x3c, 0x4e, 0x00,
+ 0xa0, 0x1a, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e,
+ 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x50, 0x04, 0x4b, 0x51, 0x51, 0x0c,
+ 0x4a, 0x65, 0x50, 0x6b, 0x51, 0x8f, 0xde, 0x5f, 0x50, 0x4b, 0x5f,
+ 0x51, 0x4a, 0x62, 0xd0, 0x00, 0x5a, 0x4e, 0x06, 0x4e, 0x03, 0x51,
+ 0x4e, 0x04, 0x50, 0x0e, 0x51, 0x03, 0x51, 0x51, 0x60, 0xd4, 0x3e,
+ 0x50, 0x54, 0x10, 0x3e, 0x50, 0x54, 0x11, 0x52, 0x00, 0x53, 0x50,
+ 0x55, 0x51, 0x00, 0x55, 0x4e, 0x06, 0x55, 0x4f,
+ 0x00, 0x55, 0x4b, 0x00, 0x55, 0x4a, 0x00, 0x3c, 0x4f, 0x00, 0xb0, 0x06,
+ 0x3c, 0x4e, 0x00, 0xa0, 0x1a, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e,
+ 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x50, 0x04, 0x4b, 0x51, 0x51,
+ 0x0c, 0x4a, 0x65, 0x50, 0x6b, 0x51, 0x8f, 0xde, 0x5f, 0x50, 0x4b,
+ 0x5f, 0x51, 0x4a, 0x62, 0xd0, 0x00, 0x5a, 0x4e, 0x06, 0x4e, 0x05,
+ 0x51, 0x4e, 0x04, 0x50, 0x0e, 0x51, 0x03, 0x51,
+ 0x51, 0x60, 0xd4, 0x3e, 0x50, 0x54, 0x12, 0x3e, 0x50, 0x54, 0x13, 0x50,
+ 0x03, 0x08, 0x5a, 0x50, 0x06, 0x50, 0x0e, 0x08, 0x51, 0x50, 0x08,
+ 0x7c, 0x1a, 0x9f, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51, 0x50, 0x54,
+ 0x15, 0x51, 0x51, 0x54, 0x14, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01,
+ 0x8c, 0x7c, 0x1d, 0x1d, 0x06, 0x50, 0x62, 0x7c, 0x1d, 0x5f, 0x7c,
+ 0x1c, 0x60, 0x51, 0x50, 0x01, 0x6a, 0x7c, 0x1d,
+ 0x1d, 0x51, 0x50, 0x01, 0x72, 0x7c, 0x1d, 0x1d, 0x06, 0x50, 0x7a, 0x7c,
+ 0x1d, 0x5f, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0xf7, 0x38, 0xea,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x16, 0x10, 0x57, 0x09, 0x50, 0x01,
+ 0x7c, 0x08, 0x74, 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x10, 0x08,
+ 0x57, 0x92, 0x28, 0x53, 0x51, 0x18, 0x75, 0x09, 0x00, 0x28, 0x53,
+ 0x50, 0x20, 0x10, 0x51, 0x51, 0x08, 0x51, 0x50,
+ 0x20, 0x7c, 0x09, 0xb9, 0x20, 0x10, 0x57, 0x0e, 0x50, 0x01, 0x7c, 0x08,
+ 0x74, 0x20, 0x62, 0xd0, 0x00, 0x3c, 0xaa, 0x01, 0xb0, 0x0b, 0x51,
+ 0x24, 0x53, 0x30, 0x51, 0x25, 0x53, 0x31, 0x80, 0x0c, 0x62, 0xd0,
+ 0x00, 0x51, 0x9c, 0x53, 0x24, 0x51, 0x9d, 0x53, 0x25, 0x10, 0x50,
+ 0x00, 0x7c, 0x09, 0x3a, 0x20, 0x56, 0x0d, 0x00, 0x80, 0xff, 0x56,
+ 0x00, 0x00, 0x80, 0xf3, 0x62, 0xd0, 0x00, 0x3c,
+ 0xaa, 0x00, 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x50, 0x55, 0x51, 0x00, 0x06,
+ 0x50, 0x9c, 0x7c, 0x1d, 0x06, 0x52, 0x00, 0x53, 0x4e, 0x55, 0x4f,
+ 0x00, 0x06, 0x4e, 0x24, 0x7c, 0x1d, 0xa1, 0x10, 0x52, 0x00, 0x7c,
+ 0x09, 0x3a, 0x20, 0x10, 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00, 0x20,
+ 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00, 0x00, 0xb0, 0x12, 0x7c, 0x1c,
+ 0x60, 0x7c, 0x1c, 0x95, 0x55, 0x4c, 0x01, 0x7c,
+ 0x1c, 0x2a, 0x7c, 0x1c, 0x88, 0x80, 0x80, 0x3d, 0x00, 0x01, 0xb0, 0x2a,
+ 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x65, 0x4e,
+ 0x6b, 0x4f, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x4f, 0x08,
+ 0x51, 0x4e, 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18, 0x53,
+ 0x4f, 0x38, 0xfe, 0x7c, 0x1c, 0x88, 0x80, 0x52, 0x3d, 0x00, 0x02,
+ 0xb0, 0x21, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60,
+ 0x7c, 0x1c, 0x95, 0x55, 0x4c, 0x03, 0x7c, 0x1c, 0x2a, 0x70, 0xfb, 0x6e,
+ 0x4f, 0x6e, 0x4e, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0x7c, 0x1c,
+ 0x88, 0x80, 0x2d, 0x3d, 0x00, 0x03, 0xb0, 0x28, 0x62, 0xd0, 0x00,
+ 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x65, 0x4e, 0x6b, 0x4f, 0x50,
+ 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x4f, 0x08, 0x51, 0x4e, 0x08,
+ 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18, 0x53,
+ 0x4f, 0x38, 0xfe, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x6c, 0x7c, 0x1c, 0xc1,
+ 0x52, 0x0d, 0x7c, 0x1d, 0xad, 0x02, 0x50, 0x53, 0x50, 0x51, 0x4f,
+ 0x0a, 0x51, 0x53, 0x51, 0x7c, 0x1d, 0x6f, 0x06, 0x4e, 0x8c, 0x0e,
+ 0x4f, 0x00, 0x51, 0x4f, 0x7c, 0x1c, 0xab, 0x7c, 0x1c, 0x88, 0x77,
+ 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x0a, 0x77, 0x0d, 0x3d, 0x0d, 0x03,
+ 0xce, 0xfe, 0x56, 0x00, 0x00, 0x81, 0x06, 0x7c,
+ 0x1c, 0x6c, 0x7c, 0x1c, 0xc1, 0x51, 0x51, 0x60, 0xd4, 0x3e, 0x50, 0x54,
+ 0x0e, 0x3e, 0x50, 0x54, 0x0f, 0x52, 0x00, 0x53, 0x50, 0x55, 0x51,
+ 0x00, 0x55, 0x4e, 0x06, 0x55, 0x4f, 0x00, 0x55, 0x4b, 0x00, 0x55,
+ 0x4a, 0x00, 0x3c, 0x4f, 0x00, 0xb0, 0x06, 0x3c, 0x4e, 0x00, 0xa0,
+ 0x1a, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0xd0, 0x0c, 0x62, 0xd0,
+ 0x00, 0x51, 0x50, 0x04, 0x4b, 0x51, 0x51, 0x0c,
+ 0x4a, 0x65, 0x50, 0x6b, 0x51, 0x8f, 0xde, 0x5f, 0x50, 0x4b, 0x5f, 0x51,
+ 0x4a, 0x62, 0xd0, 0x00, 0x5a, 0x4e, 0x06, 0x4e, 0x03, 0x51, 0x4e,
+ 0x04, 0x50, 0x0e, 0x51, 0x03, 0x51, 0x51, 0x60, 0xd4, 0x3e, 0x50,
+ 0x54, 0x10, 0x3e, 0x50, 0x54, 0x11, 0x52, 0x00, 0x53, 0x50, 0x55,
+ 0x51, 0x00, 0x55, 0x4e, 0x06, 0x55, 0x4f, 0x00, 0x55, 0x4b, 0x00,
+ 0x55, 0x4a, 0x00, 0x3c, 0x4f, 0x00, 0xb0, 0x06,
+ 0x3c, 0x4e, 0x00, 0xa0, 0x1a, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0xd0,
+ 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x50, 0x04, 0x4b, 0x51, 0x51, 0x0c,
+ 0x4a, 0x65, 0x50, 0x6b, 0x51, 0x8f, 0xde, 0x5f, 0x50, 0x4b, 0x5f,
+ 0x51, 0x4a, 0x62, 0xd0, 0x00, 0x5a, 0x4e, 0x06, 0x4e, 0x05, 0x51,
+ 0x4e, 0x04, 0x50, 0x0e, 0x51, 0x03, 0x51, 0x51, 0x60, 0xd4, 0x3e,
+ 0x50, 0x54, 0x12, 0x3e, 0x50, 0x54, 0x13, 0x50,
+ 0x03, 0x08, 0x5a, 0x50, 0x06, 0x50, 0x0e, 0x08, 0x51, 0x50, 0x08, 0x7c,
+ 0x1a, 0x9f, 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51, 0x50, 0x54, 0x15,
+ 0x51, 0x51, 0x54, 0x14, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c,
+ 0x7c, 0x1d, 0x1d, 0x06, 0x50, 0x62, 0x7c, 0x1d, 0x5f, 0x7c, 0x1c,
+ 0x60, 0x51, 0x50, 0x01, 0x6a, 0x7c, 0x1d, 0x1d, 0x51, 0x50, 0x01,
+ 0x72, 0x7c, 0x1d, 0x1d, 0x06, 0x50, 0x7a, 0x7c,
+ 0x1d, 0x5f, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0xf7, 0x56, 0x00, 0x00,
+ 0x80, 0x19, 0x7c, 0x1c, 0x6c, 0x06, 0x50, 0x24, 0x7c, 0x1d, 0x06,
+ 0x52, 0x00, 0x53, 0x4e, 0x55, 0x4f, 0x00, 0x06, 0x4e, 0x30, 0x7c,
+ 0x1d, 0xa1, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0xe4, 0x38, 0xea,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x62, 0xd0, 0x00, 0x52, 0xfc,
+ 0x01, 0x02, 0x53, 0x50, 0x52, 0xfb, 0x09, 0x00,
+ 0x7c, 0x1d, 0x12, 0x52, 0xfc, 0x01, 0x04, 0x53, 0x4e, 0x52, 0xfb, 0x7c,
+ 0x1c, 0xb6, 0x12, 0x50, 0x51, 0x4f, 0x1a, 0x51, 0xc0, 0x6f, 0x52,
+ 0xfc, 0x53, 0x50, 0x52, 0xfb, 0x7c, 0x1d, 0x12, 0x52, 0xfc, 0x01,
+ 0x02, 0x53, 0x4e, 0x52, 0xfb, 0x7c, 0x1c, 0xb6, 0x12, 0x50, 0x51,
+ 0x4f, 0x1a, 0x51, 0xc0, 0x10, 0x52, 0xfc, 0x01, 0x02, 0x7c, 0x1d,
+ 0x3b, 0x54, 0x00, 0x3e, 0x50, 0x54, 0x01, 0x80,
+ 0xb3, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x01, 0x04, 0x53, 0x50, 0x52, 0xfb,
+ 0x09, 0x00, 0x7c, 0x1d, 0x12, 0x52, 0xfc, 0x53, 0x4e, 0x52, 0xfb,
+ 0x60, 0xd4, 0x3e, 0x4e, 0x53, 0x4f, 0x3e, 0x4e, 0x12, 0x50, 0x51,
+ 0x4f, 0x1a, 0x51, 0xc0, 0x10, 0x52, 0xfc, 0x01, 0x04, 0x7c, 0x1d,
+ 0x3b, 0x54, 0x00, 0x3e, 0x50, 0x54, 0x01, 0x80, 0x7e, 0x62, 0xd0,
+ 0x00, 0x52, 0xfc, 0x53, 0x50, 0x52, 0xfb, 0x7c,
+ 0x1d, 0x54, 0x80, 0x70, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53, 0x50, 0x52,
+ 0xfb, 0x7c, 0x1d, 0x12, 0x52, 0xfc, 0x01, 0x04, 0x53, 0x4e, 0x52,
+ 0xfb, 0x7c, 0x1c, 0xb6, 0x12, 0x50, 0x51, 0x4f, 0x1a, 0x51, 0xc0,
+ 0x10, 0x52, 0xfc, 0x01, 0x04, 0x7c, 0x1d, 0x3b, 0x54, 0x00, 0x3e,
+ 0x50, 0x54, 0x01, 0x80, 0x42, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x01,
+ 0x02, 0x53, 0x50, 0x52, 0xfb, 0x09, 0x00, 0x7c,
+ 0x1d, 0x12, 0x52, 0xfc, 0x53, 0x4e, 0x52, 0xfb, 0x60, 0xd4, 0x3e, 0x4e,
+ 0x53, 0x4f, 0x3e, 0x4e, 0x12, 0x50, 0x51, 0x4f, 0x1a, 0x51, 0xc0,
+ 0x10, 0x52, 0xfc, 0x01, 0x02, 0x7c, 0x1d, 0x3b, 0x54, 0x00, 0x3e,
+ 0x50, 0x54, 0x01, 0x80, 0x0d, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53,
+ 0x50, 0x52, 0xfb, 0x7c, 0x1d, 0x54, 0x62, 0xd0, 0x00, 0x52, 0x01,
+ 0x53, 0x50, 0x52, 0x00, 0x53, 0x51, 0x38, 0xfe,
+ 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x05, 0x62, 0xd0, 0x00, 0x55, 0xb2, 0x00,
+ 0x56, 0x00, 0x00, 0x80, 0xcd, 0x62, 0xd0, 0x00, 0x3c, 0xaa, 0x00,
+ 0xb0, 0x1b, 0x52, 0x00, 0x53, 0x50, 0x55, 0x51, 0x00, 0x06, 0x50,
+ 0x9c, 0x7c, 0x1d, 0x06, 0x52, 0x00, 0x53, 0x4e, 0x55, 0x4f, 0x00,
+ 0x06, 0x4e, 0x24, 0x7c, 0x1d, 0xa1, 0x10, 0x52, 0x00, 0x7c, 0x09,
+ 0x3a, 0x20, 0x10, 0x7c, 0x05, 0xc5, 0x62, 0xd0,
+ 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee, 0x3d, 0x00, 0x00, 0xb0, 0x12, 0x7c,
+ 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x55, 0x4c, 0x01, 0x7c, 0x1c, 0x2a,
+ 0x7c, 0x1c, 0x88, 0x80, 0x80, 0x3d, 0x00, 0x01, 0xb0, 0x2a, 0x62,
+ 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x65, 0x4e, 0x6b,
+ 0x4f, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x4f, 0x08, 0x51,
+ 0x4e, 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e,
+ 0x18, 0x53, 0x4f, 0x38, 0xfe, 0x7c, 0x1c, 0x88, 0x80, 0x52, 0x3d, 0x00,
+ 0x02, 0xb0, 0x21, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x7c, 0x1c,
+ 0x95, 0x55, 0x4c, 0x03, 0x7c, 0x1c, 0x2a, 0x70, 0xfb, 0x6e, 0x4f,
+ 0x6e, 0x4e, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0x7c, 0x1c, 0x88,
+ 0x80, 0x2d, 0x3d, 0x00, 0x03, 0xb0, 0x28, 0x62, 0xd0, 0x00, 0x7c,
+ 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x65, 0x4e, 0x6b,
+ 0x4f, 0x50, 0x00, 0x08, 0x50, 0x05, 0x08, 0x51, 0x4f, 0x08, 0x51, 0x4e,
+ 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18, 0x53, 0x4f, 0x38,
+ 0xfe, 0x7c, 0x1c, 0x88, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0x30,
+ 0x56, 0x00, 0x00, 0x82, 0x86, 0x62, 0xd0, 0x00, 0x3c, 0xb1, 0x02,
+ 0xa0, 0x9f, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x62, 0x7c, 0x1c,
+ 0x77, 0x06, 0x50, 0x8c, 0x7c, 0x1d, 0x06, 0x7c,
+ 0x1d, 0x2e, 0xd0, 0x16, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x62, 0x7c,
+ 0x1c, 0x77, 0x06, 0x50, 0x8c, 0x7c, 0x1d, 0x06, 0x7c, 0x1d, 0xd2,
+ 0x80, 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01,
+ 0x8c, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x62, 0x7c, 0x1d, 0x06, 0x7c,
+ 0x1d, 0xd2, 0x50, 0x90, 0x13, 0x02, 0x50, 0x01, 0x1b, 0x01, 0xc0,
+ 0x4e, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x51,
+ 0x50, 0x01, 0x7a, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x8c, 0x7c, 0x1d, 0x06,
+ 0x7c, 0x1d, 0x2e, 0xd0, 0x16, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01,
+ 0x7a, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x8c, 0x7c, 0x1d, 0x06, 0x7c,
+ 0x1d, 0xc5, 0x80, 0x17, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x51,
+ 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x7a, 0x7c, 0x1d,
+ 0x06, 0x7c, 0x1d, 0xc5, 0x50, 0x90, 0x13, 0x04,
+ 0x50, 0x01, 0x1b, 0x03, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x76, 0xb2, 0x81,
+ 0xde, 0x62, 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c,
+ 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x7a, 0x7c, 0x1d, 0x06, 0x7c, 0x1d,
+ 0x2e, 0xd0, 0x5a, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x06, 0x4e,
+ 0x01, 0x0e, 0x4f, 0x00, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x60, 0x51,
+ 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77, 0x06, 0x50,
+ 0x7a, 0x7c, 0x1d, 0x06, 0x7c, 0x1d, 0x2e, 0xd0, 0xb4, 0x7c, 0x1c, 0x60,
+ 0x7c, 0x1c, 0x95, 0x06, 0x4e, 0x01, 0x0e, 0x4f, 0x00, 0x7c, 0x1c,
+ 0x88, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77,
+ 0x06, 0x50, 0x7a, 0x7c, 0x1d, 0x06, 0x7c, 0x1d, 0x2e, 0xd0, 0x90,
+ 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x06, 0x4e, 0x01, 0x0e, 0x4f,
+ 0x00, 0x7c, 0x1c, 0x88, 0x80, 0x7f, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77, 0x06,
+ 0x50, 0x7a, 0x7c, 0x1d, 0x06, 0x3e, 0x50, 0x12, 0x4e, 0x51, 0x51,
+ 0x1a, 0x4f, 0xd0, 0x62, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x16,
+ 0x4e, 0x01, 0x1e, 0x4f, 0x00, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x60,
+ 0x51, 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x7a, 0x7c,
+ 0x1d, 0x06, 0x3e, 0x50, 0x12, 0x4e, 0x51, 0x51,
+ 0x1a, 0x4f, 0xd0, 0x39, 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x16, 0x4e,
+ 0x01, 0x1e, 0x4f, 0x00, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x60, 0x51,
+ 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x7a, 0x7c, 0x1d,
+ 0x06, 0x3e, 0x50, 0x12, 0x4e, 0x51, 0x51, 0x1a, 0x4f, 0xd0, 0x10,
+ 0x7c, 0x1c, 0x60, 0x7c, 0x1c, 0x95, 0x16, 0x4e, 0x01, 0x1e, 0x4f,
+ 0x00, 0x7c, 0x1c, 0x88, 0x62, 0xd0, 0x00, 0x7c,
+ 0x1c, 0x60, 0x51, 0x50, 0x01, 0x72, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x6a,
+ 0x0e, 0x51, 0x00, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x60, 0x51, 0x50,
+ 0x01, 0x7a, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x72, 0x0e, 0x51, 0x00,
+ 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c, 0x7c,
+ 0x1c, 0x77, 0x06, 0x50, 0x7a, 0x0e, 0x51, 0x00, 0x7c, 0x1c, 0x88,
+ 0x10, 0x52, 0x00, 0x7c, 0x06, 0x09, 0x20, 0x62,
+ 0xd0, 0x00, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77,
+ 0x06, 0x50, 0x62, 0x7c, 0x1d, 0x06, 0x7c, 0x1d, 0x2e, 0xd0, 0x25,
+ 0x52, 0x00, 0x53, 0x50, 0x55, 0x51, 0x00, 0x06, 0x50, 0x98, 0x0e,
+ 0x51, 0x00, 0x51, 0x51, 0x60, 0xd4, 0x3e, 0x50, 0x7a, 0x50, 0x53,
+ 0x4f, 0x06, 0x4f, 0x01, 0x51, 0x51, 0x60, 0xd5, 0x51, 0x4f, 0x3f,
+ 0x50, 0x80, 0x0a, 0x7c, 0x1c, 0x6c, 0x06, 0x50,
+ 0x98, 0x7c, 0x1d, 0xb9, 0x7c, 0x1c, 0x6c, 0x06, 0x50, 0x98, 0x7c, 0x1d,
+ 0x06, 0x50, 0x05, 0x3a, 0x51, 0xd0, 0x58, 0x7c, 0x1c, 0x60, 0x51,
+ 0x50, 0x01, 0x62, 0x53, 0x4e, 0x51, 0x51, 0x09, 0x00, 0x53, 0x4f,
+ 0x06, 0x50, 0x8c, 0x7c, 0x1d, 0x06, 0x3e, 0x50, 0x53, 0x50, 0x51,
+ 0x4f, 0x60, 0xd4, 0x3e, 0x4e, 0x53, 0x4d, 0x3e, 0x4e, 0x16, 0x4e,
+ 0x02, 0x02, 0x50, 0x53, 0x50, 0x51, 0x4d, 0x0a,
+ 0x51, 0x53, 0x51, 0x70, 0xfb, 0x6e, 0x51, 0x6e, 0x50, 0x51, 0x4f, 0x60,
+ 0xd5, 0x51, 0x51, 0x3f, 0x4e, 0x51, 0x50, 0x3f, 0x4e, 0x52, 0x00,
+ 0x53, 0x50, 0x55, 0x51, 0x00, 0x06, 0x50, 0x98, 0x0e, 0x51, 0x00,
+ 0x51, 0x51, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x50, 0x77, 0x00, 0x3d,
+ 0x00, 0x02, 0xcd, 0x77, 0x62, 0xd0, 0x00, 0x3c, 0xb1, 0x02, 0xb2,
+ 0x20, 0x56, 0x00, 0x00, 0x82, 0x16, 0x62, 0xd0,
+ 0x00, 0x7c, 0x1c, 0x60, 0x51, 0x50, 0x01, 0x8c, 0x7c, 0x1c, 0x77, 0x06,
+ 0x50, 0x38, 0x0e, 0x51, 0x00, 0x7c, 0x1c, 0x88, 0x7c, 0x1c, 0x60,
+ 0x51, 0x50, 0x01, 0x62, 0x7c, 0x1c, 0x77, 0x06, 0x50, 0x3c, 0x0e,
+ 0x51, 0x00, 0x7c, 0x1c, 0x88, 0x97, 0xf7, 0x40, 0x51, 0x50, 0x01,
+ 0x62, 0x7c, 0x1c, 0x77, 0x51, 0x50, 0x01, 0x8c, 0x53, 0x4c, 0x51,
+ 0x51, 0x7c, 0x1d, 0x7b, 0x51, 0x4e, 0x12, 0x4c,
+ 0x51, 0x4f, 0x1a, 0x4d, 0xd0, 0x21, 0x7c, 0x1d, 0x6f, 0x51, 0x4e, 0x01,
+ 0x62, 0x53, 0x4c, 0x51, 0x4f, 0x7c, 0x1d, 0x7b, 0x06, 0x4e, 0x8c,
+ 0x7c, 0x1d, 0x46, 0x12, 0x4c, 0x54, 0x02, 0x51, 0x4f, 0x1a, 0x4d,
+ 0x54, 0x01, 0x80, 0x07, 0x56, 0x02, 0x00, 0x56, 0x01, 0x00, 0x62,
+ 0xd0, 0x00, 0x06, 0x50, 0x34, 0x0e, 0x51, 0x00, 0x51, 0x51, 0x60,
+ 0xd5, 0x52, 0x01, 0x3f, 0x50, 0x52, 0x02, 0x3f,
+ 0x50, 0x3d, 0x00, 0x00, 0xb0, 0x35, 0x97, 0x98, 0x40, 0x51, 0x50, 0x01,
+ 0x8c, 0x97, 0xa8, 0x40, 0x55, 0x4c, 0x01, 0x97, 0x55, 0x40, 0x06,
+ 0x50, 0x38, 0x0e, 0x51, 0x00, 0x97, 0xaa, 0x40, 0x97, 0x7f, 0x40,
+ 0x51, 0x50, 0x01, 0x62, 0x97, 0x8f, 0x40, 0x55, 0x4c, 0x01, 0x97,
+ 0x3c, 0x40, 0x06, 0x50, 0x3c, 0x0e, 0x51, 0x00, 0x97, 0x91, 0x40,
+ 0x80, 0xfb, 0x3d, 0x00, 0x01, 0xb0, 0x44, 0x62,
+ 0xd0, 0x00, 0x97, 0x5c, 0x40, 0x51, 0x50, 0x01, 0x8c, 0x97, 0x6c, 0x40,
+ 0x55, 0x4c, 0x05, 0x97, 0x19, 0x40, 0x70, 0xfb, 0x6e, 0x4f, 0x6e,
+ 0x4e, 0x06, 0x50, 0x38, 0x0e, 0x51, 0x00, 0x97, 0x68, 0x40, 0x97,
+ 0x3d, 0x40, 0x51, 0x50, 0x01, 0x62, 0x97, 0x4d, 0x40, 0x55, 0x4c,
+ 0x05, 0x96, 0xfa, 0x40, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0x06,
+ 0x50, 0x3c, 0x0e, 0x51, 0x00, 0x97, 0x49, 0x40,
+ 0x80, 0xb3, 0x3d, 0x00, 0x02, 0xb0, 0x68, 0x62, 0xd0, 0x00, 0x97, 0x14,
+ 0x40, 0x51, 0x50, 0x01, 0x8c, 0x97, 0x24, 0x40, 0x55, 0x4c, 0x03,
+ 0x96, 0xd1, 0x40, 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x51, 0x4f,
+ 0x08, 0x51, 0x4e, 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18,
+ 0x53, 0x4f, 0x38, 0xfe, 0x06, 0x50, 0x38, 0x0e, 0x51, 0x00, 0x97,
+ 0x0f, 0x40, 0x96, 0xe4, 0x40, 0x51, 0x50, 0x01,
+ 0x62, 0x96, 0xf4, 0x40, 0x65, 0x4e, 0x6b, 0x4f, 0x65, 0x4e, 0x6b, 0x4f,
+ 0x50, 0x00, 0x08, 0x50, 0x03, 0x08, 0x51, 0x4f, 0x08, 0x51, 0x4e,
+ 0x08, 0x7c, 0x1b, 0xe6, 0x18, 0x53, 0x4e, 0x18, 0x53, 0x4f, 0x38,
+ 0xfe, 0x06, 0x50, 0x3c, 0x0e, 0x51, 0x00, 0x96, 0xdd, 0x40, 0x80,
+ 0x47, 0x3d, 0x00, 0x03, 0xb0, 0x42, 0x62, 0xd0, 0x00, 0x96, 0xa8,
+ 0x40, 0x51, 0x50, 0x01, 0x8c, 0x96, 0xb8, 0x40,
+ 0x55, 0x4c, 0x05, 0x96, 0x65, 0x40, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e,
+ 0x06, 0x50, 0x38, 0x0e, 0x51, 0x00, 0x96, 0xb4, 0x40, 0x96, 0x89,
+ 0x40, 0x51, 0x50, 0x01, 0x62, 0x96, 0x99, 0x40, 0x55, 0x4c, 0x05,
+ 0x96, 0x46, 0x40, 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0x06, 0x50,
+ 0x3c, 0x0e, 0x51, 0x00, 0x96, 0x95, 0x40, 0x62, 0xd0, 0x00, 0x96,
+ 0x67, 0x40, 0x51, 0x50, 0x01, 0x62, 0x96, 0x77,
+ 0x40, 0x51, 0x50, 0x01, 0x8c, 0x53, 0x4c, 0x51, 0x51, 0x97, 0x70, 0x40,
+ 0x51, 0x4e, 0x12, 0x4c, 0x51, 0x4f, 0x1a, 0x4d, 0xd0, 0x21, 0x97,
+ 0x57, 0x40, 0x51, 0x4e, 0x01, 0x62, 0x53, 0x4c, 0x51, 0x4f, 0x97,
+ 0x58, 0x40, 0x06, 0x4e, 0x8c, 0x97, 0x1d, 0x40, 0x12, 0x4c, 0x54,
+ 0x04, 0x51, 0x4f, 0x1a, 0x4d, 0x54, 0x03, 0x80, 0x07, 0x56, 0x04,
+ 0x00, 0x56, 0x03, 0x00, 0x62, 0xd0, 0x00, 0x06,
+ 0x50, 0x34, 0x0e, 0x51, 0x00, 0x51, 0x51, 0x60, 0xd5, 0x52, 0x03, 0x3f,
+ 0x50, 0x52, 0x04, 0x3f, 0x50, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcd,
+ 0xe7, 0x62, 0xd0, 0x00, 0x3c, 0xb1, 0x02, 0xa0, 0x18, 0x3c, 0xb2,
+ 0x00, 0xa0, 0x13, 0x50, 0x01, 0x08, 0x50, 0x2c, 0x08, 0x90, 0x0e,
+ 0x38, 0xfe, 0x7c, 0x0a, 0xee, 0x10, 0x7c, 0x07, 0xc5, 0x20, 0x38,
+ 0xfb, 0x20, 0x7f, 0x10, 0x4f, 0x80, 0x02, 0x40,
+ 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53, 0x50, 0x52, 0xfb, 0x53, 0x51, 0x51,
+ 0x50, 0x11, 0x01, 0x54, 0xfc, 0x51, 0x51, 0x19, 0x00, 0x54, 0xfb,
+ 0x3c, 0x51, 0x00, 0xbf, 0xe4, 0x3c, 0x50, 0x00, 0xbf, 0xdf, 0x20,
+ 0x7f, 0x10, 0x7c, 0x04, 0x8f, 0x7c, 0x04, 0x6c, 0x20, 0x7f, 0x10,
+ 0x7c, 0x04, 0x8b, 0x7c, 0x04, 0x68, 0x20, 0x7f, 0x62, 0xd0, 0x00,
+ 0x51, 0x42, 0x12, 0x67, 0x50, 0x00, 0x1a, 0x66,
+ 0xd0, 0x0f, 0x51, 0x43, 0x12, 0x69, 0x50, 0x00, 0x1a, 0x68, 0xd0, 0x05,
+ 0x50, 0x0f, 0x80, 0x17, 0x62, 0xd0, 0x00, 0x51, 0x69, 0x12, 0x67,
+ 0x51, 0x68, 0x1a, 0x66, 0xd0, 0x05, 0x50, 0x00, 0x80, 0x06, 0x62,
+ 0xd0, 0x00, 0x50, 0x01, 0x7f, 0x10, 0x4f, 0x38, 0x05, 0x62, 0xd0,
+ 0x00, 0x51, 0x67, 0x54, 0x02, 0x51, 0x66, 0x54, 0x01, 0x56, 0x04,
+ 0x00, 0x56, 0x00, 0x00, 0x56, 0x03, 0x00, 0x80,
+ 0x61, 0x95, 0x69, 0x40, 0x06, 0x50, 0x42, 0x0e, 0x51, 0x00, 0x51, 0x51,
+ 0x60, 0xd4, 0x3e, 0x50, 0x53, 0x50, 0x96, 0x5b, 0x40, 0x06, 0x4e,
+ 0x66, 0x0e, 0x4f, 0x00, 0x51, 0x4f, 0x95, 0x8c, 0x40, 0x51, 0x50,
+ 0x12, 0x4e, 0x50, 0x00, 0x1a, 0x4f, 0xd0, 0x03, 0x77, 0x03, 0x62,
+ 0xd0, 0x00, 0x95, 0x2f, 0x40, 0x06, 0x50, 0x66, 0x95, 0xcf, 0x40,
+ 0x3e, 0x50, 0x53, 0x50, 0x52, 0x02, 0x12, 0x50,
+ 0x52, 0x01, 0x1a, 0x51, 0xd0, 0x1a, 0x95, 0x18, 0x40, 0x06, 0x50, 0x66,
+ 0x0e, 0x51, 0x00, 0x51, 0x51, 0x60, 0xd4, 0x3e, 0x50, 0x54, 0x01,
+ 0x3e, 0x50, 0x54, 0x02, 0x52, 0x00, 0x54, 0x04, 0x77, 0x00, 0x3d,
+ 0x00, 0x02, 0xcf, 0x9c, 0x50, 0x01, 0x3b, 0x03, 0xd0, 0x08, 0x62,
+ 0xd0, 0x00, 0x50, 0x0f, 0x80, 0x06, 0x52, 0x04, 0x62, 0xd0, 0x00,
+ 0x38, 0xfb, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02,
+ 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x26, 0x2a, 0xf0, 0x51, 0xb0, 0x01, 0x01,
+ 0x53, 0x51, 0x51, 0x2a, 0x2a, 0x51, 0x53, 0x2a, 0x71, 0x01, 0x62,
+ 0xe3, 0x38, 0x10, 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00, 0x20, 0x41,
+ 0x00, 0xf7, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21, 0x10,
+ 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x51, 0x47, 0x51,
+ 0x20, 0xa0, 0x03, 0x80, 0x1a, 0x50, 0x00, 0x08,
+ 0x50, 0x04, 0x08, 0x9e, 0xb6, 0x38, 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00,
+ 0x52, 0x01, 0x11, 0xdc, 0x52, 0x00, 0x19, 0x05, 0xcf, 0xd7, 0x56,
+ 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21, 0x10, 0x7c, 0x05, 0xc5,
+ 0x62, 0xd0, 0x00, 0x20, 0x53, 0x51, 0x47, 0x51, 0x20, 0xb0, 0x03,
+ 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x04, 0x08, 0x9e, 0x84, 0x38,
+ 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01,
+ 0x11, 0x2c, 0x52, 0x00, 0x19, 0x01, 0xcf, 0xd7, 0x43, 0x00, 0x08, 0x38,
+ 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x02, 0x70, 0xfe, 0x62, 0xd0,
+ 0x00, 0x26, 0x2a, 0xf0, 0x51, 0xb0, 0x01, 0x09, 0x53, 0x51, 0x51,
+ 0x2a, 0x2a, 0x51, 0x53, 0x2a, 0x71, 0x01, 0x62, 0xe3, 0x38, 0x10,
+ 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56,
+ 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x21, 0x10,
+ 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x51, 0x47, 0x51, 0x20,
+ 0xa0, 0x03, 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x04, 0x08, 0x9e,
+ 0x23, 0x38, 0xfe, 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01, 0x11,
+ 0xdc, 0x52, 0x00, 0x19, 0x05, 0xcf, 0xd7, 0x56, 0x01, 0x00, 0x56,
+ 0x00, 0x00, 0x80, 0x21, 0x10, 0x7c, 0x05, 0xc5, 0x62, 0xd0, 0x00,
+ 0x20, 0x53, 0x51, 0x47, 0x51, 0x20, 0xb0, 0x03,
+ 0x80, 0x1a, 0x50, 0x00, 0x08, 0x50, 0x04, 0x08, 0x9d, 0xf1, 0x38, 0xfe,
+ 0x77, 0x01, 0x0f, 0x00, 0x00, 0x52, 0x01, 0x11, 0x2c, 0x52, 0x00,
+ 0x19, 0x01, 0xcf, 0xd7, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f,
+ 0x10, 0x4f, 0x38, 0x04, 0x62, 0xd0, 0x00, 0x51, 0x2a, 0x21, 0xf0,
+ 0x54, 0x00, 0x51, 0x2d, 0x54, 0x01, 0x3d, 0x00, 0x10, 0xb0, 0x2a,
+ 0x55, 0xa7, 0x00, 0x3c, 0xab, 0x01, 0xb0, 0x09,
+ 0x55, 0x94, 0x00, 0x55, 0x95, 0x00, 0x80, 0x0f, 0x62, 0xd0, 0x00, 0x3c,
+ 0xae, 0x01, 0xa0, 0x07, 0x55, 0x94, 0x00, 0x55, 0x95, 0x00, 0x56,
+ 0x00, 0x00, 0x62, 0xd0, 0x00, 0x26, 0x2a, 0x0f, 0x81, 0x76, 0x3d,
+ 0x00, 0x20, 0xb0, 0x18, 0x62, 0xd0, 0x00, 0x55, 0xa7, 0x01, 0x55,
+ 0xa8, 0x00, 0x55, 0x94, 0x08, 0x55, 0x95, 0x08, 0x56, 0x00, 0x00,
+ 0x26, 0x2a, 0x0f, 0x81, 0x5a, 0x3d, 0x00, 0x30,
+ 0xb0, 0x0f, 0x62, 0xd0, 0x00, 0x55, 0xb1, 0x00, 0x56, 0x00, 0x00, 0x26,
+ 0x2a, 0x0f, 0x81, 0x47, 0x3d, 0x00, 0x40, 0xb0, 0x0f, 0x62, 0xd0,
+ 0x00, 0x55, 0xb1, 0x02, 0x56, 0x00, 0x00, 0x26, 0x2a, 0x0f, 0x81,
+ 0x34, 0x3d, 0x00, 0x50, 0xb0, 0xa7, 0x52, 0x01, 0x54, 0x03, 0x56,
+ 0x02, 0x00, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x01, 0xa0,
+ 0x21, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03,
+ 0x02, 0xa0, 0x28, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x04, 0xa0,
+ 0x36, 0x3d, 0x02, 0x00, 0xb0, 0x06, 0x3d, 0x03, 0x08, 0xa0, 0x48,
+ 0x80, 0x62, 0x62, 0xd0, 0x00, 0x55, 0xaa, 0x01, 0x51, 0x2f, 0x29,
+ 0x80, 0x53, 0x2f, 0x7c, 0x0d, 0x19, 0x80, 0x51, 0x62, 0xd0, 0x00,
+ 0x51, 0x2b, 0x53, 0x42, 0x51, 0x2b, 0x53, 0x43, 0x51, 0x2b, 0x53,
+ 0x2e, 0x51, 0x2c, 0x53, 0x0e, 0x55, 0x0d, 0x00,
+ 0x80, 0x39, 0x62, 0xd0, 0x00, 0x51, 0x2b, 0x53, 0x2f, 0x3c, 0xaa, 0x00,
+ 0xa0, 0x09, 0x51, 0x2f, 0x29, 0x80, 0x53, 0x2f, 0x80, 0x25, 0x62,
+ 0xd0, 0x00, 0x26, 0x2f, 0x7f, 0x80, 0x1d, 0x62, 0xd0, 0x00, 0x55,
+ 0xaa, 0x00, 0x26, 0x2f, 0x7f, 0x51, 0x9c, 0x53, 0x24, 0x51, 0x24,
+ 0x53, 0x30, 0x51, 0x9d, 0x53, 0x25, 0x51, 0x25, 0x53, 0x31, 0x7c,
+ 0x0d, 0x19, 0x56, 0x00, 0x00, 0x62, 0xd0, 0x00,
+ 0x26, 0x2a, 0x0f, 0x55, 0x2b, 0x11, 0x55, 0x2c, 0x08, 0x55, 0x2d, 0x00,
+ 0x80, 0x89, 0x3d, 0x00, 0x60, 0xb0, 0x0f, 0x62, 0xd0, 0x00, 0x55,
+ 0xab, 0x01, 0x56, 0x00, 0x00, 0x26, 0x2a, 0x0f, 0x80, 0x76, 0x3d,
+ 0x00, 0x70, 0xb0, 0x0f, 0x62, 0xd0, 0x00, 0x55, 0xab, 0x00, 0x56,
+ 0x00, 0x00, 0x26, 0x2a, 0x0f, 0x80, 0x63, 0x3d, 0x00, 0x80, 0xb0,
+ 0x5e, 0x56, 0x00, 0x00, 0x62, 0xd0, 0x00, 0x26,
+ 0x2a, 0x0f, 0x9c, 0x9f, 0x10, 0x7c, 0x08, 0xb8, 0x7c, 0x05, 0xdb, 0x20,
+ 0x70, 0xfe, 0x93, 0xcf, 0x40, 0x62, 0xda, 0x00, 0x71, 0x10, 0x41,
+ 0xdc, 0xfe, 0x70, 0xcf, 0x43, 0x01, 0x08, 0x43, 0x00, 0x08, 0x50,
+ 0x00, 0x08, 0x50, 0x1e, 0x08, 0x9c, 0x52, 0x38, 0xfe, 0x71, 0x01,
+ 0x43, 0xe0, 0x10, 0x43, 0xff, 0x08, 0x70, 0xfe, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x10, 0x7c, 0x07, 0xe7,
+ 0x7c, 0x05, 0x8f, 0x7c, 0x05, 0xd0, 0x20, 0x93, 0x3f, 0x40, 0x62, 0xe3,
+ 0x38, 0x56, 0x00, 0x00, 0x62, 0xd0, 0x00, 0x26, 0x2a, 0x0f, 0x38,
+ 0xfc, 0x20, 0x7f, 0x62, 0xd0, 0x00, 0x3c, 0xa7, 0x00, 0xa0, 0x13,
+ 0x9c, 0x3f, 0x62, 0xd0, 0x00, 0x3c, 0xa8, 0x00, 0xb0, 0x33, 0x55,
+ 0xa8, 0x01, 0x7c, 0x0a, 0xee, 0x80, 0x2b, 0x62, 0xd0, 0x00, 0x50,
+ 0x01, 0x3a, 0x94, 0xd0, 0x08, 0x10, 0x7c, 0x04,
+ 0x8f, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0x8b, 0x20, 0x62, 0xd0, 0x00,
+ 0x50, 0x01, 0x3a, 0x95, 0xd0, 0x08, 0x10, 0x7c, 0x04, 0x6c, 0x20,
+ 0x80, 0x06, 0x10, 0x7c, 0x04, 0x68, 0x20, 0x7f, 0x10, 0x4f, 0x38,
+ 0x03, 0x56, 0x02, 0x00, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80,
+ 0x3e, 0x62, 0xd0, 0x00, 0x91, 0xad, 0x40, 0x52, 0xfc, 0x04, 0x50,
+ 0x52, 0xfb, 0x0c, 0x51, 0x51, 0x51, 0x60, 0xd4,
+ 0x3e, 0x50, 0x53, 0x51, 0x3e, 0x50, 0x53, 0x50, 0x52, 0x02, 0x12, 0x50,
+ 0x52, 0x01, 0x1a, 0x51, 0xd0, 0x18, 0x91, 0x8c, 0x40, 0x52, 0xfc,
+ 0x04, 0x50, 0x52, 0xfb, 0x0c, 0x51, 0x51, 0x51, 0x60, 0xd4, 0x3e,
+ 0x50, 0x54, 0x01, 0x3e, 0x50, 0x54, 0x02, 0x77, 0x00, 0x52, 0x00,
+ 0x3b, 0xfa, 0xcf, 0xbe, 0x62, 0xd0, 0x00, 0x52, 0x02, 0x53, 0x50,
+ 0x52, 0x01, 0x53, 0x51, 0x38, 0xfd, 0x20, 0x7f,
+ 0x10, 0x7c, 0x04, 0x1a, 0x20, 0x10, 0x50, 0x04, 0x08, 0x50, 0x00, 0x08,
+ 0x50, 0x8c, 0x08, 0x7c, 0x04, 0x23, 0x38, 0xfd, 0x20, 0x10, 0x50,
+ 0x04, 0x08, 0x50, 0x00, 0x08, 0x50, 0x62, 0x08, 0x7c, 0x04, 0x23,
+ 0x38, 0xfd, 0x20, 0x10, 0x50, 0x04, 0x08, 0x50, 0x00, 0x08, 0x50,
+ 0x66, 0x08, 0x7c, 0x04, 0x23, 0x38, 0xfd, 0x20, 0x10, 0x50, 0x00,
+ 0x7c, 0x03, 0x3e, 0x20, 0x10, 0x50, 0xff, 0x7c,
+ 0x03, 0x3e, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x3e, 0x20, 0x7f, 0x62,
+ 0xd0, 0x00, 0x55, 0xaa, 0x00, 0x55, 0xab, 0x01, 0x10, 0x7c, 0x04,
+ 0x8f, 0x7c, 0x04, 0x6c, 0x20, 0x9b, 0x45, 0x62, 0xe3, 0x38, 0x92,
+ 0x7c, 0x40, 0x43, 0x00, 0x08, 0x62, 0xd0, 0x00, 0x55, 0x2a, 0x08,
+ 0x55, 0x2b, 0x11, 0x55, 0x2c, 0x08, 0x55, 0x2e, 0x1e, 0x55, 0x2f,
+ 0x03, 0x55, 0x30, 0x5f, 0x55, 0x31, 0x28, 0x55,
+ 0x32, 0x00, 0x55, 0x33, 0x00, 0x3c, 0xaa, 0x00, 0xa0, 0x09, 0x51, 0x2f,
+ 0x29, 0x80, 0x53, 0x2f, 0x80, 0x07, 0x62, 0xd0, 0x00, 0x26, 0x2f,
+ 0x7f, 0x10, 0x50, 0x00, 0x08, 0x50, 0x2a, 0x08, 0x50, 0x06, 0x08,
+ 0x50, 0x16, 0x08, 0x7c, 0x05, 0xe2, 0x38, 0xfc, 0x7c, 0x05, 0x8f,
+ 0x7c, 0x05, 0xd0, 0x20, 0x91, 0xd5, 0x40, 0x10, 0x7c, 0x07, 0xe7,
+ 0x7c, 0x07, 0x6d, 0x20, 0x7c, 0x0d, 0x19, 0x80,
+ 0x22, 0x62, 0xe3, 0x38, 0x7c, 0x10, 0xc2, 0x10, 0x7c, 0x07, 0xab, 0x62,
+ 0xd0, 0x00, 0x20, 0x39, 0x00, 0xa0, 0x09, 0x7c, 0x0a, 0x07, 0x7c,
+ 0x0a, 0x31, 0x80, 0x04, 0x7c, 0x0a, 0x9f, 0x9c, 0xc2, 0x9e, 0x78,
+ 0x8f, 0xde, 0x8f, 0xff, 0x10, 0x4f, 0x7c, 0x1b, 0xf1, 0x20, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50,
+ 0x00, 0x53, 0x4a, 0x53, 0x4b, 0x55, 0x49, 0x10,
+ 0x66, 0xfc, 0x6c, 0xfb, 0x6b, 0x4a, 0x6b, 0x4b, 0x51, 0x4a, 0x1b, 0xfa,
+ 0x51, 0x4b, 0x1b, 0xf9, 0xc0, 0x09, 0x53, 0x4b, 0x52, 0xfa, 0x1c,
+ 0x4a, 0x77, 0xfc, 0x7a, 0x49, 0xbf, 0xe3, 0x51, 0x4a, 0x54, 0xfa,
+ 0x51, 0x4b, 0x54, 0xf9, 0x18, 0x60, 0xd0, 0x7f, 0x55, 0x4d, 0x00,
+ 0x55, 0x4b, 0x00, 0x55, 0x4a, 0x00, 0x3c, 0x4d, 0x00, 0xb0, 0x06,
+ 0x3c, 0x4c, 0x00, 0xa0, 0x1a, 0x70, 0xfb, 0x6e,
+ 0x4d, 0x6e, 0x4c, 0xd0, 0x0c, 0x62, 0xd0, 0x00, 0x51, 0x4e, 0x04, 0x4b,
+ 0x51, 0x4f, 0x0c, 0x4a, 0x65, 0x4e, 0x6b, 0x4f, 0x8f, 0xde, 0x5f,
+ 0x4e, 0x4b, 0x5f, 0x4f, 0x4a, 0x62, 0xd0, 0x00, 0x7f, 0x52, 0x00,
+ 0x53, 0x50, 0x55, 0x51, 0x00, 0x65, 0x50, 0x6b, 0x51, 0x7f, 0x62,
+ 0xd0, 0x00, 0x52, 0x00, 0x53, 0x50, 0x55, 0x51, 0x00, 0x7f, 0x53,
+ 0x4e, 0x51, 0x51, 0x09, 0x00, 0x60, 0xd4, 0x3e,
+ 0x4e, 0x53, 0x4f, 0x3e, 0x4e, 0x53, 0x4e, 0x7f, 0x51, 0x51, 0x60, 0xd5,
+ 0x51, 0x4f, 0x3f, 0x50, 0x51, 0x4e, 0x3f, 0x50, 0x7f, 0x06, 0x50,
+ 0x8c, 0x0e, 0x51, 0x00, 0x51, 0x51, 0x60, 0xd4, 0x3e, 0x50, 0x53,
+ 0x4f, 0x3e, 0x50, 0x16, 0x50, 0x02, 0x53, 0x4e, 0x7f, 0x60, 0xd4,
+ 0x3e, 0x4e, 0x53, 0x4f, 0x3e, 0x4e, 0x53, 0x4e, 0x7f, 0x09, 0x00,
+ 0x60, 0xd4, 0x3e, 0x4e, 0x53, 0x4f, 0x3e, 0x4e,
+ 0x7f, 0x55, 0x4e, 0x06, 0x55, 0x4f, 0x00, 0x55, 0x4b, 0x00, 0x55, 0x4a,
+ 0x00, 0x3c, 0x4f, 0x00, 0xb0, 0x06, 0x3c, 0x4e, 0x00, 0xa0, 0x1a,
+ 0x70, 0xfb, 0x6e, 0x4f, 0x6e, 0x4e, 0xd0, 0x0c, 0x62, 0xd0, 0x00,
+ 0x51, 0x50, 0x04, 0x4b, 0x51, 0x51, 0x0c, 0x4a, 0x65, 0x50, 0x6b,
+ 0x51, 0x8f, 0xde, 0x5f, 0x50, 0x4b, 0x5f, 0x51, 0x4a, 0x62, 0xd0,
+ 0x00, 0x5a, 0x4e, 0x06, 0x4e, 0x01, 0x51, 0x4e,
+ 0x04, 0x50, 0x0e, 0x51, 0x03, 0x7f, 0x0e, 0x51, 0x00, 0x51, 0x51, 0x60,
+ 0xd4, 0x3e, 0x50, 0x53, 0x51, 0x7f, 0x60, 0xd4, 0x3e, 0x50, 0x53,
+ 0x51, 0x3e, 0x50, 0x53, 0x50, 0x7f, 0x53, 0x4e, 0x51, 0x51, 0x09,
+ 0x00, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x4e, 0x52, 0x15, 0x3f, 0x4e,
+ 0x7f, 0x3e, 0x50, 0x53, 0x50, 0x51, 0x4e, 0x12, 0x50, 0x51, 0x4f,
+ 0x1a, 0x51, 0x7f, 0x53, 0x50, 0x52, 0xfb, 0x09,
+ 0x00, 0x60, 0xd4, 0x3e, 0x50, 0x7f, 0x0e, 0x4f, 0x00, 0x51, 0x4f, 0x60,
+ 0xd4, 0x3e, 0x4e, 0x53, 0x4f, 0x3e, 0x4e, 0x7f, 0x60, 0xd4, 0x3e,
+ 0x50, 0x54, 0x00, 0x3e, 0x50, 0x54, 0x01, 0x7f, 0x0e, 0x51, 0x00,
+ 0x51, 0x51, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x50, 0x52, 0x15, 0x3f,
+ 0x50, 0x7f, 0x52, 0x00, 0x53, 0x4e, 0x55, 0x4f, 0x00, 0x65, 0x4e,
+ 0x6b, 0x4f, 0x7f, 0x09, 0x00, 0x60, 0xd4, 0x3e,
+ 0x4c, 0x53, 0x4d, 0x3e, 0x4c, 0x53, 0x4c, 0x7f, 0x71, 0x10, 0x41, 0x04,
+ 0xfe, 0x41, 0x05, 0xfe, 0x41, 0x04, 0xfd, 0x41, 0x05, 0xfd, 0x70,
+ 0xcf, 0x43, 0x04, 0x01, 0x43, 0x04, 0x02, 0x71, 0x01, 0x7f, 0x0e,
+ 0x4f, 0x00, 0x51, 0x4f, 0x60, 0xd5, 0x51, 0x51, 0x3f, 0x4e, 0x7f,
+ 0x53, 0x4e, 0x55, 0x4f, 0x00, 0x65, 0x4e, 0x6b, 0x4f, 0x51, 0x4e,
+ 0x7f, 0x0e, 0x51, 0x00, 0x51, 0x51, 0x60, 0xd5,
+ 0x50, 0x00, 0x3f, 0x50, 0x7f, 0x3e, 0x50, 0x12, 0x4e, 0x54, 0x04, 0x51,
+ 0x51, 0x1a, 0x4f, 0x54, 0x03, 0x7f, 0x3e, 0x50, 0x12, 0x4e, 0x54,
+ 0x02, 0x51, 0x51, 0x1a, 0x4f, 0x54, 0x01, 0x7f, 0x71, 0x10, 0x41,
+ 0x00, 0xf7, 0x41, 0x01, 0xf7, 0x70, 0xcf, 0x7f, 0x00, 0x2a, 0x00,
+ 0x16, 0x00, 0x52, 0x00, 0x10, 0x00, 0x6a, 0x00, 0x22, 0x00, 0x90,
+ 0x00, 0x04, 0x00, 0x94, 0x04, 0x08, 0x08, 0x08,
+ 0x08, 0x00, 0x98, 0x00, 0x04, 0x00, 0x9c, 0x02, 0x5f, 0x28, 0x00, 0x9e,
+ 0x00, 0x08, 0x00, 0xa6, 0x07, 0x03, 0x01, 0x01, 0x00, 0x00, 0x01,
+ 0x02, 0x00, 0xad, 0x00, 0x06, 0xff, 0x00, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/touchkey_fw_U1.h b/drivers/input/keyboard/cypressbln/touchkey_fw_U1.h
new file mode 100644
index 0000000..a625b41
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/touchkey_fw_U1.h
@@ -0,0 +1,747 @@
+unsigned char firmware_data[] = {
+ 0x40, 0x7d, 0x00, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7d, 0x05, 0x4f, 0x7e, 0x7e, 0x30,
+ 0x30, 0x30, 0x7d, 0x06, 0xbb, 0x7e, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30,
+ 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30,
+ 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30,
+ 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x7e,
+ 0x30, 0x30, 0x30, 0x7e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x40, 0x71, 0x10, 0x62, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe3, 0x38, 0x50, 0x80, 0x4e, 0x62, 0xe3, 0x38, 0x5d,
+ 0xd5, 0x08, 0x62, 0xd5, 0x00, 0x55, 0xfa, 0x01, 0x40, 0x4f, 0x5b,
+ 0x01, 0x03, 0x53, 0xf9, 0x55, 0xf8, 0x3a, 0x50, 0x06, 0x00, 0x40,
+ 0x40, 0x71, 0x10, 0x51, 0xfa, 0x60, 0xe8, 0x70, 0xef, 0x18, 0x60,
+ 0xd5, 0x55, 0xf8, 0x00, 0x55, 0xf9, 0x00, 0x71, 0x10, 0x62, 0xe0,
+ 0x02, 0x70, 0xef, 0x62, 0xe3, 0x38, 0x71, 0x10, 0x41, 0xe1, 0xfe,
+ 0x70, 0xef, 0x62, 0xe3, 0x38, 0x62, 0xd1, 0x03, 0x50, 0x00, 0x4e,
+ 0x62, 0xd3, 0x03, 0x62, 0xd0, 0x00, 0x62, 0xd5, 0x00, 0x62, 0xd4,
+ 0x00, 0x71, 0xc0, 0x7c, 0x03, 0x01, 0x62, 0xd0, 0x00, 0x50, 0x02,
+ 0x57, 0xff, 0x08, 0x28, 0x53, 0x40, 0x18, 0x75, 0x09, 0x00, 0x28,
+ 0x4b, 0x51, 0x40, 0x80, 0x04, 0x75, 0x09, 0x00, 0x62, 0xe3, 0x00,
+ 0x08, 0x28, 0x60, 0xd5, 0x74, 0xa0, 0x4b, 0x18, 0x75, 0x09, 0x00,
+ 0x08, 0x28, 0x53, 0x40, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xa0,
+ 0x1c, 0x53, 0x3f, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x3f, 0x40,
+ 0x47, 0x40, 0xff, 0xb0, 0x06, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x18,
+ 0x7a, 0x3f, 0xbf, 0xeb, 0x8f, 0xc9, 0x18, 0x75, 0x09, 0x00, 0x08,
+ 0x28, 0x53, 0x3f, 0x50, 0x00, 0x3f, 0x40, 0x47, 0x40, 0xff, 0xb0,
+ 0x08, 0x5d, 0xd5, 0x74, 0x60, 0xd5, 0x50, 0x00, 0x7a, 0x3f, 0xbf,
+ 0xef, 0x18, 0x8f, 0xaa, 0x18, 0x71, 0x10, 0x43, 0xe3, 0x00, 0x70,
+ 0xef, 0x62, 0xe0, 0x00, 0x41, 0xfe, 0xe7, 0x43, 0xfe, 0x10, 0x71,
+ 0x10, 0x62, 0xe0, 0x02, 0x70, 0xef, 0x62, 0xe2, 0x00, 0x7c, 0x0a,
+ 0xce, 0x8f, 0xff, 0x7f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x61, 0x00, 0xfd, 0x00, 0xcd, 0x00,
+ 0xce, 0x00, 0xa5, 0x00, 0xa4, 0x00, 0xa0, 0x00, 0xa1, 0x80, 0xa2,
+ 0x80, 0xa3, 0x0c, 0xa8, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0x7c, 0x33,
+ 0x7a, 0x00, 0x7b, 0x00, 0x79, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38,
+ 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00,
+ 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43,
+ 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
+ 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e,
+ 0x00, 0x4f, 0x00, 0xca, 0x20, 0xd6, 0x44, 0xcf, 0x00, 0xcb, 0x00,
+ 0xc8, 0x00, 0xcc, 0x00, 0xc9, 0x00, 0xd7, 0x00, 0xa9, 0x00, 0x2b,
+ 0x00, 0xb0, 0x00, 0xb3, 0x02, 0xb6, 0x00, 0xb2, 0x00, 0xb5, 0x00,
+ 0xb8, 0x00, 0xb1, 0x00, 0xb4, 0x00, 0xb7, 0x00, 0x33, 0x00, 0x34,
+ 0x00, 0x35, 0x00, 0xff, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
+ 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0xdc, 0x00,
+ 0xe2, 0x00, 0xdd, 0x00, 0xd8, 0x02, 0xd9, 0x00, 0xda, 0x28, 0xdb,
+ 0x00, 0xdf, 0x00, 0x29, 0x00, 0x30, 0x00, 0xbd, 0x00, 0xff, 0x70,
+ 0xef, 0x62, 0x00, 0x08, 0x71, 0x10, 0x62, 0x00, 0x08, 0x62, 0x01,
+ 0x92, 0x70, 0xef, 0x62, 0x04, 0x03, 0x71, 0x10, 0x62, 0x04, 0x14,
+ 0x62, 0x05, 0xa8, 0x70, 0xef, 0x62, 0x08, 0x00, 0x71, 0x10, 0x62,
+ 0x08, 0x00, 0x62, 0x09, 0x28, 0x70, 0xef, 0x62, 0x0c, 0x00, 0x71,
+ 0x10, 0x62, 0x0c, 0x00, 0x62, 0x0d, 0x00, 0x70, 0xef, 0x62, 0x10,
+ 0x00, 0x71, 0x10, 0x62, 0x10, 0x00, 0x62, 0x11, 0x00, 0x70, 0xef,
+ 0x62, 0x01, 0x00, 0x62, 0x05, 0x00, 0x62, 0x09, 0x00, 0x62, 0x0d,
+ 0x00, 0x62, 0x11, 0x00, 0x70, 0xef, 0x7f, 0x17, 0xc4, 0x55, 0x02,
+ 0x08, 0x55, 0x03, 0x03, 0x55, 0x04, 0x00, 0x7c, 0x03, 0x11, 0x7c,
+ 0x02, 0xaa, 0x7f, 0x10, 0x70, 0xef, 0x50, 0x00, 0x67, 0x50, 0x02,
+ 0x57, 0x00, 0x7c, 0x03, 0x2c, 0x50, 0x01, 0x67, 0x50, 0x02, 0x57,
+ 0x83, 0x7c, 0x03, 0x2c, 0x70, 0xef, 0x20, 0x7f, 0x38, 0x02, 0x10,
+ 0x08, 0x4f, 0x56, 0xfc, 0x00, 0xd0, 0x04, 0x56, 0xfc, 0x01, 0x18,
+ 0x20, 0x70, 0xef, 0x62, 0xe3, 0x00, 0x10, 0x08, 0x28, 0x39, 0xff,
+ 0xa0, 0x1f, 0x4f, 0x48, 0xfc, 0x01, 0xa0, 0x03, 0x71, 0x10, 0x54,
+ 0xfd, 0x18, 0x20, 0x75, 0x09, 0x00, 0x10, 0x08, 0x28, 0x4f, 0x59,
+ 0xfd, 0x61, 0x00, 0x18, 0x20, 0x75, 0x09, 0x00, 0x8f, 0xd7, 0x38,
+ 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x30, 0x31, 0x32, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+ 0x62, 0xd0, 0x00, 0x2e, 0x02, 0x08, 0x51, 0x02, 0x60, 0x00, 0x71,
+ 0x10, 0x41, 0x01, 0xf7, 0x43, 0x00, 0x08, 0x70, 0xef, 0x7f, 0x71,
+ 0x10, 0x43, 0x01, 0x08, 0x41, 0x00, 0xf7, 0x70, 0xef, 0x7f, 0x62,
+ 0xd0, 0x00, 0x53, 0x00, 0x71, 0x10, 0x5d, 0xe0, 0x08, 0x21, 0xf8,
+ 0x29, 0x00, 0x70, 0xfe, 0x60, 0xe0, 0x70, 0xef, 0x4b, 0x4b, 0x4b,
+ 0x4b, 0x51, 0x02, 0x21, 0xf7, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05,
+ 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e,
+ 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01,
+ 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29,
+ 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7,
+ 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0,
+ 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00,
+ 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80,
+ 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21, 0xf7, 0x80, 0x05,
+ 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x6e, 0x00, 0xc0, 0x05, 0x21,
+ 0xf7, 0x80, 0x05, 0x29, 0x08, 0x80, 0x01, 0x60, 0x00, 0x47, 0x00,
+ 0x00, 0x49, 0x01, 0x00, 0x29, 0x08, 0x60, 0x00, 0x57, 0x01, 0x79,
+ 0xbf, 0xfe, 0x18, 0x71, 0x10, 0x60, 0xe0, 0x70, 0xef, 0x71, 0x01,
+ 0x7f, 0x08, 0x67, 0x67, 0x67, 0x67, 0x21, 0x0f, 0xff, 0x20, 0x9f,
+ 0x4e, 0x18, 0x21, 0x0f, 0xff, 0x19, 0x9f, 0x47, 0x7f, 0x08, 0x5b,
+ 0x9f, 0xe9, 0x18, 0x9f, 0xe6, 0x7f, 0x08, 0x10, 0x28, 0xa0, 0x0b,
+ 0x9f, 0x37, 0x20, 0x18, 0x75, 0xdf, 0xf5, 0x74, 0x8f, 0xf2, 0x38,
+ 0xfe, 0x7f, 0x70, 0xbf, 0x60, 0xd3, 0x52, 0x00, 0xa0, 0x08, 0x10,
+ 0x9f, 0x21, 0x20, 0x75, 0x8f, 0xf6, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x50, 0x0d, 0x9f, 0x14, 0x50, 0x0a, 0x9f, 0x10, 0x7f, 0x70, 0xbf,
+ 0x62, 0xd3, 0x03, 0x4f, 0x52, 0xfb, 0xa0, 0x15, 0x7b, 0xfb, 0x52,
+ 0xfc, 0x59, 0xfd, 0x60, 0xd3, 0x52, 0x00, 0x9e, 0xf9, 0x4f, 0x62,
+ 0xd3, 0x03, 0x77, 0xfd, 0x8f, 0xe9, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x4f, 0x3d, 0xfa, 0x00, 0xb0, 0x06, 0x3d, 0xfb, 0x00, 0xa0, 0x18,
+ 0x10, 0x52, 0xfc, 0x59, 0xfd, 0x28, 0x9e, 0xd9, 0x20, 0x07, 0xfd,
+ 0x01, 0x0f, 0xfc, 0x00, 0x17, 0xfb, 0x01, 0x1f, 0xfa, 0x00, 0x8f,
+ 0xe0, 0x7f, 0x50, 0x01, 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00,
+ 0x29, 0x00, 0xa0, 0x06, 0x26, 0x03, 0xfb, 0x80, 0x04, 0x2e, 0x03,
+ 0x04, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62,
+ 0xd0, 0x00, 0x36, 0x03, 0x04, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0x03, 0x73, 0x21, 0x04,
+ 0xa0, 0x03, 0x50, 0x01, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50, 0x01,
+ 0x80, 0x03, 0x50, 0x00, 0x62, 0xd0, 0x00, 0x29, 0x00, 0xa0, 0x06,
+ 0x26, 0x03, 0xef, 0x80, 0x04, 0x2e, 0x03, 0x10, 0x51, 0x03, 0x60,
+ 0x04, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x36, 0x03,
+ 0x10, 0x51, 0x03, 0x60, 0x04, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62,
+ 0xd0, 0x00, 0x51, 0x03, 0x73, 0x21, 0x10, 0xa0, 0x03, 0x50, 0x01,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x10, 0x70, 0x3f, 0x71, 0x80,
+ 0x5d, 0xd3, 0x08, 0x5d, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x51, 0x08,
+ 0x60, 0xd3, 0x2e, 0x05, 0x80, 0x49, 0xd7, 0x08, 0xa0, 0x09, 0x26,
+ 0x05, 0xf0, 0x2e, 0x05, 0x00, 0x80, 0x08, 0x49, 0xd7, 0x20, 0xa0,
+ 0x03, 0x80, 0xac, 0x51, 0x05, 0x21, 0x0e, 0xe0, 0x01, 0x80, 0x11,
+ 0x80, 0x6d, 0x80, 0x7f, 0x80, 0x4d, 0x80, 0x9c, 0x80, 0x9a, 0x80,
+ 0x98, 0x80, 0x96, 0x80, 0x9d, 0x5d, 0xd8, 0x21, 0xfe, 0x39, 0x40,
+ 0xa0, 0x06, 0x62, 0xd7, 0x00, 0x80, 0x90, 0x49, 0xd8, 0x01, 0xb0,
+ 0x15, 0x55, 0x0c, 0x02, 0x26, 0x07, 0x00, 0x26, 0x06, 0x00, 0x26,
+ 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x62, 0xd7, 0x10, 0x80, 0x77, 0x55,
+ 0x0c, 0x01, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x06, 0x5f, 0x07, 0x06,
+ 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00, 0x60, 0xd8, 0x76, 0x07,
+ 0x62, 0xd7, 0x14, 0x80, 0x5b, 0x51, 0x0a, 0x78, 0x3a, 0x07, 0xc0,
+ 0x0f, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x52, 0x00, 0x60, 0xd8, 0x76,
+ 0x07, 0x2e, 0x05, 0x20, 0x60, 0xd8, 0x62, 0xd7, 0x04, 0x80, 0x3f,
+ 0x5d, 0xd8, 0x3a, 0x0a, 0xd0, 0x2b, 0xa0, 0x29, 0x53, 0x07, 0x53,
+ 0x06, 0x26, 0x05, 0xf0, 0x2e, 0x05, 0x04, 0x80, 0x18, 0x51, 0x0b,
+ 0x78, 0x3a, 0x07, 0xc0, 0x16, 0x51, 0x09, 0x02, 0x07, 0x5c, 0x5d,
+ 0xd8, 0x54, 0x00, 0x2e, 0x05, 0x10, 0x76, 0x07, 0x80, 0x01, 0x62,
+ 0xd7, 0x10, 0x80, 0x0f, 0x62, 0xd7, 0x00, 0x80, 0x0a, 0x26, 0x05,
+ 0xf0, 0x2e, 0x05, 0x00, 0x55, 0x0c, 0x00, 0x18, 0x60, 0xd0, 0x18,
+ 0x60, 0xd3, 0x20, 0x18, 0x7e, 0x62, 0xd0, 0x00, 0x71, 0x10, 0x41,
+ 0x04, 0xfc, 0x43, 0x05, 0x03, 0x70, 0xef, 0x26, 0x03, 0xfc, 0x51,
+ 0x03, 0x60, 0x04, 0x55, 0x0c, 0x00, 0x90, 0x2d, 0x90, 0x32, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x50, 0x00, 0x53, 0x06, 0x71, 0x10, 0x43,
+ 0x04, 0x03, 0x43, 0x05, 0x03, 0x70, 0xef, 0x2e, 0x03, 0x03, 0x51,
+ 0x03, 0x60, 0x04, 0x7f, 0x62, 0xd0, 0x00, 0x51, 0x05, 0x21, 0xb0,
+ 0x26, 0x05, 0x4f, 0x7f, 0x50, 0x20, 0x7f, 0x80, 0x04, 0x41, 0xe0,
+ 0x7f, 0x43, 0xe0, 0x80, 0x7f, 0x43, 0xd6, 0x31, 0x7f, 0x41, 0xe0,
+ 0x7f, 0x41, 0xd6, 0xfe, 0x7f, 0x41, 0xe0, 0x7f, 0x7f, 0x41, 0xd6,
+ 0xfe, 0x7f, 0x62, 0xd0, 0x00, 0x4f, 0x52, 0xfd, 0x53, 0x0a, 0x52,
+ 0xfc, 0x53, 0x0b, 0x52, 0xfb, 0x53, 0x09, 0x52, 0xfa, 0x53, 0x08,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x02, 0x20, 0x02, 0x08, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0xb9, 0x08, 0x5d, 0xa4, 0x04, 0x1b,
+ 0x5d, 0xa5, 0x0c, 0x1a, 0x55, 0x1c, 0x01, 0x18, 0x7e, 0x70, 0xbf,
+ 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x53, 0x1e, 0x64, 0x5c, 0x62, 0xd3,
+ 0x00, 0x52, 0x5b, 0x62, 0xd3, 0x00, 0x13, 0x4b, 0x62, 0xd3, 0x00,
+ 0x54, 0x4f, 0x62, 0xd3, 0x00, 0x52, 0x5a, 0x62, 0xd3, 0x00, 0x1b,
+ 0x4a, 0x62, 0xd3, 0x00, 0x54, 0x4e, 0x48, 0x4e, 0x80, 0xb0, 0x33,
+ 0x3d, 0x4e, 0x00, 0xb0, 0x7b, 0x51, 0x0d, 0x3b, 0x4f, 0xc0, 0x75,
+ 0x52, 0x4f, 0x58, 0x1e, 0x01, 0x00, 0x6d, 0x62, 0xd3, 0x00, 0x05,
+ 0x41, 0xc0, 0x09, 0x51, 0x0f, 0x3b, 0x41, 0xd0, 0x12, 0xa0, 0x10,
+ 0x56, 0x41, 0x00, 0x5b, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x07, 0x4b,
+ 0x01, 0x0f, 0x4a, 0x00, 0x80, 0x41, 0x3d, 0x4e, 0xff, 0xb0, 0x09,
+ 0x50, 0xff, 0x12, 0x0e, 0x3b, 0x4f, 0xc0, 0x20, 0x62, 0xd3, 0x00,
+ 0x56, 0x4f, 0x00, 0x56, 0x4e, 0x00, 0x5b, 0x67, 0x5c, 0x62, 0xd3,
+ 0x00, 0x52, 0x48, 0x78, 0xd0, 0x03, 0x50, 0x00, 0x54, 0x48, 0x08,
+ 0x5b, 0x64, 0x5c, 0x18, 0xb0, 0x2c, 0x62, 0xd3, 0x00, 0x52, 0x5b,
+ 0x62, 0xd3, 0x00, 0x54, 0x4b, 0x62, 0xd3, 0x00, 0x52, 0x5a, 0x62,
+ 0xd3, 0x00, 0x54, 0x4a, 0x51, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00,
+ 0x56, 0x4f, 0x00, 0x56, 0x4e, 0x00, 0x5b, 0x67, 0x5c, 0x62, 0xd3,
+ 0x00, 0x51, 0x12, 0x54, 0x48, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x70,
+ 0xbf, 0x62, 0xd0, 0x00, 0x70, 0xbf, 0x08, 0x5c, 0x62, 0xd3, 0x00,
+ 0x52, 0x43, 0x53, 0x19, 0x55, 0x18, 0x00, 0x18, 0x08, 0x90, 0x7e,
+ 0x62, 0xd3, 0x00, 0x23, 0x45, 0xb0, 0x2c, 0x51, 0x10, 0x04, 0x19,
+ 0x0e, 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x4f,
+ 0x12, 0x19, 0x52, 0x4e, 0x1a, 0x18, 0xc0, 0x39, 0x5b, 0x67, 0x5c,
+ 0x62, 0xd3, 0x00, 0x52, 0x46, 0x78, 0x54, 0x46, 0x08, 0x5b, 0x64,
+ 0x5c, 0x18, 0xb0, 0x3e, 0x80, 0x18, 0x51, 0x10, 0x14, 0x19, 0x1e,
+ 0x18, 0x00, 0x18, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x4f, 0x12,
+ 0x19, 0x52, 0x4e, 0x1a, 0x18, 0xc0, 0x0e, 0x5b, 0x67, 0x90, 0x31,
+ 0x62, 0xd3, 0x00, 0x2d, 0x45, 0x50, 0x01, 0x80, 0x24, 0x5b, 0x67,
+ 0x08, 0x90, 0x23, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x45, 0x62, 0xd3,
+ 0x00, 0x20, 0x51, 0x11, 0x54, 0x46, 0x50, 0x00, 0x80, 0x0d, 0x5b,
+ 0x67, 0x90, 0x0d, 0x73, 0x62, 0xd3, 0x00, 0x25, 0x45, 0x50, 0x00,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x08, 0x67, 0x67, 0x67, 0x5c, 0x18,
+ 0x21, 0x07, 0xf0, 0x01, 0x7f, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
+ 0x40, 0x80, 0x70, 0xbf, 0x70, 0xbf, 0x62, 0xd3, 0x00, 0x50, 0x02,
+ 0x78, 0x08, 0x5c, 0x56, 0x43, 0x28, 0x18, 0x78, 0xdf, 0xf8, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x70, 0xbf, 0x50, 0x02, 0x78, 0x08, 0x91,
+ 0xf9, 0x70, 0xbf, 0x18, 0x08, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52,
+ 0x5b, 0x62, 0xd3, 0x00, 0x54, 0x4b, 0x62, 0xd3, 0x00, 0x52, 0x5a,
+ 0x62, 0xd3, 0x00, 0x54, 0x4a, 0x18, 0x78, 0xdf, 0xe0, 0x70, 0x3f,
+ 0x71, 0xc0, 0x7f, 0x70, 0xbf, 0x08, 0x91, 0xd1, 0x70, 0xbf, 0x18,
+ 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x52, 0x5b, 0x62, 0xd3, 0x00, 0x54,
+ 0x4b, 0x62, 0xd3, 0x00, 0x52, 0x5a, 0x62, 0xd3, 0x00, 0x54, 0x4a,
+ 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x62, 0xd0, 0x00, 0x55, 0x14, 0x00,
+ 0x50, 0x02, 0x78, 0x08, 0x9e, 0xe6, 0x39, 0x01, 0xb0, 0x04, 0x55,
+ 0x14, 0x01, 0x18, 0x78, 0xdf, 0xf3, 0x51, 0x14, 0x7f, 0x50, 0x02,
+ 0x78, 0x08, 0x9e, 0x16, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x98, 0x90,
+ 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0xd8, 0xd9, 0xda, 0xdb,
+ 0xdf, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x70,
+ 0xbf, 0x62, 0xd0, 0x00, 0x62, 0xd3, 0x00, 0x57, 0x00, 0x56, 0x45,
+ 0x00, 0x79, 0xdf, 0xfb, 0x62, 0xd3, 0x00, 0x57, 0x01, 0x50, 0x03,
+ 0x54, 0x46, 0x79, 0xdf, 0xfc, 0x62, 0xd3, 0x00, 0x50, 0x32, 0x57,
+ 0x01, 0x54, 0x48, 0x79, 0xdf, 0xfc, 0x70, 0x3f, 0x71, 0xc0, 0x55,
+ 0x0d, 0x14, 0x55, 0x0e, 0x05, 0x55, 0x0f, 0x19, 0x55, 0x10, 0x01,
+ 0x55, 0x11, 0x03, 0x55, 0x12, 0x32, 0x55, 0x22, 0x04, 0x55, 0x1f,
+ 0x14, 0x43, 0x61, 0x0d, 0x57, 0x00, 0x50, 0x02, 0x90, 0xd2, 0x50,
+ 0x04, 0xff, 0x98, 0x29, 0x00, 0x60, 0xa9, 0x62, 0xa0, 0x08, 0x43,
+ 0xa2, 0x04, 0x62, 0xa3, 0x70, 0x43, 0x7a, 0x01, 0x43, 0xaa, 0x02,
+ 0x43, 0xdf, 0x01, 0x50, 0x01, 0x57, 0x0d, 0x90, 0x1b, 0x90, 0x56,
+ 0x7f, 0x62, 0xd0, 0x00, 0x39, 0x09, 0xc0, 0x03, 0x50, 0x08, 0x53,
+ 0x22, 0xff, 0x6c, 0x29, 0x00, 0x60, 0xa9, 0x51, 0x21, 0x58, 0x20,
+ 0x90, 0x01, 0x7f, 0x62, 0xd0, 0x00, 0x21, 0x03, 0x53, 0x21, 0x64,
+ 0x64, 0x64, 0x64, 0x64, 0x29, 0x80, 0x60, 0xa1, 0x5b, 0x78, 0x21,
+ 0x0f, 0x29, 0x08, 0x74, 0x53, 0x20, 0x12, 0x22, 0x02, 0x21, 0x5c,
+ 0x50, 0x00, 0x53, 0x1d, 0x53, 0x23, 0x29, 0x01, 0x79, 0xa0, 0x08,
+ 0x64, 0x6b, 0x1d, 0x6b, 0x23, 0x8f, 0xf5, 0x60, 0xb5, 0x51, 0x1d,
+ 0x60, 0xb4, 0x7f, 0x62, 0xd0, 0x00, 0x53, 0x1f, 0x7f, 0x50, 0x02,
+ 0x78, 0x08, 0x90, 0x4b, 0x90, 0x7d, 0x18, 0x78, 0xdf, 0xf8, 0x7f,
+ 0x41, 0xdf, 0xfe, 0x71, 0x10, 0x41, 0xd8, 0xfd, 0x70, 0xef, 0x41,
+ 0x61, 0xf3, 0x41, 0xa2, 0xfb, 0x41, 0xa0, 0xf7, 0x62, 0xa3, 0x00,
+ 0x62, 0xa9, 0x00, 0x41, 0xaa, 0xfd, 0x7f, 0x62, 0xd0, 0x00, 0x62,
+ 0xa3, 0x50, 0x51, 0x22, 0xfe, 0xf0, 0x29, 0x00, 0x60, 0xa9, 0x43,
+ 0x61, 0x0d, 0x57, 0x00, 0x50, 0x02, 0x90, 0x19, 0x43, 0xa3, 0x20,
+ 0x43, 0xa2, 0x04, 0x43, 0xa0, 0x08, 0x43, 0xaa, 0x02, 0x43, 0xdf,
+ 0x01, 0x7f, 0x64, 0x5c, 0xfc, 0xc6, 0x4b, 0x74, 0xfc, 0xc2, 0x7f,
+ 0x62, 0xd0, 0x00, 0x53, 0x1d, 0x10, 0x5b, 0x64, 0x64, 0x5c, 0x71,
+ 0x10, 0x5e, 0x01, 0x2a, 0x1d, 0x61, 0x01, 0x36, 0x1d, 0xff, 0x5e,
+ 0x00, 0x22, 0x1d, 0x61, 0x00, 0x36, 0x1d, 0xff, 0x18, 0xfe, 0xb2,
+ 0x5c, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef, 0x7f, 0x62,
+ 0xd0, 0x00, 0x10, 0x73, 0x53, 0x1d, 0x71, 0x10, 0x5b, 0xfe, 0x9c,
+ 0x5c, 0x5e, 0x00, 0x22, 0x1d, 0x61, 0x00, 0x70, 0xef, 0x18, 0x64,
+ 0x64, 0x5c, 0x71, 0x10, 0x5e, 0x01, 0x22, 0x1d, 0x61, 0x01, 0x36,
+ 0x1d, 0xff, 0x5e, 0x00, 0x2a, 0x1d, 0x61, 0x00, 0x70, 0xef, 0x7f,
+ 0x70, 0xbf, 0x62, 0xd0, 0x00, 0x53, 0x1e, 0x50, 0x00, 0x53, 0x1a,
+ 0x53, 0x1b, 0x43, 0xa0, 0x01, 0x51, 0x1f, 0x60, 0xfd, 0x41, 0xa3,
+ 0xdf, 0x51, 0x1e, 0x9f, 0x84, 0x9f, 0x8b, 0x58, 0x23, 0x55, 0x1c,
+ 0x00, 0x62, 0xa5, 0x00, 0x62, 0xa4, 0x00, 0x43, 0xb3, 0x01, 0x51,
+ 0x1c, 0xaf, 0xfd, 0x79, 0xdf, 0xee, 0x51, 0x1e, 0x9f, 0x69, 0x9f,
+ 0x9b, 0x43, 0xa3, 0x20, 0x41, 0xa0, 0xfe, 0x62, 0xfd, 0x00, 0x50,
+ 0xff, 0x4c, 0x1b, 0x14, 0x1b, 0x51, 0x20, 0x11, 0x08, 0xfe, 0x33,
+ 0x4c, 0x1a, 0x1c, 0x1a, 0xd0, 0x07, 0x55, 0x1a, 0x00, 0x55, 0x1b,
+ 0x00, 0x51, 0x1e, 0x64, 0x5c, 0x62, 0xd3, 0x00, 0x51, 0x1b, 0x54,
+ 0x5b, 0x51, 0x1a, 0x54, 0x5a, 0x70, 0x3f, 0x71, 0xc0, 0x7f, 0x50,
+ 0x02, 0x78, 0x08, 0x9f, 0x8d, 0x18, 0x78, 0xdf, 0xfa, 0x7f, 0x70,
+ 0xbf, 0x62, 0xd3, 0x00, 0x64, 0x5c, 0x52, 0x5b, 0x59, 0x5a, 0x70,
+ 0x3f, 0x71, 0xc0, 0x7f, 0x10, 0x7c, 0x05, 0x15, 0x7c, 0x04, 0xd7,
+ 0x20, 0x7c, 0x13, 0x53, 0x43, 0x00, 0x08, 0x62, 0xd0, 0x00, 0x55,
+ 0x24, 0x08, 0x55, 0x25, 0x04, 0x55, 0x26, 0x0c, 0x55, 0x28, 0x55,
+ 0x55, 0x29, 0x02, 0x10, 0x50, 0x00, 0x08, 0x50, 0x24, 0x08, 0x50,
+ 0x06, 0x08, 0x50, 0x12, 0x08, 0x7c, 0x06, 0x96, 0x38, 0xfc, 0x7c,
+ 0x06, 0x36, 0x7c, 0x06, 0x7c, 0x20, 0x71, 0x10, 0x41, 0x04, 0xfc,
+ 0x41, 0x05, 0xfc, 0x71, 0x01, 0x10, 0x70, 0xcf, 0x7c, 0x08, 0xcf,
+ 0x7c, 0x08, 0x2d, 0x20, 0x90, 0xc4, 0x80, 0xbf, 0x7c, 0x14, 0xa7,
+ 0x62, 0xe3, 0x38, 0x92, 0xd0, 0x62, 0xd0, 0x00, 0x3c, 0x6f, 0x01,
+ 0xb0, 0x09, 0x50, 0x00, 0x08, 0x7c, 0x16, 0x49, 0x38, 0xff, 0x62,
+ 0xe3, 0x38, 0x10, 0x7c, 0x08, 0x93, 0x20, 0x39, 0x00, 0xa0, 0x6e,
+ 0x62, 0xd0, 0x00, 0x51, 0x63, 0x11, 0xd0, 0x51, 0x62, 0x19, 0x07,
+ 0xd0, 0x12, 0x7c, 0x13, 0x65, 0x39, 0xe1, 0xa0, 0x16, 0x62, 0xd0,
+ 0x00, 0x76, 0x63, 0x0e, 0x62, 0x00, 0x80, 0x0c, 0x62, 0xd0, 0x00,
+ 0x55, 0x63, 0x00, 0x55, 0x62, 0x00, 0x90, 0x75, 0x62, 0xd0, 0x00,
+ 0x3c, 0x72, 0xf0, 0xd0, 0x06, 0x62, 0xd0, 0x00, 0x76, 0x72, 0x62,
+ 0xd0, 0x00, 0x51, 0x72, 0x62, 0xd0, 0x00, 0x3a, 0x29, 0xb0, 0x56,
+ 0x97, 0xde, 0x62, 0xd0, 0x00, 0x53, 0x73, 0x3c, 0x73, 0xe1, 0xa0,
+ 0x18, 0x62, 0xd0, 0x00, 0x55, 0x75, 0x00, 0x7c, 0x13, 0xa0, 0x62,
+ 0xd0, 0x00, 0x55, 0x71, 0x01, 0x62, 0xd0, 0x00, 0x55, 0x6e, 0x03,
+ 0x80, 0x33, 0x62, 0xd0, 0x00, 0x55, 0x72, 0x00, 0x80, 0x2b, 0x62,
+ 0xd0, 0x00, 0x55, 0x63, 0x00, 0x55, 0x62, 0x00, 0x62, 0xd0, 0x00,
+ 0x3c, 0x71, 0x01, 0xb0, 0x1a, 0x62, 0xd0, 0x00, 0x7a, 0x6e, 0x3c,
+ 0x6e, 0x00, 0xb0, 0x10, 0x7c, 0x14, 0x28, 0x62, 0xd0, 0x00, 0x55,
+ 0x71, 0x00, 0x62, 0xd0, 0x00, 0x55, 0x72, 0x00, 0x7c, 0x15, 0x24,
+ 0x8f, 0x41, 0x8f, 0xff, 0x10, 0x4f, 0x38, 0x16, 0x10, 0x62, 0xd0,
+ 0x00, 0x51, 0x68, 0x7c, 0x09, 0x8e, 0x20, 0x10, 0x50, 0x00, 0x7c,
+ 0x0a, 0x46, 0x20, 0x56, 0x0d, 0x00, 0x80, 0xae, 0x56, 0x00, 0x00,
+ 0x80, 0xa2, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40,
+ 0x00, 0x06, 0x3f, 0x68, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4,
+ 0x3e, 0x3f, 0x10, 0x7c, 0x09, 0x8e, 0x20, 0x10, 0x52, 0x00, 0x7c,
+ 0x0a, 0x46, 0x20, 0x10, 0x7c, 0x06, 0x6c, 0x62, 0xd0, 0x00, 0x20,
+ 0x39, 0x00, 0xbf, 0xee, 0x55, 0x40, 0x03, 0x5a, 0x3f, 0x06, 0x3f,
+ 0x01, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00, 0x08, 0x51, 0x3d, 0x08,
+ 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x17, 0x94, 0x38, 0xfc,
+ 0x51, 0x38, 0x53, 0x3d, 0x51, 0x37, 0x53, 0x3e, 0x51, 0x3d, 0x02,
+ 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x53, 0x40, 0x52, 0x0d,
+ 0x53, 0x3d, 0x55, 0x3e, 0x00, 0x65, 0x3d, 0x6b, 0x3e, 0x51, 0x3d,
+ 0x02, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x53, 0x40, 0x52,
+ 0x00, 0x53, 0x3d, 0x55, 0x3e, 0x00, 0x65, 0x3d, 0x6b, 0x3e, 0x06,
+ 0x3d, 0x5a, 0x0e, 0x3e, 0x00, 0x51, 0x3e, 0x60, 0xd4, 0x3e, 0x3d,
+ 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x51, 0x40, 0x60, 0xd5, 0x51,
+ 0x3e, 0x3f, 0x3f, 0x51, 0x3d, 0x3f, 0x3f, 0x77, 0x00, 0x3d, 0x00,
+ 0x02, 0xcf, 0x5b, 0x77, 0x0d, 0x3d, 0x0d, 0x03, 0xcf, 0x4f, 0x56,
+ 0x00, 0x00, 0x81, 0x3d, 0x62, 0xd0, 0x00, 0x55, 0x40, 0x03, 0x5a,
+ 0x3f, 0x06, 0x3f, 0x01, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00, 0x08,
+ 0x51, 0x3d, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x17,
+ 0x94, 0x38, 0xfc, 0x51, 0x38, 0x53, 0x3d, 0x51, 0x37, 0x53, 0x3e,
+ 0x51, 0x3d, 0x02, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x60,
+ 0xd4, 0x3e, 0x3f, 0x54, 0x0e, 0x3e, 0x3f, 0x54, 0x0f, 0x5a, 0x3f,
+ 0x06, 0x3f, 0x03, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00, 0x08, 0x51,
+ 0x3d, 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x17, 0x94,
+ 0x38, 0xfc, 0x51, 0x38, 0x53, 0x3d, 0x51, 0x37, 0x53, 0x3e, 0x51,
+ 0x3d, 0x02, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x60, 0xd4,
+ 0x3e, 0x3f, 0x54, 0x10, 0x3e, 0x3f, 0x54, 0x11, 0x5a, 0x3f, 0x06,
+ 0x3f, 0x05, 0x52, 0x00, 0x53, 0x3d, 0x50, 0x00, 0x08, 0x51, 0x3d,
+ 0x08, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7c, 0x17, 0x94, 0x38,
+ 0xfc, 0x51, 0x38, 0x53, 0x3d, 0x51, 0x37, 0x53, 0x3e, 0x51, 0x3d,
+ 0x02, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x0a, 0x40, 0x60, 0xd4, 0x3e,
+ 0x3f, 0x54, 0x12, 0x3e, 0x3f, 0x54, 0x13, 0x50, 0x03, 0x08, 0x5a,
+ 0x3f, 0x06, 0x3f, 0x0e, 0x08, 0x51, 0x3f, 0x08, 0x7c, 0x15, 0x6b,
+ 0x38, 0xfd, 0x62, 0xd0, 0x00, 0x51, 0x3f, 0x54, 0x15, 0x51, 0x40,
+ 0x54, 0x14, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f,
+ 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x53, 0x3d, 0x51, 0x40, 0x09,
+ 0x00, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x3d, 0x52, 0x15, 0x3f, 0x3d,
+ 0x06, 0x3f, 0x4a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd5, 0x52,
+ 0x14, 0x3f, 0x3f, 0x52, 0x15, 0x3f, 0x3f, 0x52, 0x00, 0x53, 0x3f,
+ 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x52,
+ 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd5, 0x52, 0x14, 0x3f,
+ 0x3d, 0x52, 0x15, 0x3f, 0x3d, 0x51, 0x3f, 0x01, 0x56, 0x53, 0x3d,
+ 0x51, 0x40, 0x09, 0x00, 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x3d, 0x52,
+ 0x15, 0x3f, 0x3d, 0x06, 0x3f, 0x5e, 0x0e, 0x40, 0x00, 0x51, 0x40,
+ 0x60, 0xd5, 0x52, 0x14, 0x3f, 0x3f, 0x52, 0x15, 0x3f, 0x3f, 0x77,
+ 0x00, 0x3d, 0x00, 0x02, 0xce, 0xc0, 0x38, 0xea, 0x20, 0x7f, 0x10,
+ 0x4f, 0x38, 0x06, 0x62, 0xd0, 0x00, 0x55, 0x70, 0x00, 0x10, 0x62,
+ 0xd0, 0x00, 0x51, 0x68, 0x7c, 0x09, 0x8e, 0x20, 0x10, 0x50, 0x00,
+ 0x7c, 0x0a, 0x46, 0x20, 0x56, 0x00, 0x00, 0x80, 0x31, 0x62, 0xd0,
+ 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x06, 0x3f, 0x68,
+ 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x10, 0x7c,
+ 0x09, 0x8e, 0x20, 0x10, 0x52, 0x00, 0x7c, 0x0a, 0x46, 0x20, 0x10,
+ 0x7c, 0x06, 0x6c, 0x62, 0xd0, 0x00, 0x20, 0x39, 0x00, 0xbf, 0xee,
+ 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcf, 0xcc, 0x56, 0x00, 0x00, 0x83,
+ 0xa2, 0x62, 0xd0, 0x00, 0x3c, 0x6f, 0x02, 0xa1, 0x8c, 0x62, 0xd0,
+ 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b,
+ 0x40, 0x51, 0x3f, 0x01, 0x4a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00,
+ 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06,
+ 0x3f, 0x5a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f,
+ 0x53, 0x40, 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x3d, 0x12, 0x3f, 0x51,
+ 0x3e, 0x1a, 0x40, 0xd0, 0x3f, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53,
+ 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01,
+ 0x4a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d,
+ 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x5a, 0x0e, 0x40,
+ 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f,
+ 0x12, 0x3d, 0x54, 0x03, 0x51, 0x40, 0x1a, 0x3e, 0x54, 0x02, 0x80,
+ 0x3d, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00,
+ 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x53, 0x3d, 0x51,
+ 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d,
+ 0x53, 0x3d, 0x06, 0x3f, 0x4a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60,
+ 0xd4, 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f, 0x12, 0x3d, 0x54, 0x03,
+ 0x51, 0x40, 0x1a, 0x3e, 0x54, 0x02, 0x50, 0x90, 0x13, 0x03, 0x50,
+ 0x01, 0x1b, 0x02, 0xc0, 0xc3, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53,
+ 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01,
+ 0x5e, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d,
+ 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x5a, 0x0e, 0x40,
+ 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f,
+ 0x53, 0x3f, 0x51, 0x3d, 0x12, 0x3f, 0x51, 0x3e, 0x1a, 0x40, 0xd0,
+ 0x3f, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00,
+ 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x5e, 0x53, 0x3d, 0x51,
+ 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d,
+ 0x53, 0x3d, 0x06, 0x3f, 0x5a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60,
+ 0xd4, 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f, 0x12, 0x3d, 0x54, 0x05,
+ 0x51, 0x40, 0x1a, 0x3e, 0x54, 0x04, 0x80, 0x3d, 0x62, 0xd0, 0x00,
+ 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40,
+ 0x51, 0x3f, 0x01, 0x5a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60,
+ 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f,
+ 0x5e, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53,
+ 0x40, 0x3e, 0x3f, 0x12, 0x3d, 0x54, 0x05, 0x51, 0x40, 0x1a, 0x3e,
+ 0x54, 0x04, 0x50, 0x90, 0x13, 0x05, 0x50, 0x01, 0x1b, 0x04, 0xd0,
+ 0x08, 0x62, 0xd0, 0x00, 0x76, 0x70, 0x82, 0x0d, 0x62, 0xd0, 0x00,
+ 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40,
+ 0x51, 0x3f, 0x01, 0x56, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60,
+ 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f,
+ 0x52, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd5, 0x51, 0x3e, 0x3f,
+ 0x3f, 0x51, 0x3d, 0x3f, 0x3f, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40,
+ 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x5e, 0x53, 0x3d,
+ 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e,
+ 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x56, 0x0e, 0x40, 0x00, 0x51, 0x40,
+ 0x60, 0xd5, 0x51, 0x3e, 0x3f, 0x3f, 0x51, 0x3d, 0x3f, 0x3f, 0x52,
+ 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51,
+ 0x3f, 0x01, 0x5a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4,
+ 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x5e,
+ 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd5, 0x51, 0x3e, 0x3f, 0x3f,
+ 0x51, 0x3d, 0x3f, 0x3f, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00,
+ 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x53, 0x3d, 0x51,
+ 0x40, 0x09, 0x00, 0x53, 0x3e, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3c,
+ 0x3e, 0x3d, 0x16, 0x3d, 0x02, 0x53, 0x3b, 0x08, 0x51, 0x3c, 0x53,
+ 0x3a, 0x18, 0x53, 0x39, 0x65, 0x39, 0x6b, 0x3a, 0x06, 0x3f, 0x56,
+ 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53, 0x40,
+ 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x39, 0x04, 0x3f, 0x51, 0x3a, 0x0c,
+ 0x40, 0x51, 0x3b, 0x04, 0x3f, 0x51, 0x3c, 0x0c, 0x40, 0x70, 0xfb,
+ 0x6e, 0x40, 0x6e, 0x3f, 0x70, 0xfb, 0x6e, 0x40, 0x6e, 0x3f, 0x51,
+ 0x3e, 0x60, 0xd5, 0x51, 0x40, 0x3f, 0x3d, 0x51, 0x3f, 0x3f, 0x3d,
+ 0x10, 0x52, 0x00, 0x7c, 0x06, 0xc9, 0x20, 0x62, 0xd0, 0x00, 0x52,
+ 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51,
+ 0x3f, 0x01, 0x5a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4,
+ 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x4a,
+ 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53, 0x40,
+ 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x3d, 0x12, 0x3f, 0x51, 0x3e, 0x1a,
+ 0x40, 0xd0, 0x28, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55,
+ 0x40, 0x00, 0x06, 0x3f, 0x6c, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60,
+ 0xd4, 0x3e, 0x3f, 0x7a, 0x3f, 0x53, 0x3e, 0x06, 0x3e, 0x01, 0x51,
+ 0x40, 0x60, 0xd5, 0x51, 0x3e, 0x3f, 0x3f, 0x80, 0x19, 0x62, 0xd0,
+ 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x06, 0x3f, 0x6c,
+ 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd5, 0x50, 0x00, 0x3f, 0x3f,
+ 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x06,
+ 0x3f, 0x6c, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f,
+ 0x53, 0x40, 0x50, 0x05, 0x3a, 0x40, 0xd0, 0x6b, 0x62, 0xd0, 0x00,
+ 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40,
+ 0x51, 0x3f, 0x01, 0x4a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x53,
+ 0x3e, 0x06, 0x3f, 0x5a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4,
+ 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x3e, 0x60,
+ 0xd4, 0x3e, 0x3d, 0x53, 0x3c, 0x3e, 0x3d, 0x16, 0x3d, 0x02, 0x02,
+ 0x3f, 0x53, 0x3f, 0x51, 0x3c, 0x0a, 0x40, 0x53, 0x40, 0x70, 0xfb,
+ 0x6e, 0x40, 0x6e, 0x3f, 0x51, 0x3e, 0x60, 0xd5, 0x51, 0x40, 0x3f,
+ 0x3d, 0x51, 0x3f, 0x3f, 0x3d, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40,
+ 0x00, 0x06, 0x3f, 0x6c, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd5,
+ 0x50, 0x00, 0x3f, 0x3f, 0x77, 0x00, 0x3d, 0x00, 0x02, 0xcc, 0x5b,
+ 0x62, 0xd0, 0x00, 0x3c, 0x6f, 0x02, 0xb1, 0x08, 0x56, 0x00, 0x00,
+ 0x80, 0xfe, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40,
+ 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x5a, 0x53, 0x3d,
+ 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e,
+ 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x2e, 0x0e, 0x40, 0x00, 0x51, 0x40,
+ 0x60, 0xd5, 0x51, 0x3e, 0x3f, 0x3f, 0x51, 0x3d, 0x3f, 0x3f, 0x52,
+ 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51,
+ 0x3f, 0x01, 0x4a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4,
+ 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x51, 0x3f, 0x01,
+ 0x5a, 0x53, 0x3b, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3b,
+ 0x53, 0x3c, 0x3e, 0x3b, 0x53, 0x3b, 0x51, 0x3d, 0x12, 0x3b, 0x51,
+ 0x3e, 0x1a, 0x3c, 0xd0, 0x3f, 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53,
+ 0x3d, 0x55, 0x3e, 0x00, 0x65, 0x3d, 0x6b, 0x3e, 0x51, 0x3d, 0x01,
+ 0x4a, 0x53, 0x3b, 0x51, 0x3e, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3b,
+ 0x53, 0x3c, 0x3e, 0x3b, 0x53, 0x3b, 0x06, 0x3d, 0x5a, 0x0e, 0x3e,
+ 0x00, 0x51, 0x3e, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d,
+ 0x12, 0x3b, 0x54, 0x03, 0x51, 0x3e, 0x1a, 0x3c, 0x54, 0x02, 0x80,
+ 0x07, 0x56, 0x03, 0x00, 0x56, 0x02, 0x00, 0x62, 0xd0, 0x00, 0x06,
+ 0x3f, 0x2a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd5, 0x52, 0x02,
+ 0x3f, 0x3f, 0x52, 0x03, 0x3f, 0x3f, 0x52, 0x00, 0x53, 0x3f, 0x55,
+ 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x4a, 0x53,
+ 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e,
+ 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x32, 0x0e, 0x40, 0x00, 0x51,
+ 0x40, 0x60, 0xd5, 0x51, 0x3e, 0x3f, 0x3f, 0x51, 0x3d, 0x3f, 0x3f,
+ 0x77, 0x00, 0x3d, 0x00, 0x02, 0xce, 0xff, 0x62, 0xd0, 0x00, 0x3c,
+ 0x6f, 0x02, 0xa0, 0x1a, 0x62, 0xd0, 0x00, 0x3c, 0x70, 0x00, 0xa0,
+ 0x12, 0x50, 0x75, 0x08, 0x50, 0x30, 0x08, 0x90, 0x0d, 0x38, 0xfe,
+ 0x98, 0xbf, 0x10, 0x7c, 0x08, 0xad, 0x20, 0x38, 0xfa, 0x20, 0x7f,
+ 0x10, 0x4f, 0x80, 0x02, 0x40, 0x62, 0xd0, 0x00, 0x52, 0xfc, 0x53,
+ 0x3f, 0x52, 0xfb, 0x53, 0x40, 0x51, 0x3f, 0x11, 0x01, 0x54, 0xfc,
+ 0x51, 0x40, 0x19, 0x00, 0x54, 0xfb, 0x3c, 0x40, 0x00, 0xbf, 0xe4,
+ 0x3c, 0x3f, 0x00, 0xbf, 0xdf, 0x20, 0x7f, 0x10, 0x7c, 0x05, 0x15,
+ 0x7c, 0x04, 0xd7, 0x20, 0x7f, 0x10, 0x7c, 0x05, 0x11, 0x7c, 0x04,
+ 0xd3, 0x20, 0x7f, 0x62, 0xd0, 0x00, 0x50, 0x28, 0x12, 0x4f, 0x50,
+ 0x00, 0x1a, 0x4e, 0xd0, 0x15, 0x62, 0xd0, 0x00, 0x50, 0x28, 0x12,
+ 0x51, 0x50, 0x00, 0x1a, 0x50, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50,
+ 0xe1, 0x80, 0x1a, 0x62, 0xd0, 0x00, 0x51, 0x51, 0x12, 0x4f, 0x51,
+ 0x50, 0x1a, 0x4e, 0xd0, 0x08, 0x62, 0xd0, 0x00, 0x50, 0x00, 0x80,
+ 0x06, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x7f, 0x10, 0x4f, 0x38, 0x02,
+ 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x51, 0x73, 0x01, 0x01, 0x62, 0xd0,
+ 0x00, 0x53, 0x24, 0x71, 0x01, 0x62, 0xd0, 0x00, 0x3c, 0x71, 0x00,
+ 0xb0, 0x69, 0x62, 0xe3, 0x38, 0x10, 0x7c, 0x06, 0x6c, 0x62, 0xd0,
+ 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10,
+ 0x7c, 0x06, 0x6c, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x40, 0x47, 0x40,
+ 0x20, 0xa0, 0x03, 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08,
+ 0x9f, 0x43, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00, 0xc8, 0xcf, 0xdf,
+ 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x6c, 0x62, 0xd0,
+ 0x00, 0x20, 0x53, 0x40, 0x47, 0x40, 0x20, 0xb0, 0x03, 0x80, 0x12,
+ 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9f, 0x1c, 0x38, 0xfe, 0x77,
+ 0x00, 0x3d, 0x00, 0x1e, 0xcf, 0xdf, 0x62, 0xd0, 0x00, 0x51, 0x24,
+ 0x29, 0x08, 0x53, 0x24, 0x43, 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f,
+ 0x10, 0x4f, 0x38, 0x02, 0x70, 0xfe, 0x62, 0xd0, 0x00, 0x51, 0x73,
+ 0x01, 0x09, 0x62, 0xd0, 0x00, 0x53, 0x24, 0x71, 0x01, 0x62, 0xd0,
+ 0x00, 0x3c, 0x71, 0x01, 0xb0, 0x60, 0x62, 0xe3, 0x38, 0x10, 0x7c,
+ 0x06, 0x6c, 0x62, 0xd0, 0x00, 0x20, 0x41, 0x00, 0xf7, 0x56, 0x00,
+ 0x00, 0x80, 0x1e, 0x10, 0x7c, 0x06, 0x6c, 0x62, 0xd0, 0x00, 0x20,
+ 0x53, 0x40, 0x47, 0x40, 0x20, 0xa0, 0x03, 0x80, 0x12, 0x50, 0x00,
+ 0x08, 0x50, 0x14, 0x08, 0x9e, 0xbb, 0x38, 0xfe, 0x77, 0x00, 0x3d,
+ 0x00, 0xc8, 0xcf, 0xdf, 0x56, 0x00, 0x00, 0x80, 0x1e, 0x10, 0x7c,
+ 0x06, 0x6c, 0x62, 0xd0, 0x00, 0x20, 0x53, 0x40, 0x47, 0x40, 0x20,
+ 0xb0, 0x03, 0x80, 0x12, 0x50, 0x00, 0x08, 0x50, 0x14, 0x08, 0x9e,
+ 0x94, 0x38, 0xfe, 0x77, 0x00, 0x3d, 0x00, 0x1e, 0xcf, 0xdf, 0x43,
+ 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x01, 0x62,
+ 0xd0, 0x00, 0x51, 0x24, 0x54, 0x00, 0x52, 0x00, 0x21, 0x0f, 0x39,
+ 0x01, 0xb0, 0x18, 0x62, 0xd0, 0x00, 0x55, 0x75, 0x00, 0x62, 0xd0,
+ 0x00, 0x55, 0x67, 0x00, 0x55, 0x66, 0x00, 0x62, 0xd0, 0x00, 0x55,
+ 0x24, 0x00, 0x80, 0x50, 0x52, 0x00, 0x21, 0x0f, 0x39, 0x02, 0xb0,
+ 0x1e, 0x62, 0xd0, 0x00, 0x55, 0x75, 0x01, 0x62, 0xd0, 0x00, 0x55,
+ 0x74, 0x00, 0x62, 0xd0, 0x00, 0x55, 0x67, 0x08, 0x55, 0x66, 0x08,
+ 0x62, 0xd0, 0x00, 0x55, 0x24, 0x00, 0x80, 0x2b, 0x52, 0x00, 0x21,
+ 0xf0, 0x39, 0x40, 0xb0, 0x0f, 0x62, 0xd0, 0x00, 0x55, 0x6f, 0x02,
+ 0x62, 0xd0, 0x00, 0x55, 0x24, 0x00, 0x80, 0x15, 0x52, 0x00, 0x21,
+ 0xf0, 0x39, 0x50, 0xb0, 0x0d, 0x62, 0xd0, 0x00, 0x55, 0x6f, 0x01,
+ 0x62, 0xd0, 0x00, 0x55, 0x24, 0x00, 0x38, 0xff, 0x20, 0x7f, 0x62,
+ 0xd0, 0x00, 0x3c, 0x75, 0x00, 0xa0, 0x13, 0x9e, 0x25, 0x62, 0xd0,
+ 0x00, 0x3c, 0x74, 0x00, 0xb0, 0x35, 0x55, 0x74, 0x01, 0x7c, 0x0b,
+ 0xe1, 0x80, 0x2d, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x66, 0xd0,
+ 0x08, 0x10, 0x7c, 0x05, 0x15, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x05,
+ 0x11, 0x20, 0x62, 0xd0, 0x00, 0x50, 0x01, 0x3a, 0x67, 0xd0, 0x08,
+ 0x10, 0x7c, 0x04, 0xd7, 0x20, 0x80, 0x06, 0x10, 0x7c, 0x04, 0xd3,
+ 0x20, 0x98, 0x8d, 0x7f, 0x10, 0x4f, 0x38, 0x03, 0x56, 0x02, 0x00,
+ 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x80, 0x51, 0x62, 0xd0, 0x00,
+ 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40,
+ 0x52, 0xfc, 0x04, 0x3f, 0x52, 0xfb, 0x0c, 0x40, 0x51, 0x40, 0x60,
+ 0xd4, 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f, 0x53, 0x3f, 0x52, 0x02,
+ 0x12, 0x3f, 0x52, 0x01, 0x1a, 0x40, 0xd0, 0x23, 0x62, 0xd0, 0x00,
+ 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40,
+ 0x52, 0xfc, 0x04, 0x3f, 0x52, 0xfb, 0x0c, 0x40, 0x51, 0x40, 0x60,
+ 0xd4, 0x3e, 0x3f, 0x54, 0x01, 0x3e, 0x3f, 0x54, 0x02, 0x77, 0x00,
+ 0x52, 0x00, 0x3b, 0xfa, 0xcf, 0xab, 0x62, 0xd0, 0x00, 0x52, 0x02,
+ 0x53, 0x3f, 0x52, 0x01, 0x53, 0x40, 0x38, 0xfd, 0x20, 0x7f, 0x10,
+ 0x4f, 0x38, 0x02, 0x71, 0x10, 0x41, 0x01, 0xf7, 0x43, 0x00, 0x08,
+ 0x70, 0xcf, 0x43, 0x00, 0x08, 0x50, 0x00, 0x08, 0x50, 0x64, 0x08,
+ 0x9d, 0x33, 0x71, 0x10, 0x41, 0x01, 0xf7, 0x41, 0x00, 0xf7, 0x70,
+ 0xcf, 0x43, 0x00, 0x08, 0x50, 0x00, 0x08, 0x50, 0x64, 0x08, 0x9d,
+ 0x1e, 0x38, 0xfc, 0x5d, 0x00, 0x62, 0xd0, 0x00, 0x53, 0x40, 0x26,
+ 0x40, 0x08, 0x3c, 0x40, 0x08, 0xb0, 0x09, 0x56, 0x01, 0x00, 0x56,
+ 0x00, 0x00, 0x80, 0x07, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x52,
+ 0x01, 0x62, 0xd0, 0x00, 0x53, 0x6f, 0x71, 0x10, 0x43, 0x00, 0x08,
+ 0x41, 0x01, 0xf7, 0x70, 0xcf, 0x3c, 0x6f, 0x00, 0xb0, 0x04, 0x43,
+ 0x00, 0x08, 0x38, 0xfe, 0x20, 0x7f, 0x10, 0x4f, 0x38, 0x01, 0x62,
+ 0xe3, 0x38, 0x10, 0x50, 0x02, 0x7c, 0x03, 0x9c, 0x20, 0x10, 0x50,
+ 0xff, 0x7c, 0x03, 0x9c, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x9c,
+ 0x20, 0x10, 0x50, 0x04, 0x08, 0x50, 0x00, 0x08, 0x50, 0x5a, 0x08,
+ 0x7c, 0x04, 0x8d, 0x38, 0xfd, 0x20, 0x56, 0x00, 0x00, 0x80, 0xda,
+ 0x62, 0xd0, 0x00, 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65,
+ 0x3f, 0x6b, 0x40, 0x51, 0x3f, 0x01, 0x4a, 0x53, 0x3d, 0x51, 0x40,
+ 0x09, 0x00, 0x60, 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53,
+ 0x3d, 0x06, 0x3f, 0x5a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4,
+ 0x3e, 0x3f, 0x53, 0x40, 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x3d, 0x12,
+ 0x3f, 0x51, 0x3e, 0x1a, 0x40, 0xd0, 0x8c, 0x62, 0xd0, 0x00, 0x52,
+ 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40, 0x51,
+ 0x3f, 0x01, 0x4a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60, 0xd4,
+ 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f, 0x5a,
+ 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53, 0x40,
+ 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x3d, 0x14, 0x3f, 0x51, 0x3e, 0x1c,
+ 0x40, 0x51, 0x40, 0x10, 0x7c, 0x03, 0x9c, 0x20, 0x62, 0xd0, 0x00,
+ 0x52, 0x00, 0x53, 0x3f, 0x55, 0x40, 0x00, 0x65, 0x3f, 0x6b, 0x40,
+ 0x51, 0x3f, 0x01, 0x4a, 0x53, 0x3d, 0x51, 0x40, 0x09, 0x00, 0x60,
+ 0xd4, 0x3e, 0x3d, 0x53, 0x3e, 0x3e, 0x3d, 0x53, 0x3d, 0x06, 0x3f,
+ 0x5a, 0x0e, 0x40, 0x00, 0x51, 0x40, 0x60, 0xd4, 0x3e, 0x3f, 0x53,
+ 0x40, 0x3e, 0x3f, 0x53, 0x3f, 0x51, 0x3d, 0x14, 0x3f, 0x51, 0x3e,
+ 0x1c, 0x40, 0x26, 0x40, 0x00, 0x51, 0x3f, 0x10, 0x7c, 0x03, 0x9c,
+ 0x20, 0x80, 0x0f, 0x10, 0x50, 0x00, 0x7c, 0x03, 0x9c, 0x20, 0x10,
+ 0x50, 0x00, 0x7c, 0x03, 0x9c, 0x20, 0x77, 0x00, 0x3d, 0x00, 0x02,
+ 0xcf, 0x23, 0x10, 0x50, 0x00, 0x7c, 0x03, 0x9c, 0x20, 0x10, 0x50,
+ 0x01, 0x7c, 0x03, 0x9c, 0x20, 0x10, 0x50, 0x00, 0x7c, 0x03, 0x9c,
+ 0x20, 0x10, 0x50, 0x01, 0x7c, 0x03, 0x9c, 0x20, 0x10, 0x50, 0xff,
+ 0x7c, 0x03, 0x9c, 0x20, 0x10, 0x50, 0xff, 0x7c, 0x03, 0x9c, 0x7c,
+ 0x04, 0x84, 0x20, 0x50, 0x13, 0x08, 0x50, 0x88, 0x08, 0x9b, 0x9e,
+ 0x38, 0xfe, 0x38, 0xff, 0x20, 0x7f, 0x7f, 0x10, 0x4f, 0x5d, 0xd0,
+ 0x08, 0x62, 0xd0, 0x00, 0x50, 0x00, 0x53, 0x38, 0x53, 0x37, 0x55,
+ 0x36, 0x10, 0x6f, 0xf9, 0x6f, 0xfa, 0xd0, 0x09, 0x52, 0xfc, 0x04,
+ 0x38, 0x52, 0xfb, 0x0c, 0x37, 0x66, 0xfc, 0x6c, 0xfb, 0x7a, 0x36,
+ 0xbf, 0xeb, 0x18, 0x60, 0xd0, 0x20, 0x70, 0x3f, 0x71, 0xc0, 0x7f,
+ 0x00, 0x24, 0x00, 0x12, 0x00, 0x52, 0x00, 0x08, 0x00, 0x5e, 0x00,
+ 0x07, 0x00, 0x65, 0x05, 0x01, 0x08, 0x08, 0x78, 0x64, 0x00, 0x6a,
+ 0x00, 0x04, 0x00, 0x6e, 0x01, 0x03, 0x00, 0x6f, 0x00, 0x05, 0x00,
+ 0x74, 0x02, 0x01, 0x01, 0xff, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
+};
diff --git a/drivers/input/keyboard/cypressbln/u1-cypress-gpio.h b/drivers/input/keyboard/cypressbln/u1-cypress-gpio.h
new file mode 100644
index 0000000..36296e1
--- /dev/null
+++ b/drivers/input/keyboard/cypressbln/u1-cypress-gpio.h
@@ -0,0 +1,28 @@
+#ifndef __U1_CYPRESS_GPIO_H__
+#define __U1_CYPRESS_GPIO_H__
+
+extern unsigned int system_rev;
+
+#if defined (CONFIG_MACH_U1_REV00PRE) || defined (CONFIG_MACH_U1_REV01PRE) \
+ || defined (CONFIG_MACH_U1_REV00)
+#define _3_GPIO_TOUCH_EN S5PV310_GPE3(3)
+#define _3_GPIO_TOUCH_INT S5PV310_GPE3(7)
+#define _3_GPIO_TOUCH_INT_AF S3C_GPIO_SFN(0xf)
+#define _3_TOUCH_SDA_28V S5PV310_GPE4(0)
+#define _3_TOUCH_SCL_28V S5PV310_GPE4(1)
+
+#define IRQ_TOUCH_INT gpio_to_irq(_3_GPIO_TOUCH_INT)
+
+#else
+
+#define _3_GPIO_TOUCH_EN -1
+#define _3_GPIO_TOUCH_INT GPIO_3_TOUCH_INT
+#define _3_GPIO_TOUCH_INT_AF S3C_GPIO_SFN(0xf)
+#define _3_TOUCH_SDA_28V GPIO_3_TOUCH_SDA
+#define _3_TOUCH_SCL_28V GPIO_3_TOUCH_SCL
+
+#define IRQ_TOUCH_INT gpio_to_irq(_3_GPIO_TOUCH_INT)
+#endif
+
+
+#endif
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 0a619c5..c0531c2 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -1811,6 +1811,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
+ /* Verify that a device really has an endpoint */
+ if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+ dev_err(&intf->dev,
+ "interface has %d endpoints, but must have minimum 1\n",
+ intf->altsetting[0].desc.bNumEndpoints);
+ err = -EINVAL;
+ goto fail3;
+ }
endpoint = &intf->altsetting[0].endpoint[0].desc;
/* Go set up our URB, which is called when the tablet receives
@@ -1853,7 +1861,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (i == ARRAY_SIZE(speeds)) {
dev_info(&intf->dev,
"Aiptek tried all speeds, no sane response\n");
- goto fail2;
+ err = -EINVAL;
+ goto fail3;
}
/* Associate this driver's struct with the usb interface.
diff --git a/drivers/input/touchscreen/mxt224_u1.c b/drivers/input/touchscreen/mxt224_u1.c
index 5a243fb..8b81017 100644
--- a/drivers/input/touchscreen/mxt224_u1.c
+++ b/drivers/input/touchscreen/mxt224_u1.c
@@ -1210,6 +1210,10 @@ static int __devinit mxt224_init_touch_driver(struct mxt224_data *data)
return ret;
}
+#if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN) && defined(CONFIG_TOUCHKEY_BLN)
+void (*mxt224_touch_cb)(void) = NULL;
+#endif
+
static void report_input_data(struct mxt224_data *data)
{
int i;
@@ -1336,6 +1340,9 @@ static void report_input_data(struct mxt224_data *data)
level);
copy_data->lock_status = 1;
}
+ #if defined(CONFIG_KEYBOARD_CYPRESS_TOUCH_BLN) && defined(CONFIG_TOUCHKEY_BLN)
+ if(mxt224_touch_cb!=NULL) (*mxt224_touch_cb)();
+ #endif
}
}
diff --git a/drivers/media/video/s5c73m3.c b/drivers/media/video/s5c73m3.c
index bd08605..3d24612 100644
--- a/drivers/media/video/s5c73m3.c
+++ b/drivers/media/video/s5c73m3.c
@@ -579,6 +579,7 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd)
u16 read_val;
int i, rxSize;
int err = 0;
+ struct file *fp = NULL;
mm_segment_t old_fs;
long ret = 0;
char fw_path[25] = {0,};
@@ -729,6 +730,17 @@ retry:
set_fs(KERNEL_DS);
if (IntOriginalCRC == DataCRC) {
+ fp = filp_open(fw_path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (IS_ERR(fp) || fp == NULL) {
+ cam_err("failed to open %s, err %ld\n",
+ fw_path, PTR_ERR(fp));
+ err = -EINVAL;
+ goto out;
+ }
+
+ ret = vfs_write(fp, (char __user *)data_memory,
+ state->sensor_size, &fp->f_pos);
+
if (camfw_info[S5C73M3_SD_CARD].opened == 0) {
memcpy(state->phone_fw,
state->sensor_fw,
@@ -749,6 +761,9 @@ retry:
}
}
+ if (fp != NULL)
+ filp_close(fp, current->files);
+
out:
set_fs(old_fs);
return err;
@@ -1049,14 +1064,17 @@ request_fw:
state->fw_index = S5C73M3_IN_DATA;
}
} else {
+ cam_dbg("can't open %s Ver. Firmware. so, download from F-ROM\n",
+ state->sensor_fw);
if (fw != NULL)
release_firmware(fw);
- memcpy(state->phone_fw, state->sensor_fw, S5C73M3_FW_VER_LEN);
- fw_requested = 0;
- err = 0;
- goto out;
-
+ retVal = s5c73m3_reset_module(sd, true);
+ CHECK_ERR(retVal);
+ retVal = s5c73m3_get_sensor_fw_binary(sd);
+ CHECK_ERR(retVal);
+ copied_fw_binary = 1;
+ goto request_fw;
}
}
@@ -1232,7 +1250,7 @@ static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download)
/* retVal = 0 : Same Version
retVal < 0 : Phone Version is latest Version than sensorFW.
retVal > 0 : Sensor Version is latest version than phoenFW. */
- if (retVal < 0 || download) {
+ if (retVal <= 0 || download) {
cam_dbg("Loading From PhoneFW......\n");
/* In case that there is no FW in phone and FW needs to be
@@ -1252,10 +1270,10 @@ static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download)
CHECK_ERR(err);
}
} else {
- cam_dbg("Loading From FROM......\n");
- err = s5c73m3_reset_module(sd, false);
+ cam_dbg("Loading From SensorFW......\n");
+ err = s5c73m3_reset_module(sd, true);
CHECK_ERR(err);
- err = s5c73m3_SPI_booting_by_ISP(sd);
+ err = s5c73m3_get_sensor_fw_binary(sd);
CHECK_ERR(err);
}
@@ -2663,6 +2681,7 @@ static int s5c73m3_load_fw(struct v4l2_subdev *sd)
const struct firmware *fw;
char fw_path[20] = {0,};
char fw_path_in_data[25] = {0,};
+ u8 *buf = NULL;
int err = 0;
int txSize = 0;
@@ -2732,25 +2751,30 @@ static int s5c73m3_load_fw(struct v4l2_subdev *sd)
}
/*cam_dbg("start, size %d Bytes\n", fw->size);*/
- memcpy((void *) &data_memory, (void *) fw->data, fw->size);
+ buf = (u8 *)fw->data;
fsize = fw->size;
}
txSize = 60*1024; /*60KB*/
- err = s5c73m3_spi_write((char *)&data_memory,
- fsize, txSize);
- if (err < 0) {
- cam_err("s5c73m3_spi_write falied\n");
- goto out;
+ if (state->fw_index != S5C73M3_IN_SYSTEM) {
+ err = s5c73m3_spi_write((char *)&data_memory,
+ fsize, txSize);
+ if (err < 0) {
+ cam_err("s5c73m3_spi_write falied\n");
+ goto out;
+ }
+ } else {
+ err = s5c73m3_spi_write((char *)buf, fsize, txSize);
}
-
out:
if (state->fw_index == S5C73M3_SD_CARD ||
state->fw_index == S5C73M3_IN_DATA) {
if (!IS_ERR(fp) && fp != NULL)
filp_close(fp, current->files);
+ vfree(buf);
+
set_fs(old_fs);
} else {
release_firmware(fw);
@@ -3488,14 +3512,25 @@ static int s5c73m3_init(struct v4l2_subdev *sd, u32 val)
err = s5c73m3_i2c_check_status_with_CRC(sd);
if (err < 0) {
cam_err("ISP is not ready. retry loading fw!!\n");
-
- err = s5c73m3_check_fw(sd, 0);
- if (err < 0) {
- cam_dbg("isp.bad_fw is true\n");
- state->isp.bad_fw = 1;
+ /* retry */
+ retVal = s5c73m3_check_fw_date(sd);
+
+ /* retVal = 0 : Same Version
+ retVal < 0 : Phone Version is latest Version than sensorFW.
+ retVal > 0 : Sensor Version is latest version than phoenFW. */
+ if (retVal <= 0) {
+ cam_dbg("Loading From PhoneFW......\n");
+ err = s5c73m3_reset_module(sd, false);
+ CHECK_ERR(err);
+ err = s5c73m3_SPI_booting(sd);
+ CHECK_ERR(err);
+ } else {
+ cam_dbg("Loading From SensorFW......\n");
+ err = s5c73m3_reset_module(sd, true);
+ CHECK_ERR(err);
+ err = s5c73m3_get_sensor_fw_binary(sd);
+ CHECK_ERR(err);
}
-
- CHECK_ERR(err);
}
state->isp.bad_fw = 0;
diff --git a/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h b/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h
index cbf6cab..c68980d 100644
--- a/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h
+++ b/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h
@@ -41,7 +41,7 @@
#define SAMSUNG_MFC_DEV_NAME "/dev/s3c-mfc"
#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412)
-#define SUPPORT_SLICE_ENCODING 0 // originaly 1, but we're missing matching userspace
+#define SUPPORT_SLICE_ENCODING 0 // originally 1, but we're missing matching userspace
#else
#define SUPPORT_SLICE_ENCODING 0
#endif
@@ -136,7 +136,7 @@ typedef enum {
/* C210 specific feature */
MFC_ENC_SETCONF_VUI_INFO,
MFC_ENC_SETCONF_I_PERIOD,
- MFC_ENC_SETCONF_SPS_PPS_GEN,
+ MFC_ENC_SETCONF_SPS_PPS_GEN,
MFC_ENC_SETCONF_HIER_P,
MFC_ENC_SETCONF_SEI_GEN,
diff --git a/drivers/media/video/samsung/mfc5x/mfc_buf.h b/drivers/media/video/samsung/mfc5x/mfc_buf.h
index 28ef0d6..f93ed26 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_buf.h
+++ b/drivers/media/video/samsung/mfc5x/mfc_buf.h
@@ -34,8 +34,13 @@
#define ALIGN_H_L_L 16 /* Linear, Vertical, Luma */
#define ALIGN_H_L_C 8 /* Linear, Vertical, Chroma */
+#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_GC1)
+/* System */ /* Size, Port, Align */
+#define MFC_FW_SYSTEM_SIZE (0x100000) /* 1MB, A, N(4KB for VMEM) */
+#else
/* System */ /* Size, Port, Align */
#define MFC_FW_SYSTEM_SIZE (0x80000) /* 512KB, A, N(4KB for VMEM) */
+#endif
/* Instance */
#define MFC_CTX_SIZE_L (0x96000) /* 600KB, N, 2KB, H.264 Decoding only */
diff --git a/drivers/media/video/samsung/mfc5x/mfc_cmd.c b/drivers/media/video/samsung/mfc5x/mfc_cmd.c
index 38b4757..ba4faf9 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_cmd.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_cmd.c
@@ -310,7 +310,7 @@ int mfc_cmd_inst_open(struct mfc_inst_ctx *ctx)
}
memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
- h2r_args.arg[0] = ctx->codecid;
+ h2r_args.arg[0] = (1 << 29) | ctx->codecid;
h2r_args.arg[1] = crc << 31 | pixelcache;
h2r_args.arg[2] = ctx->ctxbufofs;
h2r_args.arg[3] = ctx->ctxbufsize;
diff --git a/drivers/media/video/samsung/mfc5x/mfc_dec.c b/drivers/media/video/samsung/mfc5x/mfc_dec.c
index d3d336a..f0a7c4d 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_dec.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_dec.c
@@ -155,10 +155,6 @@ static void dump_stream(unsigned long address, unsigned int size)
ctx->ctxbufofs = mfc_mem_base_ofs(alloc->real) >> 11;
ctx->ctxbufsize = alloc->size;
- memset((void *)alloc->addr, 0, alloc->size);
-
- mfc_mem_cache_clean((void *)alloc->addr, alloc->size);
-
return 0;
}
@@ -176,10 +172,6 @@ static int h264_alloc_ctx_buf(struct mfc_inst_ctx *ctx)
ctx->ctxbufofs = mfc_mem_base_ofs(alloc->real) >> 11;
ctx->ctxbufsize = alloc->size;
- memset((void *)alloc->addr, 0, alloc->size);
-
- mfc_mem_cache_clean((void *)alloc->addr, alloc->size);
-
return 0;
}
@@ -1591,56 +1583,6 @@ static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize)
return -1;
}
-static int CheckDecStartCode(unsigned char *src_mem,
- unsigned int nstreamSize,
- SSBSIP_MFC_CODEC_TYPE nCodecType)
-{
- unsigned int index = 0;
- /* Check Start Code within "isearchSize" bytes */
- unsigned int isearchSize = 20;
- unsigned int nShift = 0;
- unsigned char nFlag = 0xFF;
-
- if (nCodecType == H263_DEC) {
- nFlag = 0x08;
- nShift = 4;
- } else if (nCodecType == MPEG4_DEC) {
- nFlag = 0x01;
- nShift = 0;
- } else if (nCodecType == H264_DEC) {
- nFlag = 0x01;
- nShift = 0;
- } else
- nFlag = 0xFF;
-
- /* Last frame detection from user */
- if (nstreamSize == 0)
- nFlag = 0xFF;
-
- if (nFlag == 0xFF)
- return 0;
-
- if (nstreamSize > 3) {
- if (nstreamSize > isearchSize) {
- for (index = 0; index < isearchSize-3; index++) {
- if ((src_mem[index] == 0x00) &&
- (src_mem[index+1] == 0x00) &&
- ((src_mem[index+2] >> nShift) == nFlag))
- return index;
- }
- } else {
- for (index = 0; index < nstreamSize - 3; index++) {
- if ((src_mem[index] == 0x00) &&
- (src_mem[index+1] == 0x00) &&
- ((src_mem[index+2] >> nShift) == nFlag))
- return index;
- }
- }
- }
-
- return -1;
-}
-
void mfc_init_decoders(void)
{
list_add_tail(&unknown_dec.list, &mfc_decoders);
@@ -1904,6 +1846,20 @@ int mfc_init_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args)
}
#endif
+#if defined(CONFIG_MACH_GC1) && defined(CONFIG_EXYNOS4_CPUFREQ)
+ if ((ctx->width >= 1280 && ctx->height >= 720)
+ || (ctx->width >= 720 && ctx->height >= 1280)) {
+ if (atomic_read(&ctx->dev->cpufreq_lock_cnt) == 0) {
+ if (0 == ctx->dev->cpufreq_level) /* 800MHz */
+ exynos_cpufreq_get_level(800000, &ctx->dev->cpufreq_level);
+ exynos_cpufreq_lock(DVFS_LOCK_ID_MFC, ctx->dev->cpufreq_level);
+ mfc_dbg("[%s] CPU Freq Locked 800MHz!\n", __func__);
+ }
+ atomic_inc(&ctx->dev->cpufreq_lock_cnt);
+ ctx->cpufreq_flag = true;
+ }
+#endif
+
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ)
if ((ctx->width >= 1280 && ctx->height >= 720)
|| (ctx->width >= 720 && ctx->height >= 1280)) {
@@ -1919,27 +1875,27 @@ int mfc_init_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args)
#endif
#ifdef CONFIG_BUSFREQ_OPP
- if (HD_MOVIE_SIZE_MULTIPLY_WIDTH_HEIGHT > (ctx->width * ctx->height)) {
- if (atomic_read(&ctx->dev->dmcthreshold_lock_cnt) == 0) {
- mfc_info("Implement set dmc_max_threshold\n");
- if (soc_is_exynos4212()) {
+if (HD_MOVIE_SIZE_MULTIPLY_WIDTH_HEIGHT > (ctx->width * ctx->height)) {
+ if (atomic_read(&ctx->dev->dmcthreshold_lock_cnt) == 0) {
+ mfc_info("Implement set dmc_max_threshold\n");
+ if (soc_is_exynos4212()) {
+ dmc_max_threshold =
+ EXYNOS4212_DMC_MAX_THRESHOLD + DECODING_LOAD;
+ } else if (soc_is_exynos4412()) {
+ if (samsung_rev() >= EXYNOS4412_REV_2_0)
dmc_max_threshold =
- EXYNOS4212_DMC_MAX_THRESHOLD + 5;
- } else if (soc_is_exynos4412()) {
- if (samsung_rev() >= EXYNOS4412_REV_2_0)
- dmc_max_threshold =
- PRIME_DMC_MAX_THRESHOLD + 5;
- else
- dmc_max_threshold =
- EXYNOS4412_DMC_MAX_THRESHOLD + 5;
- } else {
- pr_err("Unsupported model.\n");
- return -EINVAL;
- }
+ PRIME_DMC_MAX_THRESHOLD + DECODING_LOAD;
+ else
+ dmc_max_threshold =
+ EXYNOS4412_DMC_MAX_THRESHOLD + DECODING_LOAD;
+ } else {
+ pr_err("Unsupported model.\n");
+ return -EINVAL;
}
- atomic_inc(&ctx->dev->dmcthreshold_lock_cnt);
- ctx->dmcthreshold_flag = true;
}
+ atomic_inc(&ctx->dev->dmcthreshold_lock_cnt);
+ ctx->dmcthreshold_flag = true;
+}
#endif
/*
* allocate & set codec buffers
@@ -2146,7 +2102,6 @@ static int mfc_decoding_frame(struct mfc_inst_ctx *ctx, struct mfc_dec_exe_arg *
int display_chroma_addr;
int display_frame_type;
int display_frame_tag;
- unsigned char *stream_vir;
int ret;
struct mfc_dec_ctx *dec_ctx = (struct mfc_dec_ctx *)ctx->c_priv;
long mem_ofs;
@@ -2154,22 +2109,6 @@ static int mfc_decoding_frame(struct mfc_inst_ctx *ctx, struct mfc_dec_exe_arg *
void *ump_handle;
#endif
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
- if (!ctx->drm_flag) {
-#endif
- /* Check Frame Start code */
- stream_vir = phys_to_virt(exe_arg->in_strm_buf + start_ofs);
- ret = CheckDecStartCode(stream_vir, exe_arg->in_strm_size,
- exe_arg->in_codec_type);
- if (ret < 0) {
- mfc_err("Frame Check start Code Failed\n");
- /* FIXME: Need to define proper error */
- return MFC_FRM_BUF_SIZE_FAIL;
- }
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
- }
-#endif
-
/* Set Frame Tag */
write_shm(ctx, dec_ctx->frametag, SET_FRAME_TAG);
@@ -2405,7 +2344,9 @@ int mfc_exec_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args)
if (ctx->resolution_status == RES_SET_CHANGE) {
ret = mfc_decoding_frame(ctx, exe_arg, &consumed);
#ifndef CONFIG_SLP
- } else if ((ctx->resolution_status == RES_WAIT_FRAME_DONE) &&
+ }
+
+ if ((ctx->resolution_status == RES_WAIT_FRAME_DONE) &&
(exe_arg->out_display_status == DISP_S_FINISH)) {
exe_arg->out_display_status = DISP_S_RES_CHANGE;
ret = mfc_change_resolution(ctx, exe_arg);
diff --git a/drivers/media/video/samsung/mfc5x/mfc_dev.c b/drivers/media/video/samsung/mfc5x/mfc_dev.c
index 23bc10d..43ea79d 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_dev.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_dev.c
@@ -213,7 +213,7 @@ static int mfc_open(struct inode *inode, struct file *file)
mutex_lock(&mfcdev->lock);
-#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0)
+#ifdef CONFIG_USE_MFC_CMA
if (atomic_read(&mfcdev->inst_cnt) == 0) {
size_t size = 0x02800000;
mfcdev->cma_vaddr = dma_alloc_coherent(mfcdev->device, size,
@@ -368,8 +368,6 @@ static int mfc_open(struct inode *inode, struct file *file)
mfc_ctx->ctxbufofs = mfc_mem_base_ofs(alloc->real) >> 11;
mfc_ctx->ctxbufsize = alloc->size;
- memset((void *)alloc->addr, 0, alloc->size);
- mfc_mem_cache_clean((void *)alloc->addr, alloc->size);
}
#endif
@@ -392,7 +390,7 @@ static int mfc_open(struct inode *inode, struct file *file)
ret = mfc_queue_alloc(mfc_ctx);
if (ret < 0) {
mfc_err("mfc_queue_alloc failed\n");
- goto err_inst_ctx;
+ goto err_queue_alloc;
}
#endif
@@ -403,9 +401,17 @@ static int mfc_open(struct inode *inode, struct file *file)
return 0;
+#ifdef CONFIG_SLP_DMABUF
+err_queue_alloc:
+#endif
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
err_drm_ctx:
#endif
+ mfcdev->inst_ctx[inst_id] = NULL;
+ atomic_dec(&mfcdev->inst_cnt);
+
+ mfc_destroy_inst(mfc_ctx);
+
err_inst_ctx:
err_inst_id:
err_inst_cnt:
@@ -423,7 +429,16 @@ err_pwr_enable:
#endif
err_fw_state:
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+#ifdef CONFIG_USE_MFC_CMA
+ if (atomic_read(&mfcdev->inst_cnt) == 0) {
+ size_t size = 0x02800000;
+ dma_free_coherent(mfcdev->device, size, mfcdev->cma_vaddr,
+ mfcdev->cma_dma_addr);
+ printk(KERN_INFO "%s[%d] size 0x%x, vaddr 0x%x, base 0x0%x\n",
+ __func__, __LINE__, (int)size,
+ (int) mfcdev->cma_vaddr,
+ (int)mfcdev->cma_dma_addr);
+ }
#endif
mutex_unlock(&mfcdev->lock);
@@ -476,6 +491,19 @@ static int mfc_release(struct inode *inode, struct file *file)
}
#endif
+#if defined(CONFIG_MACH_GC1) && defined(CONFIG_EXYNOS4_CPUFREQ)
+ /* Release MFC & CPU Frequency lock for High resolution */
+ if (mfc_ctx->cpufreq_flag == true) {
+ atomic_dec(&dev->cpufreq_lock_cnt);
+ mfc_ctx->cpufreq_flag = false;
+ if (atomic_read(&dev->cpufreq_lock_cnt) == 0) {
+ /* release Freq lock back to normal */
+ exynos_cpufreq_lock_free(DVFS_LOCK_ID_MFC);
+ mfc_dbg("[%s] CPU Freq lock Released Normal!\n", __func__);
+ }
+ }
+#endif
+
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ)
/* Release MFC & CPU Frequency lock for High resolution */
if (mfc_ctx->cpufreq_flag == true) {
@@ -565,7 +593,7 @@ static int mfc_release(struct inode *inode, struct file *file)
err_pwr_disable:
-#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0)
+#ifdef CONFIG_USE_MFC_CMA
if (atomic_read(&mfcdev->inst_cnt) == 0) {
size_t size = 0x02800000;
dma_free_coherent(mfcdev->device, size, mfcdev->cma_vaddr,
@@ -977,6 +1005,16 @@ static long mfc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* RMVME: need locking ? */
mutex_lock(&dev->lock);
+ if (mfc_ctx->state < INST_STATE_SETUP) {
+ mfc_err("IOCTL_MFC_GET_CONFIG invalid state: 0x%08x\n",
+ mfc_ctx->state);
+ in_param.ret_code = MFC_STATE_INVALID;
+ ret = -EINVAL;
+
+ mutex_unlock(&dev->lock);
+ break;
+ }
+
cfg_arg = (struct mfc_config_arg *)&in_param.args;
in_param.ret_code = mfc_get_inst_cfg(mfc_ctx, cfg_arg->type,
@@ -1083,9 +1121,13 @@ static int mfc_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long start, size;
#endif
#endif
+ mfc_info("%s line : %d IN\n", __func__, __LINE__);
mfc_ctx = (struct mfc_inst_ctx *)file->private_data;
- if (!mfc_ctx)
+ if (!mfc_ctx) {
+ mfc_err("%s line : %d mfc_ctx is NULL\n",
+ __func__, __LINE__);
return -EINVAL;
+ }
#if !(defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(CONFIG_S5P_VMEM))
dev = mfc_ctx->dev;
@@ -1325,9 +1367,30 @@ static int mfc_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
+#ifdef CONFIG_USE_MFC_CMA
+/* FIXME: workaround for CMA migration fail due to page lock */
+static int mfc_open_with_retry(struct inode *inode, struct file *file)
+{
+ int ret;
+ int i = 0;
+
+ ret = mfc_open(inode, file);
+
+ while (ret == -ENOMEM && i++ < 10) {
+ msleep(1000);
+ ret = mfc_open(inode, file);
+ }
+
+ return ret;
+}
+#define MFC_OPEN mfc_open_with_retry
+#else
+#define MFC_OPEN mfc_open
+#endif
+
static const struct file_operations mfc_fops = {
.owner = THIS_MODULE,
- .open = mfc_open,
+ .open = MFC_OPEN,
.release = mfc_release,
.unlocked_ioctl = mfc_ioctl,
.mmap = mfc_mmap,
diff --git a/drivers/media/video/samsung/mfc5x/mfc_dev.h b/drivers/media/video/samsung/mfc5x/mfc_dev.h
index bb2095c..16bd027 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_dev.h
+++ b/drivers/media/video/samsung/mfc5x/mfc_dev.h
@@ -114,6 +114,10 @@ struct mfc_dev {
#if defined(CONFIG_BUSFREQ)
atomic_t busfreq_lock_cnt; /* Bus frequency Lock count */
#endif
+#if defined(CONFIG_MACH_GC1) && defined(CONFIG_EXYNOS4_CPUFREQ)
+ atomic_t cpufreq_lock_cnt; /* CPU frequency Lock count */
+ int cpufreq_level; /* CPU frequency leve */
+#endif
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ)
atomic_t cpufreq_lock_cnt; /* CPU frequency Lock count */
int cpufreq_level; /* CPU frequency leve */
diff --git a/drivers/media/video/samsung/mfc5x/mfc_enc.c b/drivers/media/video/samsung/mfc5x/mfc_enc.c
index 65d7b6b..f2dc039 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_enc.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_enc.c
@@ -55,10 +55,6 @@ static LIST_HEAD(mfc_encoders);
ctx->ctxbufofs = mfc_mem_base_ofs(alloc->real) >> 11;
ctx->ctxbufsize = alloc->size;
- memset((void *)alloc->addr, 0, alloc->size);
-
- mfc_mem_cache_clean((void *)alloc->addr, alloc->size);
-
return 0;
}
@@ -101,7 +97,7 @@ int get_init_arg(struct mfc_inst_ctx *ctx, void *arg)
write_reg((1 << 1) | 0x1, MFC_ENC_MSLICE_CTRL);
if (init_arg->cmn.in_ms_arg < 1900)
init_arg->cmn.in_ms_arg = 1900;
- write_reg(init_arg->cmn.in_ms_arg, MFC_ENC_MSLICE_BIT);
+ write_reg(init_arg->cmn.in_ms_arg * 8, MFC_ENC_MSLICE_BIT);
} else {
write_reg(0, MFC_ENC_MSLICE_CTRL);
write_reg(0, MFC_ENC_MSLICE_MB);
@@ -586,8 +582,7 @@ static int h264_pre_seq_start(struct mfc_inst_ctx *ctx)
if (h264->sps_pps_gen == 1) {
write_shm(ctx,
- ((h264->sps_pps_gen << 8) |
- read_shm(ctx, EXT_ENC_CONTROL)),
+ ((h264->sps_pps_gen << 8) | read_shm(ctx, EXT_ENC_CONTROL)),
EXT_ENC_CONTROL);
}
@@ -1066,10 +1061,8 @@ static int h264_set_codec_cfg(struct mfc_inst_ctx *ctx, int type, void *arg)
case MFC_ENC_SETCONF_SPS_PPS_GEN:
mfc_dbg("MFC_ENC_SETCONF_SPS_PPS_GEN : %d\n", ctx->state);
- if ((ctx->state < INST_STATE_CREATE) ||
- (ctx->state > INST_STATE_EXE)) {
- mfc_err("MFC_ENC_SETCONF_SPS_PPS_GEN : "
- " state is invalid\n");
+ if ((ctx->state < INST_STATE_CREATE) || (ctx->state > INST_STATE_EXE)) {
+ mfc_err("MFC_ENC_SETCONF_SPS_PPS_GEN : state is invalid\n");
return MFC_STATE_INVALID;
}
@@ -1079,6 +1072,7 @@ static int h264_set_codec_cfg(struct mfc_inst_ctx *ctx, int type, void *arg)
h264->sps_pps_gen = 0;
break;
+
default:
mfc_dbg("invalid set cfg type: 0x%08x\n", type);
ret = -2;
@@ -1548,6 +1542,22 @@ int mfc_init_encoding(struct mfc_inst_ctx *ctx, union mfc_args *args)
}
#endif
+#if defined(CONFIG_MACH_GC1) && defined(CONFIG_EXYNOS4_CPUFREQ)
+ if ((ctx->width >= 1280 && ctx->height >= 720)
+ || (ctx->width >= 720 && ctx->height >= 1280)) {
+ if (atomic_read(&ctx->dev->cpufreq_lock_cnt) == 0) {
+ if (0 == ctx->dev->cpufreq_level) /* 800MHz */
+ exynos_cpufreq_get_level(800000,
+ &ctx->dev->cpufreq_level);
+ exynos_cpufreq_lock(DVFS_LOCK_ID_MFC,
+ ctx->dev->cpufreq_level);
+ mfc_dbg("[%s] CPU Freq Locked 800MHz!\n", __func__);
+ }
+ atomic_inc(&ctx->dev->cpufreq_lock_cnt);
+ ctx->cpufreq_flag = true;
+ }
+#endif
+
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ)
if ((ctx->width >= 320 && ctx->height >= 240)
|| (ctx->width >= 240 && ctx->height >= 320)) {
diff --git a/drivers/media/video/samsung/mfc5x/mfc_inst.c b/drivers/media/video/samsung/mfc5x/mfc_inst.c
index ef0d0e0..33736c9 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_inst.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_inst.c
@@ -55,6 +55,9 @@ struct mfc_inst_ctx *mfc_create_inst(void)
#ifdef CONFIG_BUSFREQ
ctx->busfreq_flag = false;
#endif
+#if defined(CONFIG_MACH_GC1) && defined(CONFIG_EXYNOS4_CPUFREQ)
+ ctx->cpufreq_flag = false;
+#endif
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ)
ctx->cpufreq_flag = false;
#endif
@@ -193,34 +196,34 @@ int mfc_set_inst_cfg(struct mfc_inst_ctx *ctx, int type, void *arg)
}
switch (type) {
- case MFC_DEC_SETCONF_POST_ENABLE:
- case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM:
- case MFC_DEC_SETCONF_DISPLAY_DELAY:
- case MFC_DEC_SETCONF_IS_LAST_FRAME:
- case MFC_DEC_SETCONF_SLICE_ENABLE:
- case MFC_DEC_SETCONF_CRC_ENABLE:
- case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT:
- case MFC_DEC_SETCONF_FRAME_TAG:
- case MFC_DEC_SETCONF_IMMEDIATELY_DISPLAY:
- case MFC_DEC_SETCONF_DPB_FLUSH:
- case MFC_DEC_SETCONF_SEI_PARSE:
- case MFC_DEC_SETCONF_PIXEL_CACHE:
- case MFC_ENC_SETCONF_FRAME_TYPE:
- case MFC_ENC_SETCONF_CHANGE_FRAME_RATE:
- case MFC_ENC_SETCONF_CHANGE_BIT_RATE:
- case MFC_ENC_SETCONF_FRAME_TAG:
- case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP:
- case MFC_ENC_SETCONF_VUI_INFO:
- case MFC_ENC_SETCONF_I_PERIOD:
- case MFC_ENC_SETCONF_HIER_P:
- case MFC_ENC_SETCONF_SEI_GEN:
- case MFC_ENC_SETCONF_FRAME_PACKING:
- case MFC_ENC_SETCONF_SPS_PPS_GEN:
- if (ctx->c_ops->set_codec_cfg) {
- if ((ctx->c_ops->set_codec_cfg(ctx, type, arg)) < 0)
- return MFC_SET_CONF_FAIL;
- }
- break;
+ case MFC_DEC_SETCONF_POST_ENABLE:
+ case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM:
+ case MFC_DEC_SETCONF_DISPLAY_DELAY:
+ case MFC_DEC_SETCONF_IS_LAST_FRAME:
+ case MFC_DEC_SETCONF_SLICE_ENABLE:
+ case MFC_DEC_SETCONF_CRC_ENABLE:
+ case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT:
+ case MFC_DEC_SETCONF_FRAME_TAG:
+ case MFC_DEC_SETCONF_IMMEDIATELY_DISPLAY:
+ case MFC_DEC_SETCONF_DPB_FLUSH:
+ case MFC_DEC_SETCONF_SEI_PARSE:
+ case MFC_DEC_SETCONF_PIXEL_CACHE:
+ case MFC_ENC_SETCONF_FRAME_TYPE:
+ case MFC_ENC_SETCONF_CHANGE_FRAME_RATE:
+ case MFC_ENC_SETCONF_CHANGE_BIT_RATE:
+ case MFC_ENC_SETCONF_FRAME_TAG:
+ case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP:
+ case MFC_ENC_SETCONF_VUI_INFO:
+ case MFC_ENC_SETCONF_I_PERIOD:
+ case MFC_ENC_SETCONF_HIER_P:
+ case MFC_ENC_SETCONF_SEI_GEN:
+ case MFC_ENC_SETCONF_FRAME_PACKING:
+ case MFC_ENC_SETCONF_SPS_PPS_GEN:
+ if (ctx->c_ops->set_codec_cfg) {
+ if ((ctx->c_ops->set_codec_cfg(ctx, type, arg)) < 0)
+ return MFC_SET_CONF_FAIL;
+ }
+ break;
default:
mfc_err("invalid set config type: 0x%08x\n", type);
diff --git a/drivers/media/video/samsung/mfc5x/mfc_inst.h b/drivers/media/video/samsung/mfc5x/mfc_inst.h
index b78dd91..eedd6f1 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_inst.h
+++ b/drivers/media/video/samsung/mfc5x/mfc_inst.h
@@ -158,6 +158,10 @@ struct mfc_inst_ctx {
int busfreq_flag; /* context bus frequency flag */
#endif
+#if defined(CONFIG_MACH_GC1) && defined(CONFIG_EXYNOS4_CPUFREQ)
+ int cpufreq_flag; /* context CPU frequency flag*/
+#endif
+
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ)
int cpufreq_flag; /* context CPU frequency flag*/
#endif
diff --git a/drivers/media/video/samsung/mfc5x/mfc_mem.c b/drivers/media/video/samsung/mfc5x/mfc_mem.c
index 051e4c0..a4f5345 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_mem.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_mem.c
@@ -551,12 +551,26 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
/* early allocator */
#if defined(CONFIG_S5P_MEM_CMA)
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0)
+#ifdef CONFIG_USE_MFC_CMA
+#if defined(CONFIG_MACH_M0)
cma_infos[0].lower_bound = 0x5C100000;
cma_infos[0].upper_bound = 0x5F200000;
cma_infos[0].total_size = 0x03100000;
cma_infos[0].free_size = 0x03100000;
cma_infos[0].count = 1;
+#elif defined(CONFIG_MACH_GC1) || defined(CONFIG_MACH_GC2PD)
+ cma_infos[0].lower_bound = 0x50200000;
+ cma_infos[0].upper_bound = 0x53300000;
+ cma_infos[0].total_size = 0x03100000;
+ cma_infos[0].free_size = 0x03100000;
+ cma_infos[0].count = 1;
+#elif defined(CONFIG_MACH_TAB3) || defined(CONFIG_MACH_ZEST)
+ cma_infos[0].lower_bound = 0x58100000;
+ cma_infos[0].upper_bound = 0x5B200000;
+ cma_infos[0].total_size = 0x03100000;
+ cma_infos[0].free_size = 0x03100000;
+ cma_infos[0].count = 1;
+#endif
#else
if (cma_info(&cma_infos[0], dev->device, "A")) {
mfc_info("failed to get CMA info of 'mfc-secure'\n");
@@ -611,8 +625,14 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
return -ENOMEM;
}
-#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0)
+#ifdef CONFIG_USE_MFC_CMA
+#if defined(CONFIG_MACH_GC1) || defined(CONFIG_MACH_GC2PD)
+ base[0] = 0x50200000;
+#elif defined(CONFIG_MACH_TAB3) || defined(CONFIG_MACH_ZEST)
+ base[0] = 0x58100000;
+#else
base[0] = 0x5c100000;
+#endif
dev->mem_infos[0].base = base[0];
dev->mem_infos[0].size = size;
dev->mem_infos[0].addr = phys_to_virt(base[0]);
@@ -707,6 +727,20 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
dev->mem_infos[0].size = size;
dev->mem_infos[0].addr = cma_get_virt(base[0], size, 0);
} else if (dev->mem_ports == 2) {
+#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_Q1_BD)
+ /* for MFC0:A */
+ cma_infos[0].lower_bound = 0x67200000;
+ cma_infos[0].upper_bound = 0x68400000;
+ cma_infos[0].total_size = 0x01200000;
+ cma_infos[0].free_size = 0x01200000;
+ cma_infos[0].count = 1;
+ /* for MFC1:B */
+ cma_infos[1].lower_bound = 0x68400000;
+ cma_infos[1].upper_bound = 0x6A000000;
+ cma_infos[1].total_size = 0x01C00000;
+ cma_infos[1].free_size = 0x01C00000;
+ cma_infos[1].count = 1;
+#else
if (cma_info(&cma_infos[0], dev->device, "A")) {
mfc_info("failed to get CMA info of 'mfc0'\n");
return -ENOMEM;
@@ -716,7 +750,7 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
mfc_info("failed to get CMA info of 'mfc1'\n");
return -ENOMEM;
}
-
+#endif
if (cma_infos[0].lower_bound > cma_infos[1].lower_bound)
cma_index = 1;
@@ -733,8 +767,12 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
base[0] = cma_alloc(dev->device, cma_index ? "B" : "A",
MFC_FW_SYSTEM_SIZE, ALIGN_128KB);
#else
+#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_Q1_BD)
+ base[0] = cma_index ? 0x68400000 : 0x67200000;
+#else
base[0] = cma_alloc(dev->device, cma_index ? "B" : "A", size, ALIGN_128KB);
#endif
+#endif
if (IS_ERR_VALUE(base[0])) {
mfc_err("failed to get rsv. memory from CMA on port #0");
return -ENOMEM;
@@ -742,7 +780,11 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
dev->mem_infos[0].base = base[0];
dev->mem_infos[0].size = size;
+#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_Q1_BD)
+ dev->mem_infos[0].addr = phys_to_virt(base[0]);
+#else
dev->mem_infos[0].addr = cma_get_virt(base[0], size, 0);
+#endif
/* swap CMA index */
cma_index = !cma_index;
@@ -760,8 +802,12 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
base[1] = cma_index ? cma_infos[1].lower_bound :
cma_infos[0].lower_bound;
#else
+#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_Q1_BD)
+ base[1] = cma_index ? 0x68400000 : 0x67200000;
+#else
base[1] = cma_alloc(dev->device, cma_index ? "B" : "A", size, ALIGN_128KB);
#endif
+#endif
if (IS_ERR_VALUE(base[1])) {
mfc_err("failed to get rsv. memory from CMA on port #1");
cma_free(base[0]);
@@ -770,7 +816,11 @@ int mfc_init_mem_mgr(struct mfc_dev *dev)
dev->mem_infos[1].base = base[1];
dev->mem_infos[1].size = size;
+#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_Q1_BD)
+ dev->mem_infos[1].addr = phys_to_virt(base[1]);
+#else
dev->mem_infos[1].addr = cma_get_virt(base[1], size, 0);
+#endif
} else {
mfc_err("failed to get reserved memory from CMA");
return -EPERM;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 0559caa..1daa392 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -61,27 +61,6 @@ config AD525X_DPOT_SPI
To compile this driver as a module, choose M here: the
module will be called ad525x_dpot-spi.
-config ANDROID_PMEM
- bool "Android pmem allocator"
- depends on MACH_U1 || MACH_PX || MACH_TRATS
- default n
-
-if ANDROID_PMEM
- comment "Reserved memory configurations"
-
-config ANDROID_PMEM_MEMSIZE_PMEM
- int "Memory size in kbytes for android surface using pmem"
- default "4096"
-
-config ANDROID_PMEM_MEMSIZE_PMEM_GPU1
- int "Memory size in kbytes for android surface using pmem_gpu1"
- default "10240"
-
-config ANDROID_PMEM_MEMSIZE_PMEM_CAM
- int "Memory size in kbytes for android camera using pmem_camera"
- default "4096"
-endif
-
config ATMEL_PWM
tristate "Atmel AT32/AT91 PWM support"
depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 44e4884..8d3b193 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
-obj-$(CONFIG_ANDROID_PMEM) += pmem.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
diff --git a/drivers/misc/modem_if/Kconfig b/drivers/misc/modem_if/Kconfig
index 6a6eeab..a425439 100644
--- a/drivers/misc/modem_if/Kconfig
+++ b/drivers/misc/modem_if/Kconfig
@@ -24,11 +24,21 @@ config CDMA_MODEM_CBP72
depends on SEC_MODEM
default n
+config CDMA_MODEM_CBP82
+ bool "modem chip : VIA CBP8.2"
+ depends on SEC_MODEM
+ default n
+
config LTE_MODEM_CMC221
bool "modem chip : SEC CMC221"
depends on SEC_MODEM
default n
+config UMTS_MODEM_SS222
+ bool "modem chip : SEC SS222"
+ depends on SEC_MODEM
+ default n
+
config CDMA_MODEM_MDM6600
bool "modem chip : QC MDM6600"
depends on SEC_MODEM
@@ -44,6 +54,11 @@ config GSM_MODEM_ESC6270
depends on SEC_MODEM
default n
+config CDMA_MODEM_QSC6085
+ bool "modem chip : Qualcomm QSC6085"
+ depends on SEC_MODEM
+ default n
+
config LINK_DEVICE_MIPI
bool "modem driver link device MIPI-HSI"
depends on SEC_MODEM
@@ -58,6 +73,7 @@ config LINK_DEVICE_PLD
bool "modem driver link device PLD"
depends on SEC_MODEM
default n
+
config LINK_DEVICE_USB
bool "modem driver link device USB"
depends on SEC_MODEM
@@ -78,6 +94,11 @@ config LINK_DEVICE_SPI
depends on SEC_MODEM
default n
+config BOOT_DEVICE_SPI
+ bool "modem driver boot device SPI"
+ depends on SEC_MODEM
+ default n
+
config WORKQUEUE_FRONT
bool "IPC: SPI workqueue front"
depends on SEC_MODEM
diff --git a/drivers/misc/modem_if/Makefile b/drivers/misc/modem_if/Makefile
index 5bd62ea..fbb00af 100644
--- a/drivers/misc/modem_if/Makefile
+++ b/drivers/misc/modem_if/Makefile
@@ -2,7 +2,7 @@
EXTRA_CFLAGS += -Idrivers/misc/modem_if
-obj-y += sipc5_modem.o sipc5_io_device.o
+obj-y += sipc5_modem.o sipc5_io_device.o sipc5_common.o
obj-y += sipc4_modem.o sipc4_io_device.o
obj-y += modem_net_flowcontrol_device.o modem_utils.o
@@ -10,17 +10,43 @@ obj-$(CONFIG_UMTS_MODEM_XMM6260) += modem_modemctl_device_xmm6260.o
obj-$(CONFIG_UMTS_MODEM_XMM6262) += modem_modemctl_device_xmm6262.o
obj-$(CONFIG_CDMA_MODEM_CBP71) += modem_modemctl_device_cbp71.o
obj-$(CONFIG_CDMA_MODEM_CBP72) += modem_modemctl_device_cbp72.o
+obj-$(CONFIG_CDMA_MODEM_CBP82) += modem_modemctl_device_cbp82.o
obj-$(CONFIG_LTE_MODEM_CMC221) += modem_modemctl_device_cmc221.o lte_modem_bootloader.o
+obj-$(CONFIG_UMTS_MODEM_SS222) += modem_modemctl_device_ss222.o
obj-$(CONFIG_CDMA_MODEM_MDM6600) += modem_modemctl_device_mdm6600.o
obj-$(CONFIG_GSM_MODEM_ESC6270) += modem_modemctl_device_esc6270.o
+obj-$(CONFIG_CDMA_MODEM_QSC6085) += modem_modemctl_device_qsc6085.o
obj-$(CONFIG_TDSCDMA_MODEM_SPRD8803) += modem_modemctl_device_sprd8803.o
obj-$(CONFIG_LINK_DEVICE_MIPI) += modem_link_device_mipi.o
-obj-$(CONFIG_LINK_DEVICE_DPRAM) += modem_link_device_dpram.o modem_link_device_dpram_ext_op.o
-obj-$(CONFIG_LINK_DEVICE_PLD) += modem_link_device_pld.o modem_link_device_pld_ext_op.o
obj-$(CONFIG_LINK_DEVICE_USB) += modem_link_device_usb.o modem_link_pm_usb.o
obj-$(CONFIG_LINK_DEVICE_HSIC) += modem_link_device_hsic.o
+obj-$(CONFIG_LINK_DEVICE_DPRAM) += modem_link_device_dpram.o modem_link_device_dpram_ext_op.o
+obj-$(CONFIG_LINK_DEVICE_PLD) += modem_link_device_pld.o modem_link_device_pld_ext_op.o
obj-$(CONFIG_LINK_DEVICE_C2C) += modem_link_device_c2c.o
obj-$(CONFIG_LINK_DEVICE_SPI) += modem_link_device_spi.o
+obj-$(CONFIG_BOOT_DEVICE_SPI) += modem_boot_device_spi.o
+
obj-$(CONFIG_SIM_SLOT_SWITCH) += modem_sim_slot_switch.o
+
+# Check whether or not memory-type interface
+ifeq ($(CONFIG_LINK_DEVICE_DPRAM),y)
+LINK_DEVICE_MEMORY_INTERFACE=y
+endif
+
+ifeq ($(CONFIG_LINK_DEVICE_PLD),y)
+LINK_DEVICE_MEMORY_INTERFACE=y
+endif
+
+ifeq ($(CONFIG_LINK_DEVICE_C2C),y)
+LINK_DEVICE_MEMORY_INTERFACE=y
+endif
+
+ifeq ($(CONFIG_LINK_DEVICE_SHMEM),y)
+LINK_DEVICE_MEMORY_INTERFACE=y
+endif
+
+ifdef LINK_DEVICE_MEMORY_INTERFACE
+obj-y += modem_link_device_memory.o
+endif
diff --git a/drivers/misc/modem_if/lte_modem_bootloader.c b/drivers/misc/modem_if/lte_modem_bootloader.c
index f259aae..0bc8894 100644
--- a/drivers/misc/modem_if/lte_modem_bootloader.c
+++ b/drivers/misc/modem_if/lte_modem_bootloader.c
@@ -31,7 +31,7 @@
#include <linux/delay.h>
#include <linux/spi/spi.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include <linux/platform_data/lte_modem_bootloader.h>
#define LEN_XMIT_DELEY 100
diff --git a/drivers/misc/modem_if/modem.h b/drivers/misc/modem_if/modem.h
new file mode 100644
index 0000000..bc4433e
--- /dev/null
+++ b/drivers/misc/modem_if/modem.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MODEM_IF_H__
+#define __MODEM_IF_H__
+
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+
+enum modem_t {
+ IMC_XMM6260,
+ IMC_XMM6262,
+ VIA_CBP71,
+ VIA_CBP72,
+ VIA_CBP82,
+ SEC_CMC220,
+ SEC_CMC221,
+ SEC_SS222,
+ QC_MDM6600,
+ QC_ESC6270,
+ QC_QSC6085,
+ SPRD_SC8803,
+ DUMMY,
+ MAX_MODEM_TYPE
+};
+
+enum dev_format {
+ IPC_FMT,
+ IPC_RAW,
+ IPC_RFS,
+ IPC_MULTI_RAW,
+ IPC_CMD,
+ IPC_BOOT,
+ IPC_RAMDUMP,
+ IPC_DEBUG,
+ MAX_DEV_FORMAT,
+};
+#define MAX_IPC_DEV (IPC_RFS + 1) /* FMT, RAW, RFS */
+#define MAX_SIPC5_DEV (IPC_RAW + 1) /* FMT, RAW */
+
+enum modem_io {
+ IODEV_MISC,
+ IODEV_NET,
+ IODEV_DUMMY,
+};
+
+enum modem_link {
+ LINKDEV_UNDEFINED,
+ LINKDEV_MIPI,
+ LINKDEV_USB,
+ LINKDEV_HSIC,
+ LINKDEV_DPRAM,
+ LINKDEV_PLD,
+ LINKDEV_C2C,
+ LINKDEV_SHMEM,
+ LINKDEV_SPI,
+ LINKDEV_MAX
+};
+#define LINKTYPE(modem_link) (1u << (modem_link))
+
+enum modem_network {
+ UMTS_NETWORK,
+ CDMA_NETWORK,
+ TDSCDMA_NETWORK,
+ LTE_NETWORK,
+ MAX_MODEM_NETWORK
+};
+
+enum ap_type {
+ S5P,
+ MAX_AP_TYPE
+};
+
+enum sipc_ver {
+ NO_SIPC_VER = 0,
+ SIPC_VER_40 = 40,
+ SIPC_VER_41 = 41,
+ SIPC_VER_42 = 42,
+ SIPC_VER_50 = 50,
+ MAX_SIPC_VER
+};
+
+/**
+ * struct modem_io_t - declaration for io_device
+ * @name: device name
+ * @id: for SIPC4, contains format & channel information
+ * (id & 11100000b)>>5 = format (eg, 0=FMT, 1=RAW, 2=RFS)
+ * (id & 00011111b) = channel (valid only if format is RAW)
+ * for SIPC5, contains only 8-bit channel ID
+ * @format: device format
+ * @io_type: type of this io_device
+ * @links: list of link_devices to use this io_device
+ * for example, if you want to use DPRAM and USB in an io_device.
+ * .links = LINKTYPE(LINKDEV_DPRAM) | LINKTYPE(LINKDEV_USB)
+ * @tx_link: when you use 2+ link_devices, set the link for TX.
+ * If define multiple link_devices in @links,
+ * you can receive data from them. But, cannot send data to all.
+ * TX is only one link_device.
+ * @app: the name of the application that will use this IO device
+ *
+ * This structure is used in board-*-modems.c
+ */
+struct modem_io_t {
+ char *name;
+ int id;
+ enum dev_format format;
+ enum modem_io io_type;
+ enum modem_link links;
+ enum modem_link tx_link;
+ char *app;
+};
+
+struct modemlink_pm_data {
+ char *name;
+ /* link power contol 2 types : pin & regulator control */
+ int (*link_ldo_enable)(bool);
+ unsigned gpio_link_enable;
+ unsigned gpio_link_active;
+ unsigned gpio_link_hostwake;
+ unsigned gpio_link_slavewake;
+ int (*link_reconnect)(void);
+
+ /* usb hub only */
+ int (*port_enable)(int, int);
+ int (*hub_standby)(void *);
+ void *hub_pm_data;
+ bool has_usbhub;
+
+#ifdef CONFIG_EXYNOS4_CPUFREQ
+ /* cpu/bus frequency lock */
+ atomic_t freqlock;
+ atomic_t freq_dpramlock;
+ int (*freq_lock)(struct device *dev);
+ int (*freq_unlock)(struct device *dev);
+ unsigned gpio_cpufreq_lock;
+#endif
+
+ int autosuspend_delay_ms; /* if zero, the default value is used */
+ void (*ehci_reg_dump)(struct device *);
+};
+
+struct modemlink_pm_link_activectl {
+ int gpio_initialized;
+ int gpio_request_host_active;
+};
+
+#define RES_DPRAM_MEM_ID 0
+#define RES_DPRAM_SFR_ID 1
+
+#define STR_DPRAM_BASE "dpram_base"
+#define STR_DPRAM_SFR_BASE "dpram_sfr_base"
+
+enum dpram_type {
+ EXT_DPRAM,
+ AP_IDPRAM,
+ CP_IDPRAM,
+ PLD_DPRAM,
+ MAX_DPRAM_TYPE
+};
+
+#define DPRAM_SIZE_8KB (8 << 10)
+#define DPRAM_SIZE_16KB (16 << 10)
+#define DPRAM_SIZE_32KB (32 << 10)
+#define DPRAM_SIZE_64KB (64 << 10)
+#define DPRAM_SIZE_128KB (128 << 10)
+
+enum dpram_speed {
+ DPRAM_SPEED_LOW,
+ DPRAM_SPEED_MID,
+ DPRAM_SPEED_HIGH,
+ MAX_DPRAM_SPEED
+};
+
+struct dpram_circ {
+ u16 __iomem *head;
+ u16 __iomem *tail;
+ u8 __iomem *buff;
+ u32 size;
+};
+
+struct dpram_ipc_device {
+ char name[16];
+ int id;
+
+ struct dpram_circ txq;
+ struct dpram_circ rxq;
+
+ u16 mask_req_ack;
+ u16 mask_res_ack;
+ u16 mask_send;
+};
+
+struct dpram_ipc_map {
+ u16 __iomem *magic;
+ u16 __iomem *access;
+
+ struct dpram_ipc_device dev[MAX_IPC_DEV];
+
+ u16 __iomem *mbx_cp2ap;
+ u16 __iomem *mbx_ap2cp;
+};
+
+struct pld_ipc_map {
+ u16 __iomem *mbx_ap2cp;
+ u16 __iomem *magic_ap2cp;
+ u16 __iomem *access_ap2cp;
+
+ u16 __iomem *mbx_cp2ap;
+ u16 __iomem *magic_cp2ap;
+ u16 __iomem *access_cp2ap;
+
+ struct dpram_ipc_device dev[MAX_IPC_DEV];
+
+ u16 __iomem *address_buffer;
+};
+
+struct modemlink_dpram_data {
+ enum dpram_type type; /* DPRAM type */
+ enum ap_type ap; /* AP type for AP_IDPRAM */
+
+ /* Stirct I/O access (e.g. ioread16(), etc.) is required */
+ bool strict_io_access;
+
+ /* Aligned access is required */
+ int aligned;
+
+ /* Disabled during phone booting */
+ bool disabled;
+
+ /* Virtual base address and size */
+ u8 __iomem *base;
+ u32 size;
+
+ /* Pointer to an IPC map (DPRAM or PLD) */
+ void *ipc_map;
+
+ /* Timeout of waiting for RES_ACK from CP (in msec) */
+ unsigned long res_ack_wait_timeout;
+
+ unsigned boot_size_offset;
+ unsigned boot_tag_offset;
+ unsigned boot_count_offset;
+ unsigned max_boot_frame_size;
+
+ void (*setup_speed)(enum dpram_speed);
+ void (*clear_int2ap)(void);
+};
+
+enum shmem_type {
+ REAL_SHMEM,
+ C2C_SHMEM,
+ MAX_SHMEM_TYPE
+};
+
+#define STR_SHMEM_BASE "shmem_base"
+
+#define SHMEM_SIZE_1MB (1 << 20) /* 1 MB */
+#define SHMEM_SIZE_2MB (2 << 20) /* 2 MB */
+#define SHMEM_SIZE_4MB (4 << 20) /* 4 MB */
+
+/* platform data */
+struct modem_data {
+ char *name;
+
+ unsigned gpio_cp_on;
+ unsigned gpio_cp_off;
+ unsigned gpio_reset_req_n;
+ unsigned gpio_cp_reset;
+
+ /* for broadcasting AP's PM state (active or sleep) */
+ unsigned gpio_pda_active;
+
+ /* for checking aliveness of CP */
+ unsigned gpio_phone_active;
+ int irq_phone_active;
+
+ /* for AP-CP IPC interrupt */
+ unsigned gpio_ipc_int2ap;
+ int irq_ipc_int2ap;
+ unsigned long irqf_ipc_int2ap; /* IRQ flags */
+ unsigned gpio_ipc_int2cp;
+
+ /* for AP-CP power management (PM) handshaking */
+ unsigned gpio_ap_wakeup;
+ int irq_ap_wakeup;
+ unsigned gpio_ap_status;
+ unsigned gpio_cp_wakeup;
+ unsigned gpio_cp_status;
+ int irq_cp_status;
+
+ /* for USB/HSIC PM */
+ unsigned gpio_host_wakeup;
+ int irq_host_wakeup;
+ unsigned gpio_host_active;
+ unsigned gpio_slave_wakeup;
+ unsigned gpio_hub_suspend;
+
+ unsigned gpio_cp_dump_int;
+ unsigned gpio_ap_dump_int;
+ unsigned gpio_flm_uart_sel;
+ unsigned gpio_cp_warm_reset;
+#if defined(CONFIG_MACH_M0_CTC)
+ unsigned gpio_flm_uart_sel_rev06;
+#endif
+
+ unsigned gpio_sim_detect;
+ int irq_sim_detect;
+
+#ifdef CONFIG_LINK_DEVICE_PLD
+ unsigned gpio_fpga1_creset;
+ unsigned gpio_fpga1_cdone;
+ unsigned gpio_fpga1_rst_n;
+ unsigned gpio_fpga1_cs_n;
+
+ unsigned gpio_fpga2_creset;
+ unsigned gpio_fpga2_cdone;
+ unsigned gpio_fpga2_rst_n;
+ unsigned gpio_fpga2_cs_n;
+#endif
+
+#ifdef CONFIG_MACH_U1_KOR_LGT
+ unsigned gpio_cp_reset_msm;
+ unsigned gpio_boot_sw_sel;
+ void (*vbus_on)(void);
+ void (*vbus_off)(void);
+ struct regulator *cp_vbus;
+#endif
+
+#ifdef CONFIG_TDSCDMA_MODEM_SPRD8803
+ unsigned gpio_ipc_mrdy;
+ unsigned gpio_ipc_srdy;
+ unsigned gpio_ipc_sub_mrdy;
+ unsigned gpio_ipc_sub_srdy;
+ unsigned gpio_ap_cp_int1;
+ unsigned gpio_ap_cp_int2;
+#endif
+
+#ifdef CONFIG_SEC_DUAL_MODEM_MODE
+ unsigned gpio_sim_io_sel;
+ unsigned gpio_cp_ctrl1;
+ unsigned gpio_cp_ctrl2;
+#endif
+
+ /* Switch with 2 links in a modem */
+ unsigned gpio_link_switch;
+
+#ifdef CONFIG_EXYNOS4_CPUFREQ
+ /* cpu/bus frequency lock */
+ unsigned gpio_cpufreq_lock;
+#endif
+
+ /* Modem component */
+ enum modem_network modem_net;
+ enum modem_t modem_type;
+ enum modem_link link_types;
+ char *link_name;
+
+ /* Link to DPRAM control functions dependent on each platform */
+ struct modemlink_dpram_data *dpram;
+
+ /* SIPC version */
+ enum sipc_ver ipc_version;
+
+ /* the number of real IPC devices -> (IPC_RAW + 1) or (IPC_RFS + 1) */
+ int max_ipc_dev;
+
+ /* Information of IO devices */
+ unsigned num_iodevs;
+ struct modem_io_t *iodevs;
+
+ /* Modem link PM support */
+ struct modemlink_pm_data *link_pm_data;
+
+ /* Handover with 2+ modems */
+ bool use_handover;
+
+ /* SIM Detect polarity */
+ bool sim_polarity;
+
+ void (*gpio_revers_bias_clear)(void);
+ void (*gpio_revers_bias_restore)(void);
+};
+
+#define MODEM_BOOT_DEV_SPI "modem_boot_spi"
+
+struct modem_boot_spi_platform_data {
+ const char *name;
+ unsigned int gpio_cp_status;
+};
+
+struct modem_boot_spi {
+ struct miscdevice dev;
+ struct spi_device *spi_dev;
+ struct mutex lock;
+ unsigned gpio_cp_status;
+};
+#define to_modem_boot_spi(misc) container_of(misc, struct modem_boot_spi, dev);
+
+struct utc_time {
+ u16 year;
+ u8 mon:4,
+ day:4;
+ u8 hour;
+ u8 min;
+ u8 sec;
+ u16 msec;
+} __packed;
+
+extern void get_utc_time(struct utc_time *utc);
+
+#define LOG_TAG "mif: "
+#define CALLER (__builtin_return_address(0))
+
+#define mif_err(fmt, ...) \
+ pr_err(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__)
+#define mif_debug(fmt, ...) \
+ pr_debug(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__)
+#define mif_info(fmt, ...) \
+ pr_info(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__)
+#define mif_trace(fmt, ...) \
+ printk(KERN_DEBUG "mif: %s: %d: called(%pF): " fmt, \
+ __func__, __LINE__, __builtin_return_address(0), ##__VA_ARGS__)
+
+#endif
diff --git a/drivers/misc/modem_if/modem_boot_device_spi.c b/drivers/misc/modem_if/modem_boot_device_spi.c
new file mode 100644
index 0000000..369e473
--- /dev/null
+++ b/drivers/misc/modem_if/modem_boot_device_spi.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/wakelock.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+
+#include "modem.h"
+#include "modem_prj.h"
+
+#define SPI_XMIT_DELEY 100
+
+static int check_cp_status(unsigned int gpio_cp_status, unsigned int count)
+{
+ int ret = 0;
+ int cnt = 0;
+
+ while (1) {
+ if (gpio_get_value(gpio_cp_status) != 0) {
+ ret = 0;
+ break;
+ }
+
+ cnt++;
+ if (cnt >= count) {
+ mif_err("ERR! gpio_cp_status == 0 (cnt %d)\n", cnt);
+ ret = -EFAULT;
+ break;
+ }
+
+ msleep(20);
+ }
+
+ return ret;
+}
+
+static inline int spi_send(struct modem_boot_spi *loader, const char val)
+{
+ char buff[1];
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 1,
+ .tx_buf = buff,
+ };
+
+ buff[0] = val;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ ret = spi_sync(loader->spi_dev, &msg);
+ if (ret < 0)
+ mif_err("ERR! spi_sync fail (err %d)\n", ret);
+
+ return ret;
+}
+
+static int spi_boot_write(struct modem_boot_spi *loader, const char *addr,
+ const long len)
+{
+ int i;
+ int ret = 0;
+ char *buff = NULL;
+ mif_err("+++\n");
+
+ buff = kzalloc(len, GFP_KERNEL);
+ if (!buff) {
+ mif_err("ERR! kzalloc(%ld) fail\n", len);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ret = copy_from_user(buff, (const void __user *)addr, len);
+ if (ret) {
+ mif_err("ERR! copy_from_user fail (err %d)\n", ret);
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ for (i = 0 ; i < len ; i++) {
+ ret = spi_send(loader, buff[i]);
+ if (ret < 0) {
+ mif_err("ERR! spi_send fail (err %d)\n", ret);
+ goto exit;
+ }
+ }
+
+exit:
+ if (buff)
+ kfree(buff);
+
+ mif_err("---\n");
+ return ret;
+}
+
+static int spi_boot_open(struct inode *inode, struct file *filp)
+{
+ struct modem_boot_spi *loader = to_modem_boot_spi(filp->private_data);
+ filp->private_data = loader;
+ return 0;
+}
+
+static long spi_boot_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ struct modem_firmware img;
+ struct modem_boot_spi *loader = filp->private_data;
+
+ mutex_lock(&loader->lock);
+ switch (cmd) {
+ case IOCTL_MODEM_XMIT_BOOT:
+ ret = copy_from_user(&img, (const void __user *)arg,
+ sizeof(struct modem_firmware));
+ if (ret) {
+ mif_err("ERR! copy_from_user fail (err %d)\n", ret);
+ ret = -EFAULT;
+ goto exit_err;
+ }
+ mif_info("IOCTL_MODEM_XMIT_BOOT (size %d)\n", img.size);
+
+ ret = spi_boot_write(loader, img.binary, img.size);
+ if (ret < 0) {
+ mif_err("ERR! spi_boot_write fail (err %d)\n", ret);
+ break;
+ }
+
+ if (!loader->gpio_cp_status)
+ break;
+
+ ret = check_cp_status(loader->gpio_cp_status, 100);
+ if (ret < 0)
+ mif_err("ERR! check_cp_status fail (err %d)\n", ret);
+
+ break;
+
+ default:
+ mif_err("ioctl cmd error\n");
+ ret = -ENOIOCTLCMD;
+
+ break;
+ }
+ mutex_unlock(&loader->lock);
+
+exit_err:
+ return ret;
+}
+
+static const struct file_operations modem_spi_boot_fops = {
+ .owner = THIS_MODULE,
+ .open = spi_boot_open,
+ .unlocked_ioctl = spi_boot_ioctl,
+};
+
+static int __devinit modem_spi_boot_probe(struct spi_device *spi)
+{
+ int ret;
+ struct modem_boot_spi *loader;
+ struct modem_boot_spi_platform_data *pdata;
+ mif_debug("+++\n");
+
+ loader = kzalloc(sizeof(*loader), GFP_KERNEL);
+ if (!loader) {
+ mif_err("failed to allocate for modem_boot_spi\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+ mutex_init(&loader->lock);
+
+ spi->bits_per_word = 8;
+
+ if (spi_setup(spi)) {
+ mif_err("ERR! spi_setup fail\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+ loader->spi_dev = spi;
+
+ if (!spi->dev.platform_data) {
+ mif_err("ERR! no platform_data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+ pdata = (struct modem_boot_spi_platform_data *)spi->dev.platform_data;
+
+ loader->gpio_cp_status = pdata->gpio_cp_status;
+
+ spi_set_drvdata(spi, loader);
+
+ loader->dev.minor = MISC_DYNAMIC_MINOR;
+ loader->dev.name = MODEM_BOOT_DEV_SPI;
+ loader->dev.fops = &modem_spi_boot_fops;
+ ret = misc_register(&loader->dev);
+ if (ret) {
+ mif_err("ERR! misc_register fail (err %d)\n", ret);
+ goto err_setup;
+ }
+
+ mif_debug("---\n");
+ return 0;
+
+err_setup:
+ mutex_destroy(&loader->lock);
+ kfree(loader);
+
+err_alloc:
+ mif_err("xxx\n");
+ return ret;
+}
+
+static int __devexit modem_spi_boot_remove(struct spi_device *spi)
+{
+ struct modem_boot_spi *loader = spi_get_drvdata(spi);
+
+ misc_deregister(&loader->dev);
+ mutex_destroy(&loader->lock);
+ kfree(loader);
+
+ return 0;
+}
+
+static struct spi_driver modem_boot_device_spi_driver = {
+ .driver = {
+ .name = MODEM_BOOT_DEV_SPI,
+ .owner = THIS_MODULE,
+ },
+ .probe = modem_spi_boot_probe,
+ .remove = __devexit_p(modem_spi_boot_remove),
+};
+
+static int __init modem_boot_device_spi_init(void)
+{
+ int err;
+
+ err = spi_register_driver(&modem_boot_device_spi_driver);
+ if (err) {
+ mif_err("spi_register_driver fail (err %d)\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit modem_boot_device_spi_exit(void)
+{
+ spi_unregister_driver(&modem_boot_device_spi_driver);
+}
+
+module_init(modem_boot_device_spi_init);
+module_exit(modem_boot_device_spi_exit);
+
+MODULE_DESCRIPTION("SPI Driver for Downloading Modem Bootloader");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/misc/modem_if/modem_link_device_c2c.c b/drivers/misc/modem_if/modem_link_device_c2c.c
index acbaadf..b51cf9e 100644
--- a/drivers/misc/modem_if/modem_link_device_c2c.c
+++ b/drivers/misc/modem_if/modem_link_device_c2c.c
@@ -1,6 +1,4 @@
-/* /linux/drivers/new_modem_if/link_dev_c2c.c
- *
- * Copyright (C) 2010 Google, Inc.
+/*
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -14,9 +12,9 @@
*
*/
-#include <linux/init.h>
#include <linux/irq.h>
#include <linux/gpio.h>
+#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/wakelock.h>
@@ -24,38 +22,2279 @@
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
#include <linux/if_arp.h>
#include <linux/platform_device.h>
+#include <linux/kallsyms.h>
+#include <linux/suspend.h>
+#ifdef CONFIG_FB
+#include <linux/fb.h>
+#endif
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+#include <mach/regs-gpio.h>
+#include <linux/notifier.h>
-#include <linux/platform_data/modem.h>
-#include <linux/platform_data/c2c.h>
+#include "modem.h"
#include "modem_prj.h"
+#include "modem_utils.h"
#include "modem_link_device_c2c.h"
+static void trigger_forced_cp_crash(struct shmem_link_device *shmd);
+
+#ifdef DEBUG_MODEM_IF
+static void save_mem_dump(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ char *path = shmd->dump_path;
+ struct file *fp;
+ struct utc_time t;
+
+ get_utc_time(&t);
+ snprintf(path, MIF_MAX_PATH_LEN, "%s/%s_%d%02d%02d_%02d%02d%02d.dump",
+ MIF_LOG_DIR, ld->name, t.year, t.mon, t.day, t.hour, t.min,
+ t.sec);
+
+ fp = mif_open_file(path);
+ if (!fp) {
+ mif_err("%s: ERR! %s open fail\n", ld->name, path);
+ return;
+ }
+ mif_err("%s: %s opened\n", ld->name, path);
+
+ mif_save_file(fp, shmd->base, shmd->size);
+
+ mif_close_file(fp);
+}
+
+/**
+ * mem_dump_work
+ * @ws: pointer to an instance of work_struct structure
+ *
+ * Performs actual file operation for saving a DPRAM dump.
+ */
+static void mem_dump_work(struct work_struct *ws)
+{
+ struct shmem_link_device *shmd;
+
+ shmd = container_of(ws, struct shmem_link_device, dump_dwork.work);
+ if (!shmd) {
+ mif_err("ERR! no shmd\n");
+ return;
+ }
+
+ save_mem_dump(shmd);
+}
+#endif
+
+static void print_pm_status(struct shmem_link_device *shmd, int level)
+{
+#ifdef DEBUG_MODEM_IF
+ struct utc_time t;
+ u32 magic;
+ int ap_wakeup;
+ int ap_status;
+ int cp_wakeup;
+ int cp_status;
+
+ if (level < 0)
+ return;
+
+ get_utc_time(&t);
+ magic = get_magic(shmd);
+ ap_wakeup = gpio_get_value(shmd->gpio_ap_wakeup);
+ ap_status = gpio_get_value(shmd->gpio_ap_status);
+ cp_wakeup = gpio_get_value(shmd->gpio_cp_wakeup);
+ cp_status = gpio_get_value(shmd->gpio_cp_status);
+
+ /*
+ ** PM {ap_wakeup:cp_wakeup:cp_status:ap_status:magic:state} CALLER
+ */
+ if (level > 0) {
+ pr_err(LOG_TAG "[%02d:%02d:%02d.%03d] C2C PM {%d:%d:%d:%d:%X} "
+ "%pf\n", t.hour, t.min, t.sec, t.msec, ap_wakeup,
+ cp_wakeup, cp_status, ap_status, magic, CALLER);
+ } else {
+ pr_info(LOG_TAG "[%02d:%02d:%02d.%03d] C2C PM {%d:%d:%d:%d:%X} "
+ "%pf\n", t.hour, t.min, t.sec, t.msec, ap_wakeup,
+ cp_wakeup, cp_status, ap_status, magic, CALLER);
+ }
+#endif
+}
+
+static inline void s5p_change_irq_type(int irq, int value)
+{
+ irq_set_irq_type(irq, value ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_LEVEL_HIGH);
+ /**
+ * Exynos BSP has a problem when using level-triggering interrupt.
+ * If the irq type is changed in an interrupt handler, the handler will
+ * be called again.
+ * Below is a temporary solution until SYS.LSI resolves this problem.
+ */
+ __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
+}
+
+/**
+ * recv_int2ap
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Returns the value of the CP-to-AP interrupt register.
+ */
+static inline u16 recv_int2ap(struct shmem_link_device *shmd)
+{
+ if (shmd->type == C2C_SHMEM)
+ return (u16)c2c_read_interrupt();
+
+ if (shmd->mbx2ap)
+ return *shmd->mbx2ap;
+
+ return 0;
+}
+
+/**
+ * send_int2cp
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @mask: value to be written to the AP-to-CP interrupt register
+ */
+static inline void send_int2cp(struct shmem_link_device *shmd, u16 mask)
+{
+ struct link_device *ld = &shmd->ld;
+
+ if (ld->mode != LINK_MODE_IPC)
+ mif_info("%s: <by %pf> mask = 0x%04X\n", ld->name, CALLER, mask);
+
+ if (shmd->type == C2C_SHMEM)
+ c2c_send_interrupt(mask);
+
+ if (shmd->mbx2cp)
+ *shmd->mbx2cp = mask;
+}
+
+/**
+ * get_shmem_status
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dir: direction of communication (TX or RX)
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Takes a snapshot of the current status of a SHMEM.
+ */
+static void get_shmem_status(struct shmem_link_device *shmd,
+ enum circ_dir_type dir, struct mem_status *mst)
+{
+#ifdef DEBUG_MODEM_IF
+ getnstimeofday(&mst->ts);
+#endif
+
+ mst->dir = dir;
+ mst->magic = get_magic(shmd);
+ mst->access = get_access(shmd);
+ mst->head[IPC_FMT][TX] = get_txq_head(shmd, IPC_FMT);
+ mst->tail[IPC_FMT][TX] = get_txq_tail(shmd, IPC_FMT);
+ mst->head[IPC_FMT][RX] = get_rxq_head(shmd, IPC_FMT);
+ mst->tail[IPC_FMT][RX] = get_rxq_tail(shmd, IPC_FMT);
+ mst->head[IPC_RAW][TX] = get_txq_head(shmd, IPC_RAW);
+ mst->tail[IPC_RAW][TX] = get_txq_tail(shmd, IPC_RAW);
+ mst->head[IPC_RAW][RX] = get_rxq_head(shmd, IPC_RAW);
+ mst->tail[IPC_RAW][RX] = get_rxq_tail(shmd, IPC_RAW);
+}
+
+static inline int check_link_status(struct shmem_link_device *shmd)
+{
+ u32 magic = get_magic(shmd);
+ int cnt;
+
+ if (gpio_get_value(shmd->gpio_cp_status) != 0 && magic == SHM_IPC_MAGIC)
+ return 0;
+
+ cnt = 0;
+ while (gpio_get_value(shmd->gpio_cp_status) == 0) {
+ if (gpio_get_value(shmd->gpio_ap_status) == 0) {
+ print_pm_status(shmd, 1);
+ gpio_set_value(shmd->gpio_ap_status, 1);
+ }
+
+ cnt++;
+ if (cnt >= 100) {
+ mif_err("ERR! cp_status != 1 (cnt %d)\n", cnt);
+ return -EACCES;
+ }
+
+ if (in_interrupt())
+ udelay(100);
+ else
+ usleep_range(100, 200);
+ }
+
+ cnt = 0;
+ while (1) {
+ magic = get_magic(shmd);
+ if (magic == SHM_IPC_MAGIC)
+ break;
+
+ cnt++;
+ if (cnt >= 100) {
+ mif_err("ERR! magic 0x%X != SHM_IPC_MAGIC (cnt %d)\n",
+ magic, cnt);
+ return -EACCES;
+ }
+
+ if (in_interrupt())
+ udelay(100);
+ else
+ usleep_range(100, 200);
+ }
+
+ return 0;
+}
+
+static void release_cp_wakeup(struct work_struct *ws)
+{
+ struct shmem_link_device *shmd;
+ struct link_device *ld;
+ int i;
+ unsigned long flags;
+
+ shmd = container_of(ws, struct shmem_link_device, cp_sleep_dwork.work);
+
+ spin_lock_irqsave(&shmd->pm_lock, flags);
+ i = atomic_read(&shmd->ref_cnt);
+ spin_unlock_irqrestore(&shmd->pm_lock, flags);
+ if (i > 0)
+ goto reschedule;
+
+ /*
+ * If there is any IPC message remained in a TXQ, AP must prevent CP
+ * from going to sleep.
+ */
+ ld = &shmd->ld;
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ if (ld->skb_txq[i]->qlen > 0)
+ goto reschedule;
+ }
+
+ if (gpio_get_value(shmd->gpio_ap_wakeup))
+ goto reschedule;
+
+ gpio_set_value(shmd->gpio_cp_wakeup, 0);
+ print_pm_status(shmd, 1);
+ return;
+
+reschedule:
+ if (!work_pending(&shmd->cp_sleep_dwork.work)) {
+ queue_delayed_work(system_nrt_wq, &shmd->cp_sleep_dwork,
+ msecs_to_jiffies(CP_WAKEUP_HOLD_TIME));
+ }
+}
+
+static void release_ap_status(struct work_struct *ws)
+{
+ struct shmem_link_device *shmd;
+ struct link_device *ld;
+ int i;
+ unsigned long flags;
+
+ shmd = container_of(ws, struct shmem_link_device, link_off_dwork.work);
+
+ spin_lock_irqsave(&shmd->pm_lock, flags);
+ i = atomic_read(&shmd->ref_cnt);
+ spin_unlock_irqrestore(&shmd->pm_lock, flags);
+ if (i > 0)
+ goto reschedule;
+
+ if (gpio_get_value(shmd->gpio_cp_status))
+ goto reschedule;
+
+ gpio_set_value(shmd->gpio_ap_status, 0);
+ print_pm_status(shmd, 1);
+
+ if (wake_lock_active(&shmd->cp_wlock))
+ wake_unlock(&shmd->cp_wlock);
+
+ return;
+
+reschedule:
+ if (!work_pending(&shmd->link_off_dwork.work)) {
+ queue_delayed_work(system_nrt_wq, &shmd->link_off_dwork,
+ msecs_to_jiffies(100));
+ }
+}
+
+/**
+ * forbid_cp_sleep
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Wakes up a CP if it can sleep and increases the "ref_cnt" counter in the
+ * shmem_link_device instance.
+ *
+ * CAUTION!!! permit_cp_sleep() MUST be invoked after forbid_cp_sleep() success
+ * to decrease the "ref_cnt" counter.
+ */
+static int forbid_cp_sleep(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ int err = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&shmd->pm_lock, flags);
+ atomic_inc(&shmd->ref_cnt);
+ if (gpio_get_value(shmd->gpio_ap_status) == 0) {
+ gpio_set_value(shmd->gpio_ap_status, 1);
+ print_pm_status(shmd, 1);
+ }
+ spin_unlock_irqrestore(&shmd->pm_lock, flags);
+
+ if (work_pending(&shmd->cp_sleep_dwork.work))
+ cancel_delayed_work(&shmd->cp_sleep_dwork);
+
+ if (work_pending(&shmd->link_off_dwork.work))
+ cancel_delayed_work(&shmd->link_off_dwork);
+
+ if (gpio_get_value(shmd->gpio_cp_wakeup) == 0) {
+ gpio_set_value(shmd->gpio_cp_wakeup, 1);
+ print_pm_status(shmd, 1);
+ }
+
+ if (check_link_status(shmd) < 0) {
+ print_pm_status(shmd, 1);
+ mif_err("%s: ERR! check_link_status fail\n", ld->name);
+ err = -EACCES;
+ goto exit;
+ }
+
+exit:
+ return err;
+}
+
+/**
+ * permit_cp_sleep
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Decreases the "ref_cnt" counter in the shmem_link_device instance if it can
+ * sleep and allows a CP to sleep only if the value of "ref_cnt" counter is
+ * less than or equal to 0.
+ *
+ * MUST be invoked after forbid_cp_sleep() success to decrease the "ref_cnt"
+ * counter.
+ */
+static void permit_cp_sleep(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ unsigned long flags;
+
+ spin_lock_irqsave(&shmd->pm_lock, flags);
+
+ if (atomic_dec_return(&shmd->ref_cnt) > 0) {
+ spin_unlock_irqrestore(&shmd->pm_lock, flags);
+ return;
+ }
+
+ atomic_set(&shmd->ref_cnt, 0);
+ spin_unlock_irqrestore(&shmd->pm_lock, flags);
+
+ /* Hold gpio_cp_wakeup for CP_WAKEUP_HOLD_TIME until CP finishes RX */
+ if (!work_pending(&shmd->cp_sleep_dwork.work)) {
+ queue_delayed_work(system_nrt_wq, &shmd->cp_sleep_dwork,
+ msecs_to_jiffies(CP_WAKEUP_HOLD_TIME));
+ }
+}
+
+/**
+ * ap_wakeup_handler: interrupt handler for a wakeup interrupt
+ * @irq: IRQ number
+ * @data: pointer to a data
+ *
+ * 1) Reads the interrupt value
+ * 2) Performs interrupt handling
+ */
+static irqreturn_t ap_wakeup_handler(int irq, void *data)
+{
+ struct shmem_link_device *shmd = (struct shmem_link_device *)data;
+ struct link_device *ld = (struct link_device *)&shmd->ld;
+ int ap_wakeup = gpio_get_value(shmd->gpio_ap_wakeup);
+ int ap_status = gpio_get_value(shmd->gpio_ap_status);
+
+ s5p_change_irq_type(irq, ap_wakeup);
+
+ if (ld->mode != LINK_MODE_IPC)
+ goto exit;
+
+ if (work_pending(&shmd->cp_sleep_dwork.work))
+ __cancel_delayed_work(&shmd->cp_sleep_dwork);
+
+ print_pm_status(shmd, 1);
+
+ if (ap_wakeup) {
+ if (work_pending(&shmd->link_off_dwork.work))
+ __cancel_delayed_work(&shmd->link_off_dwork);
+
+ if (!wake_lock_active(&shmd->ap_wlock))
+ wake_lock(&shmd->ap_wlock);
+
+ if (!c2c_suspended() && !ap_status)
+ gpio_set_value(shmd->gpio_ap_status, 1);
+ } else {
+ if (wake_lock_active(&shmd->ap_wlock))
+ wake_unlock(&shmd->ap_wlock);
+
+ queue_delayed_work(system_nrt_wq, &shmd->cp_sleep_dwork,
+ msecs_to_jiffies(CP_WAKEUP_HOLD_TIME));
+ }
+
+exit:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cp_status_handler(int irq, void *data)
+{
+ struct shmem_link_device *shmd = (struct shmem_link_device *)data;
+ struct link_device *ld = (struct link_device *)&shmd->ld;
+ int cp_status = gpio_get_value(shmd->gpio_cp_status);
+ unsigned long flags;
+
+ spin_lock_irqsave(&shmd->pm_lock, flags);
+
+ s5p_change_irq_type(irq, cp_status);
+
+ if (ld->mode != LINK_MODE_IPC)
+ goto exit;
+
+ if (work_pending(&shmd->link_off_dwork.work))
+ __cancel_delayed_work(&shmd->link_off_dwork);
+
+ print_pm_status(shmd, 1);
+
+ if (cp_status) {
+ if (!wake_lock_active(&shmd->cp_wlock))
+ wake_lock(&shmd->cp_wlock);
+ } else {
+ if (atomic_read(&shmd->ref_cnt) > 0) {
+ queue_delayed_work(system_nrt_wq, &shmd->link_off_dwork,
+ msecs_to_jiffies(10));
+ } else {
+ gpio_set_value(shmd->gpio_ap_status, 0);
+ if (wake_lock_active(&shmd->cp_wlock))
+ wake_unlock(&shmd->cp_wlock);
+ }
+ }
+
+exit:
+ spin_unlock_irqrestore(&shmd->pm_lock, flags);
+ return IRQ_HANDLED;
+}
+
+#if 1
+/* Functions for IPC/BOOT/DUMP RX */
+#endif
+
+/**
+ * handle_cp_crash
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Actual handler for the CRASH_EXIT command from a CP.
+ */
+static void handle_cp_crash(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ struct io_device *iod;
+ int i;
+
+ if (shmd->forced_cp_crash)
+ shmd->forced_cp_crash = false;
+
+ /* Stop network interfaces */
+ mif_netif_stop(ld);
+
+ /* Purge the skb_txq in every IPC device (IPC_FMT, IPC_RAW, etc.) */
+ for (i = 0; i < MAX_SIPC5_DEV; i++)
+ skb_queue_purge(ld->skb_txq[i]);
+
+ /* Change the modem state to STATE_CRASH_EXIT for the FMT IO device */
+ iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_EXIT);
+
+ /* time margin for taking state changes by rild */
+ mdelay(100);
+
+ /* Change the modem state to STATE_CRASH_EXIT for the BOOT IO device */
+ iod = link_get_iod_with_format(ld, IPC_BOOT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_EXIT);
+}
+
+/**
+ * handle_no_cp_crash_ack
+ * @arg: pointer to an instance of shmem_link_device structure
+ *
+ * Invokes handle_cp_crash() to enter the CRASH_EXIT state if there was no
+ * CRASH_ACK from a CP in FORCE_CRASH_ACK_TIMEOUT.
+ */
+static void handle_no_cp_crash_ack(unsigned long arg)
+{
+ struct shmem_link_device *shmd = (struct shmem_link_device *)arg;
+ struct link_device *ld = &shmd->ld;
+
+ mif_err("%s: ERR! No CRASH_EXIT ACK from CP\n", ld->name);
+
+ handle_cp_crash(shmd);
+}
+
+/**
+ * trigger_forced_cp_crash
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Triggers an enforced CP crash.
+ */
+static void trigger_forced_cp_crash(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ struct utc_time t;
+
+ if (ld->mode == LINK_MODE_ULOAD) {
+ mif_err("%s: <by %pf> ALREADY in progress\n", ld->name, CALLER);
+ return;
+ }
+ ld->mode = LINK_MODE_ULOAD;
+ shmd->forced_cp_crash = true;
+
+ get_utc_time(&t);
+ mif_err("%s: [%02d:%02d:%02d.%03d] <by %pf>\n",
+ ld->name, t.hour, t.min, t.sec, t.msec, CALLER);
+
+ if (!wake_lock_active(&shmd->wlock))
+ wake_lock(&shmd->wlock);
+
+#ifdef DEBUG_MODEM_IF
+ if (in_interrupt())
+ queue_delayed_work(system_nrt_wq, &shmd->dump_dwork, 0);
+ else
+ save_mem_dump(shmd);
+#endif
+
+ /* Send CRASH_EXIT command to a CP */
+ send_int2cp(shmd, INT_CMD(INT_CMD_CRASH_EXIT));
+ get_shmem_status(shmd, TX, msq_get_free_slot(&shmd->stat_list));
+
+ /* If there is no CRASH_ACK from a CP in FORCE_CRASH_ACK_TIMEOUT,
+ handle_no_cp_crash_ack() will be executed. */
+ mif_add_timer(&shmd->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
+ handle_no_cp_crash_ack, (unsigned long)shmd);
+
+ return;
+}
+
+/**
+ * cmd_crash_reset_handler
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Handles the CRASH_RESET command from a CP.
+ */
+static void cmd_crash_reset_handler(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ struct io_device *iod = NULL;
+ int i;
+ struct utc_time t;
+
+ ld->mode = LINK_MODE_ULOAD;
+
+ if (!wake_lock_active(&shmd->wlock))
+ wake_lock(&shmd->wlock);
+
+ get_utc_time(&t);
+ mif_err("%s: ERR! [%02d:%02d:%02d.%03d] Recv 0xC7 (CRASH_RESET)\n",
+ ld->name, t.hour, t.min, t.sec, t.msec);
+#ifdef DEBUG_MODEM_IF
+ queue_delayed_work(system_nrt_wq, &shmd->dump_dwork, 0);
+#endif
+
+ /* Stop network interfaces */
+ mif_netif_stop(ld);
+
+ /* Purge the skb_txq in every IPC device (IPC_FMT, IPC_RAW, etc.) */
+ for (i = 0; i < MAX_SIPC5_DEV; i++)
+ skb_queue_purge(ld->skb_txq[i]);
+
+ /* Change the modem state to STATE_CRASH_RESET for the FMT IO device */
+ iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_RESET);
+
+ /* time margin for taking state changes by rild */
+ mdelay(100);
+
+ /* Change the modem state to STATE_CRASH_RESET for the BOOT IO device */
+ iod = link_get_iod_with_format(ld, IPC_BOOT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_RESET);
+}
+
+/**
+ * cmd_crash_exit_handler
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Handles the CRASH_EXIT command from a CP.
+ */
+static void cmd_crash_exit_handler(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ struct utc_time t;
+
+ ld->mode = LINK_MODE_ULOAD;
+
+ del_timer(&shmd->crash_ack_timer);
+
+ if (!wake_lock_active(&shmd->wlock))
+ wake_lock(&shmd->wlock);
+
+ get_utc_time(&t);
+ mif_err("%s: ERR! [%02d:%02d:%02d.%03d] Recv 0xC9 (CRASH_EXIT)\n",
+ ld->name, t.hour, t.min, t.sec, t.msec);
+#ifdef DEBUG_MODEM_IF
+ queue_delayed_work(system_nrt_wq, &shmd->dump_dwork, 0);
+#endif
+
+ handle_cp_crash(shmd);
+}
+
+/**
+ * cmd_phone_start_handler
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Handles the PHONE_START command from a CP.
+ */
+static void cmd_phone_start_handler(struct shmem_link_device *shmd)
+{
+ int err;
+ struct link_device *ld = &shmd->ld;
+ struct io_device *iod;
+ int ap_wakeup = gpio_get_value(shmd->gpio_ap_wakeup);
+ int cp_status = gpio_get_value(shmd->gpio_cp_status);
+
+ mif_err("%s: Recv 0xC8 (CP_START)\n", ld->name);
+
+ iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (!iod) {
+ mif_err("%s: ERR! no iod\n", ld->name);
+ return;
+ }
+
+ err = init_shmem_ipc(shmd);
+ if (err)
+ return;
+
+ if (wake_lock_active(&shmd->wlock))
+ wake_unlock(&shmd->wlock);
+
+ s5p_change_irq_type(shmd->irq_ap_wakeup, ap_wakeup);
+ if (ap_wakeup && !wake_lock_active(&shmd->ap_wlock))
+ wake_lock(&shmd->ap_wlock);
+
+ s5p_change_irq_type(shmd->irq_cp_status, cp_status);
+ if (cp_status && !wake_lock_active(&shmd->ap_wlock))
+ wake_lock(&shmd->cp_wlock);
+
+ ld->mode = LINK_MODE_IPC;
+ iod->modem_state_changed(iod, STATE_ONLINE);
+}
+
+/**
+ * cmd_handler: processes a SHMEM command from a CP
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @cmd: SHMEM command from a CP
+ */
+static void cmd_handler(struct shmem_link_device *shmd, u16 cmd)
+{
+ struct link_device *ld = &shmd->ld;
+
+ switch (INT_CMD_MASK(cmd)) {
+ case INT_CMD_CRASH_RESET:
+ cmd_crash_reset_handler(shmd);
+ break;
+
+ case INT_CMD_CRASH_EXIT:
+ cmd_crash_exit_handler(shmd);
+ break;
+
+ case INT_CMD_PHONE_START:
+ cmd_phone_start_handler(shmd);
+ complete_all(&ld->init_cmpl);
+ break;
+
+ default:
+ mif_err("%s: unknown command 0x%04X\n", ld->name, cmd);
+ break;
+ }
+}
+
+/**
+ * ipc_rx_work
+ * @ws: pointer to an instance of work_struct structure
+ *
+ * Invokes the recv method in the io_device instance to perform receiving IPC
+ * messages from each skb.
+ */
+static void ipc_rx_work(struct work_struct *ws)
+{
+ struct shmem_link_device *shmd;
+ struct link_device *ld;
+ struct io_device *iod;
+ struct sk_buff *skb;
+ int i;
+
+ shmd = container_of(ws, struct shmem_link_device, ipc_rx_dwork.work);
+ ld = &shmd->ld;
+
+ for (i = 0; i < MAX_SIPC5_DEV; i++) {
+ iod = shmd->iod[i];
+ while (1) {
+ skb = skb_dequeue(ld->skb_rxq[i]);
+ if (!skb)
+ break;
+ iod->recv_skb(iod, ld, skb);
+ }
+ }
+}
+
+/**
+ * rx_ipc_frames
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Returns
+ * ret < 0 : error
+ * ret == 0 : ILLEGAL status
+ * ret > 0 : valid data
+ *
+ * Must be invoked only when there is data in the corresponding RXQ.
+ *
+ * Requires a recv_skb method in the io_device instance, so this function must
+ * be used for only SIPC5.
+ */
+static int rx_ipc_frames(struct shmem_link_device *shmd, int dev,
+ struct circ_status *circ)
+{
+ struct link_device *ld = &shmd->ld;
+ struct sk_buff_head *rxq = ld->skb_rxq[dev];
+ struct sk_buff *skb;
+ int ret;
+ /**
+ * variables for the status of the circular queue
+ */
+ u8 *src;
+ u8 hdr[SIPC5_MIN_HEADER_SIZE];
+ /**
+ * variables for RX processing
+ */
+ int qsize; /* size of the queue */
+ int rcvd; /* size of data in the RXQ or error */
+ int rest; /* size of the rest data */
+ int out; /* index to the start of current frame */
+ u8 *dst; /* pointer to the destination buffer */
+ int tot; /* total length including padding data */
+
+ src = circ->buff;
+ qsize = circ->qsize;
+ out = circ->out;
+ rcvd = circ->size;
+
+ rest = rcvd;
+ tot = 0;
+ while (rest > 0) {
+ /* Copy the header in the frame to the header buffer */
+ circ_read(hdr, src, qsize, out, SIPC5_MIN_HEADER_SIZE);
+
+ /* Check the config field in the header */
+ if (unlikely(!sipc5_start_valid(hdr))) {
+ mif_err("%s: ERR! %s INVALID config 0x%02X "
+ "(rcvd %d, rest %d)\n", ld->name,
+ get_dev_name(dev), hdr[0], rcvd, rest);
+ ret = -EBADMSG;
+ goto exit;
+ }
+
+ /* Verify the total length of the frame (data + padding) */
+ tot = sipc5_get_total_len(hdr);
+ if (unlikely(tot > rest)) {
+ mif_err("%s: ERR! %s tot %d > rest %d (rcvd %d)\n",
+ ld->name, get_dev_name(dev), tot, rest, rcvd);
+ ret = -EBADMSG;
+ goto exit;
+ }
+
+ /* Allocate an skb */
+ skb = dev_alloc_skb(tot);
+ if (!skb) {
+ mif_err("%s: ERR! %s dev_alloc_skb fail\n",
+ ld->name, get_dev_name(dev));
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ /* Set the attribute of the skb as "single frame" */
+ skbpriv(skb)->single_frame = true;
+
+ /* Read the frame from the RXQ */
+ dst = skb_put(skb, tot);
+ circ_read(dst, src, qsize, out, tot);
+
+ /* Store the skb to the corresponding skb_rxq */
+ skb_queue_tail(rxq, skb);
+
+ /* Calculate new out value */
+ rest -= tot;
+ out += tot;
+ if (unlikely(out >= qsize))
+ out -= qsize;
+ }
+
+ /* Update tail (out) pointer to empty out the RXQ */
+ set_rxq_tail(shmd, dev, circ->in);
+
+ return rcvd;
+
+exit:
+#ifdef DEBUG_MODEM_IF
+ mif_err("%s: ERR! rcvd:%d tot:%d rest:%d\n", ld->name, rcvd, tot, rest);
+ pr_ipc(1, "c2c: ERR! CP2MIF", (src + out), (rest > 20) ? 20 : rest);
+#endif
+
+ return ret;
+}
+
+/**
+ * msg_handler: receives IPC messages from every RXQ
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * 1) Receives all IPC message frames currently in every IPC RXQ.
+ * 2) Sends RES_ACK responses if there are REQ_ACK requests from a CP.
+ * 3) Completes all threads waiting for the corresponding RES_ACK from a CP if
+ * there is any RES_ACK response.
+ */
+static void msg_handler(struct shmem_link_device *shmd, struct mem_status *mst)
+{
+ struct link_device *ld = &shmd->ld;
+ struct circ_status circ;
+ int i = 0;
+ int ret = 0;
+
+ if (!ipc_active(shmd))
+ return;
+
+ /* Read data from every RXQ */
+ for (i = 0; i < MAX_SIPC5_DEV; i++) {
+ /* Invoke an RX function only when there is data in the RXQ */
+ if (likely(mst->head[i][RX] != mst->tail[i][RX])) {
+ ret = get_rxq_rcvd(shmd, i, mst, &circ);
+ if (unlikely(ret < 0)) {
+ mif_err("%s: ERR! get_rxq_rcvd fail (err %d)\n",
+ ld->name, ret);
+#ifdef DEBUG_MODEM_IF
+ trigger_forced_cp_crash(shmd);
+#endif
+ return;
+ }
+
+ ret = rx_ipc_frames(shmd, i, &circ);
+ if (ret < 0) {
+#ifdef DEBUG_MODEM_IF
+ trigger_forced_cp_crash(shmd);
+#endif
+ reset_rxq_circ(shmd, i);
+ }
+ }
+ }
+
+ /* Schedule soft IRQ for RX */
+ queue_delayed_work(system_nrt_wq, &shmd->ipc_rx_dwork, 0);
+}
+
+static void msg_rx_task(unsigned long data)
+{
+ struct shmem_link_device *shmd = (struct shmem_link_device *)data;
+ struct link_device *ld = &shmd->ld;
+ struct mem_status mst;
+ u16 mask = 0;
+
+ get_shmem_status(shmd, RX, &mst);
+
+ if ((mst.head[IPC_FMT][RX] != mst.tail[IPC_FMT][RX])
+ || (mst.head[IPC_RAW][RX] != mst.tail[IPC_RAW][RX])) {
+#if 0
+ print_mem_status(ld, &mst);
+#endif
+ msg_handler(shmd, &mst);
+ }
+
+ /*
+ ** Check and process REQ_ACK (at this time, in == out)
+ */
+ if (unlikely(shmd->dev[IPC_FMT]->req_ack_rcvd)) {
+ mask |= get_mask_res_ack(shmd, IPC_FMT);
+ shmd->dev[IPC_FMT]->req_ack_rcvd = 0;
+ }
+
+ if (unlikely(shmd->dev[IPC_RAW]->req_ack_rcvd)) {
+ mask |= get_mask_res_ack(shmd, IPC_RAW);
+ shmd->dev[IPC_RAW]->req_ack_rcvd = 0;
+ }
+
+ if (unlikely(mask)) {
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: send RES_ACK 0x%04X\n", ld->name, mask);
+#endif
+ send_int2cp(shmd, INT_NON_CMD(mask));
+ }
+}
+
+/**
+ * ipc_handler: processes a SHMEM command or receives IPC messages
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Invokes cmd_handler for a SHMEM command or msg_handler for IPC messages.
+ */
+static void ipc_handler(struct shmem_link_device *shmd, struct mem_status *mst)
+{
+#ifdef DEBUG_MODEM_IF
+ struct link_device *ld = &shmd->ld;
+#endif
+ u16 intr = mst->int2ap;
+
+ if (unlikely(INT_CMD_VALID(intr))) {
+ cmd_handler(shmd, intr);
+ return;
+ }
+
+ /*
+ ** Check REQ_ACK from CP -> REQ_ACK will be processed in the RX tasklet
+ */
+ if (unlikely(intr & get_mask_req_ack(shmd, IPC_FMT)))
+ shmd->dev[IPC_FMT]->req_ack_rcvd = 1;
+
+ if (unlikely(intr & get_mask_req_ack(shmd, IPC_RAW)))
+ shmd->dev[IPC_RAW]->req_ack_rcvd = 1;
+
+ /*
+ ** Check and process RES_ACK from CP
+ */
+ if (unlikely(intr & get_mask_res_ack(shmd, IPC_FMT))) {
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: recv FMT RES_ACK\n", ld->name);
+#endif
+ complete(&shmd->req_ack_cmpl[IPC_FMT]);
+ }
+
+ if (unlikely(intr & get_mask_res_ack(shmd, IPC_RAW))) {
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: recv RAW RES_ACK\n", ld->name);
+#endif
+ complete(&shmd->req_ack_cmpl[IPC_RAW]);
+ }
+
+ /*
+ ** Schedule RX tasklet
+ */
+ tasklet_hi_schedule(&shmd->rx_tsk);
+}
+
+/**
+ * rx_udl_frames
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Returns
+ * ret < 0 : error
+ * ret == 0 : ILLEGAL status
+ * ret > 0 : valid data
+ *
+ * Must be invoked only when there is data in the corresponding RXQ.
+ *
+ * Requires a recv_skb method in the io_device instance, so this function must
+ * be used for only SIPC5.
+ */
+static int rx_udl_frames(struct shmem_link_device *shmd, int dev,
+ struct circ_status *circ)
+{
+ struct link_device *ld = &shmd->ld;
+ struct io_device *iod;
+ struct sk_buff *skb;
+ int ret;
+ /**
+ * variables for the status of the circular queue
+ */
+ u8 *src;
+ u8 hdr[SIPC5_MIN_HEADER_SIZE];
+ /**
+ * variables for RX processing
+ */
+ int qsize; /* size of the queue */
+ int rcvd; /* size of data in the RXQ or error */
+ int rest; /* size of the rest data */
+ int out; /* index to the start of current frame */
+ u8 *dst; /* pointer to the destination buffer */
+ int tot; /* total length including padding data */
+
+ src = circ->buff;
+ qsize = circ->qsize;
+ out = circ->out;
+ rcvd = circ->size;
+
+ rest = rcvd;
+ tot = 0;
+ while (rest > 0) {
+ /* Copy the header in the frame to the header buffer */
+ circ_read(hdr, src, qsize, out, SIPC5_MIN_HEADER_SIZE);
+
+ /* Check the config field in the header */
+ if (unlikely(!sipc5_start_valid(hdr))) {
+ mif_err("%s: ERR! %s INVALID config 0x%02X "
+ "(rest %d, rcvd %d)\n", ld->name,
+ get_dev_name(dev), hdr[0], rest, rcvd);
+ pr_ipc(1, "UDL", (src + out), (rest > 20) ? 20 : rest);
+ ret = -EBADMSG;
+ goto exit;
+ }
+
+ /* Verify the total length of the frame (data + padding) */
+ tot = sipc5_get_total_len(hdr);
+ if (unlikely(tot > rest)) {
+ mif_err("%s: ERR! %s tot %d > rest %d (rcvd %d)\n",
+ ld->name, get_dev_name(dev), tot, rest, rcvd);
+ ret = -ENODATA;
+ goto exit;
+ }
+
+ /* Allocate an skb */
+ skb = alloc_skb(tot + NET_SKB_PAD, GFP_KERNEL);
+ if (!skb) {
+ mif_err("%s: ERR! %s alloc_skb fail\n",
+ ld->name, get_dev_name(dev));
+ ret = -ENOMEM;
+ goto exit;
+ }
+ skb_reserve(skb, NET_SKB_PAD);
+
+ /* Set the attribute of the skb as "single frame" */
+ skbpriv(skb)->single_frame = true;
+
+ /* Read the frame from the RXQ */
+ dst = skb_put(skb, tot);
+ circ_read(dst, src, qsize, out, tot);
+
+ /* Pass the skb to an iod */
+ iod = link_get_iod_with_channel(ld, sipc5_get_ch_id(skb->data));
+ if (!iod) {
+ mif_err("%s: ERR! no IPC_BOOT iod\n", ld->name);
+ break;
+ }
+
+#ifdef DEBUG_MODEM_IF
+ if (!std_udl_with_payload(std_udl_get_cmd(skb->data))) {
+ if (ld->mode == LINK_MODE_DLOAD) {
+ pr_ipc(0, "[CP->AP] DL CMD", skb->data,
+ (skb->len > 20 ? 20 : skb->len));
+ } else {
+ pr_ipc(0, "[CP->AP] UL CMD", skb->data,
+ (skb->len > 20 ? 20 : skb->len));
+ }
+ }
+#endif
+
+ iod->recv_skb(iod, ld, skb);
+
+ /* Calculate new out value */
+ rest -= tot;
+ out += tot;
+ if (unlikely(out >= qsize))
+ out -= qsize;
+ }
+
+ /* Update tail (out) pointer to empty out the RXQ */
+ set_rxq_tail(shmd, dev, circ->in);
+
+ return rcvd;
+
+exit:
+ return ret;
+}
+
+/**
+ * udl_rx_work
+ * @ws: pointer to an instance of the work_struct structure
+ *
+ * Invokes the recv method in the io_device instance to perform receiving IPC
+ * messages from each skb.
+ */
+static void udl_rx_work(struct work_struct *ws)
+{
+ struct shmem_link_device *shmd;
+ struct link_device *ld;
+ struct sk_buff_head *rxq;
+ struct mem_status mst;
+ struct circ_status circ;
+ int dev = IPC_RAW;
+
+ shmd = container_of(ws, struct shmem_link_device, udl_rx_dwork.work);
+ ld = &shmd->ld;
+ rxq = ld->skb_rxq[dev];
+
+ while (1) {
+ get_shmem_status(shmd, RX, &mst);
+ if (mst.head[dev][RX] == mst.tail[dev][RX])
+ break;
+
+ /* Invoke an RX function only when there is data in the RXQ */
+ if (get_rxq_rcvd(shmd, dev, &mst, &circ) < 0) {
+ mif_err("%s: ERR! get_rxq_rcvd fail\n", ld->name);
+#ifdef DEBUG_MODEM_IF
+ trigger_forced_cp_crash(shmd);
+#endif
+ break;
+ }
+
+ if (rx_udl_frames(shmd, dev, &circ) < 0) {
+ skb_queue_purge(rxq);
+ break;
+ }
+ }
+}
+
+/**
+ * udl_handler: receives BOOT/DUMP IPC messages from every RXQ
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * 1) Receives all IPC message frames currently in every IPC RXQ.
+ * 2) Sends RES_ACK responses if there are REQ_ACK requests from a CP.
+ * 3) Completes all threads waiting for the corresponding RES_ACK from a CP if
+ * there is any RES_ACK response.
+ */
+static void udl_handler(struct shmem_link_device *shmd, struct mem_status *mst)
+{
+ u16 intr = mst->int2ap;
+
+ /* Schedule soft IRQ for RX */
+ queue_delayed_work(system_nrt_wq, &shmd->udl_rx_dwork, 0);
+
+ /* Check and process RES_ACK */
+ if (intr & INT_MASK_RES_ACK_SET) {
+ if (intr & get_mask_res_ack(shmd, IPC_RAW)) {
+#ifdef DEBUG_MODEM_IF
+ struct link_device *ld = &shmd->ld;
+ mif_info("%s: recv RAW RES_ACK\n", ld->name);
+ print_circ_status(ld, IPC_RAW, mst);
+#endif
+ complete(&shmd->req_ack_cmpl[IPC_RAW]);
+ }
+ }
+}
+
+/**
+ * c2c_irq_handler: interrupt handler for a C2C interrupt
+ * @data: pointer to a data
+ *
+ * 1) Reads the interrupt value
+ * 2) Performs interrupt handling
+ *
+ * Flow for normal interrupt handling:
+ * c2c_irq_handler -> udl_handler
+ * c2c_irq_handler -> ipc_handler -> cmd_handler -> cmd_xxx_handler
+ * c2c_irq_handler -> ipc_handler -> msg_handler -> rx_ipc_frames -> ...
+ */
+static void c2c_irq_handler(void *data, u32 intr)
+{
+ struct shmem_link_device *shmd = (struct shmem_link_device *)data;
+ struct link_device *ld = (struct link_device *)&shmd->ld;
+ struct mem_status *mst = msq_get_free_slot(&shmd->stat_list);
+
+ get_shmem_status(shmd, RX, mst);
+
+ if (unlikely(ld->mode == LINK_MODE_OFFLINE)) {
+ mif_info("%s: ld->mode == LINK_MODE_OFFLINE\n", ld->name);
+ return;
+ }
+
+ if (unlikely(!INT_VALID(intr))) {
+ mif_info("%s: ERR! invalid intr 0x%X\n", ld->name, intr);
+ return;
+ }
+
+ mst->int2ap = intr;
+
+ if (ld->mode == LINK_MODE_DLOAD || ld->mode == LINK_MODE_ULOAD)
+ udl_handler(shmd, mst);
+ else
+ ipc_handler(shmd, mst);
+}
+
+#if 1
+/* Functions for IPC/BOOT/DUMP TX */
+#endif
+
+/**
+ * write_ipc_to_txq
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @circ: pointer to an instance of circ_status structure
+ * @skb: pointer to an instance of sk_buff structure
+ *
+ * Must be invoked only when there is enough space in the TXQ.
+ */
+static void write_ipc_to_txq(struct shmem_link_device *shmd, int dev,
+ struct circ_status *circ, struct sk_buff *skb)
+{
+ u32 qsize = circ->qsize;
+ u32 in = circ->in;
+ u8 *buff = circ->buff;
+ u8 *src = skb->data;
+ u32 len = skb->len;
+#ifdef DEBUG_MODEM_IF
+ struct io_device *iod = skbpriv(skb)->iod;
+ struct modem_ctl *mc = shmd->ld.mc;
+ char tag[MIF_MAX_STR_LEN];
+
+ snprintf(tag, MIF_MAX_STR_LEN, "LNK: %s->%s", iod->name, mc->name);
+
+ if (dev == IPC_FMT)
+ pr_ipc(1, tag, src, (len > 20 ? 20 : len));
+#if 0
+ if (dev == IPC_RAW)
+ pr_ipc(0, tag, src, (len > 20 ? 20 : len));
+#endif
+#endif
+
+ /* Write data to the TXQ */
+ circ_write(buff, src, qsize, in, len);
+
+ /* Update new head (in) pointer */
+ set_txq_head(shmd, dev, circ_new_pointer(qsize, in, len));
+}
+
+/**
+ * xmit_ipc_msg
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Tries to transmit IPC messages in the skb_txq of @dev as many as possible.
+ *
+ * Returns total length of IPC messages transmitted or an error code.
+ */
+static int xmit_ipc_msg(struct shmem_link_device *shmd, int dev)
+{
+ struct link_device *ld = &shmd->ld;
+ struct sk_buff_head *txq = ld->skb_txq[dev];
+ struct sk_buff *skb;
+ unsigned long flags;
+ struct circ_status circ;
+ int space;
+ int copied = 0;
+
+ /* Acquire the spin lock for a TXQ */
+ spin_lock_irqsave(&shmd->tx_lock[dev], flags);
+
+ while (1) {
+ /* Get the size of free space in the TXQ */
+ space = get_txq_space(shmd, dev, &circ);
+ if (unlikely(space < 0)) {
+#ifdef DEBUG_MODEM_IF
+ /* Trigger a enforced CP crash */
+ trigger_forced_cp_crash(shmd);
+#endif
+ /* Empty out the TXQ */
+ reset_txq_circ(shmd, dev);
+ copied = -EIO;
+ break;
+ }
+
+ skb = skb_dequeue(txq);
+ if (unlikely(!skb))
+ break;
+
+ /* Check the free space size comparing with skb->len */
+ if (unlikely(space < skb->len)) {
+#ifdef DEBUG_MODEM_IF
+ struct mem_status mst;
+#endif
+ /* Set res_required flag for the "dev" */
+ atomic_set(&shmd->res_required[dev], 1);
+
+ /* Take the skb back to the skb_txq */
+ skb_queue_head(txq, skb);
+
+ mif_err("%s: <by %pf> NOSPC in %s_TXQ"
+ "{qsize:%u in:%u out:%u} free:%u < len:%u\n",
+ ld->name, CALLER, get_dev_name(dev),
+ circ.qsize, circ.in, circ.out, space, skb->len);
+#ifdef DEBUG_MODEM_IF
+ get_shmem_status(shmd, TX, &mst);
+ print_circ_status(ld, dev, &mst);
+#endif
+ copied = -ENOSPC;
+ break;
+ }
+
+#ifdef DEBUG_MODEM_IF
+ if (!ipc_active(shmd)) {
+ if (get_magic(shmd) == SHM_PM_MAGIC) {
+ mif_err("%s: Going to SLEEP\n", ld->name);
+ copied = -EBUSY;
+ } else {
+ mif_err("%s: IPC is NOT active\n", ld->name);
+ copied = -EIO;
+ }
+ break;
+ }
+#endif
+
+ /* TX only when there is enough space in the TXQ */
+ write_ipc_to_txq(shmd, dev, &circ, skb);
+ copied += skb->len;
+ dev_kfree_skb_any(skb);
+ }
+
+ /* Release the spin lock */
+ spin_unlock_irqrestore(&shmd->tx_lock[dev], flags);
+
+ return copied;
+}
+
+/**
+ * wait_for_res_ack
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * 1) Sends an REQ_ACK interrupt for @dev to CP.
+ * 2) Waits for the corresponding RES_ACK for @dev from CP.
+ *
+ * Returns the return value from wait_for_completion_interruptible_timeout().
+ */
+static int wait_for_res_ack(struct shmem_link_device *shmd, int dev)
+{
+ struct link_device *ld = &shmd->ld;
+ struct completion *cmpl = &shmd->req_ack_cmpl[dev];
+ unsigned long timeout = msecs_to_jiffies(RES_ACK_WAIT_TIMEOUT);
+ int ret;
+ u16 mask;
+
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: send %s REQ_ACK\n", ld->name, get_dev_name(dev));
+#endif
+
+ mask = get_mask_req_ack(shmd, dev);
+ send_int2cp(shmd, INT_NON_CMD(mask));
+
+ /* ret < 0 if interrupted, ret == 0 on timeout */
+ ret = wait_for_completion_interruptible_timeout(cmpl, timeout);
+ if (ret < 0) {
+ mif_err("%s: %s: wait_for_completion interrupted! (ret %d)\n",
+ ld->name, get_dev_name(dev), ret);
+ goto exit;
+ }
+
+ if (ret == 0) {
+ struct mem_status mst;
+ get_shmem_status(shmd, TX, &mst);
+
+ mif_err("%s: wait_for_completion TIMEOUT! (no %s_RES_ACK)\n",
+ ld->name, get_dev_name(dev));
+
+ /*
+ ** The TXQ must be checked whether or not it is empty, because
+ ** an interrupt mask can be overwritten by the next interrupt.
+ */
+ if (mst.head[dev][TX] == mst.tail[dev][TX]) {
+ ret = get_txq_buff_size(shmd, dev);
+#ifdef DEBUG_MODEM_IF
+ mif_err("%s: %s_TXQ has been emptied\n",
+ ld->name, get_dev_name(dev));
+ print_circ_status(ld, dev, &mst);
+#endif
+ }
+ }
+
+exit:
+ return ret;
+}
+
+/**
+ * process_res_ack
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * 1) Tries to transmit IPC messages in the skb_txq with xmit_ipc_msg().
+ * 2) Sends an interrupt to CP if there is no error from xmit_ipc_msg().
+ * 3) Restarts SHMEM flow control if xmit_ipc_msg() returns -ENOSPC.
+ *
+ * Returns the return value from xmit_ipc_msg().
+ */
+static int process_res_ack(struct shmem_link_device *shmd, int dev)
+{
+ int ret;
+ u16 mask;
+
+ ret = xmit_ipc_msg(shmd, dev);
+ if (ret > 0) {
+ mask = get_mask_send(shmd, dev);
+ send_int2cp(shmd, INT_NON_CMD(mask));
+ get_shmem_status(shmd, TX, msq_get_free_slot(&shmd->stat_list));
+ }
+
+ if (ret >= 0)
+ atomic_set(&shmd->res_required[dev], 0);
+
+ return ret;
+}
+
+/**
+ * fmt_tx_work: performs TX for FMT IPC device under SHMEM flow control
+ * @ws: pointer to an instance of the work_struct structure
+ *
+ * 1) Starts waiting for RES_ACK of FMT IPC device.
+ * 2) Returns immediately if the wait is interrupted.
+ * 3) Restarts SHMEM flow control if there is a timeout from the wait.
+ * 4) Otherwise, it performs processing RES_ACK for FMT IPC device.
+ */
+static void fmt_tx_work(struct work_struct *ws)
+{
+ struct link_device *ld;
+ struct shmem_link_device *shmd;
+ int ret;
+
+ ld = container_of(ws, struct link_device, fmt_tx_dwork.work);
+ shmd = to_shmem_link_device(ld);
+
+ ret = wait_for_res_ack(shmd, IPC_FMT);
+ /* ret < 0 if interrupted */
+ if (ret < 0)
+ return;
+
+ /* ret == 0 on timeout */
+ if (ret == 0) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_FMT], 0);
+ return;
+ }
+
+ ret = process_res_ack(shmd, IPC_FMT);
+ if (ret >= 0) {
+ permit_cp_sleep(shmd);
+ return;
+ }
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC || ret == -EBUSY) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_FMT],
+ msecs_to_jiffies(1));
+ }
+}
+
+/**
+ * raw_tx_work: performs TX for RAW IPC device under SHMEM flow control.
+ * @ws: pointer to an instance of the work_struct structure
+ *
+ * 1) Starts waiting for RES_ACK of RAW IPC device.
+ * 2) Returns immediately if the wait is interrupted.
+ * 3) Restarts SHMEM flow control if there is a timeout from the wait.
+ * 4) Otherwise, it performs processing RES_ACK for RAW IPC device.
+ */
+static void raw_tx_work(struct work_struct *ws)
+{
+ struct link_device *ld;
+ struct shmem_link_device *shmd;
+ int ret;
+
+ ld = container_of(ws, struct link_device, raw_tx_dwork.work);
+ shmd = to_shmem_link_device(ld);
+
+ ret = wait_for_res_ack(shmd, IPC_RAW);
+ /* ret < 0 if interrupted */
+ if (ret < 0)
+ return;
+
+ /* ret == 0 on timeout */
+ if (ret == 0) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_RAW], 0);
+ return;
+ }
+
+ ret = process_res_ack(shmd, IPC_RAW);
+ if (ret >= 0) {
+ permit_cp_sleep(shmd);
+ mif_netif_wake(ld);
+ return;
+ }
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC || ret == -EBUSY) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_RAW],
+ msecs_to_jiffies(1));
+ }
+}
+
+/**
+ * c2c_send_ipc
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @skb: pointer to an skb that will be transmitted
+ *
+ * 1) Tries to transmit IPC messages in the skb_txq with xmit_ipc_msg().
+ * 2) Sends an interrupt to CP if there is no error from xmit_ipc_msg().
+ * 3) Starts SHMEM flow control if xmit_ipc_msg() returns -ENOSPC.
+ */
+static int c2c_send_ipc(struct shmem_link_device *shmd, int dev)
+{
+ struct link_device *ld = &shmd->ld;
+ int ret;
+ u16 mask;
+
+ if (atomic_read(&shmd->res_required[dev]) > 0) {
+ mif_info("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev));
+ return 0;
+ }
+
+ ret = xmit_ipc_msg(shmd, dev);
+ if (likely(ret > 0)) {
+ mask = get_mask_send(shmd, dev);
+ send_int2cp(shmd, INT_NON_CMD(mask));
+ get_shmem_status(shmd, TX, msq_get_free_slot(&shmd->stat_list));
+ goto exit;
+ }
+
+ /* If there was no TX, just exit */
+ if (ret == 0)
+ goto exit;
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC || ret == -EBUSY) {
+ /* Prohibit CP from sleeping until the TXQ buffer is empty */
+ if (forbid_cp_sleep(shmd) < 0) {
+ trigger_forced_cp_crash(shmd);
+ goto exit;
+ }
+
+ /*----------------------------------------------------*/
+ /* shmd->res_required[dev] was set in xmit_ipc_msg(). */
+ /*----------------------------------------------------*/
+
+ if (dev == IPC_RAW)
+ mif_netif_stop(ld);
+
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[dev],
+ msecs_to_jiffies(1));
+ }
+
+exit:
+ return ret;
+}
+
+/**
+ * c2c_try_send_ipc
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @iod: pointer to an instance of the io_device structure
+ * @skb: pointer to an skb that will be transmitted
+ *
+ * 1) Enqueues an skb to the skb_txq for @dev in the link device instance.
+ * 2) Tries to transmit IPC messages with c2c_send_ipc().
+ */
+static void c2c_try_send_ipc(struct shmem_link_device *shmd, int dev,
+ struct io_device *iod, struct sk_buff *skb)
+{
+ struct link_device *ld = &shmd->ld;
+ struct sk_buff_head *txq = ld->skb_txq[dev];
+ int ret;
+
+ if (forbid_cp_sleep(shmd) < 0) {
+ trigger_forced_cp_crash(shmd);
+ goto exit;
+ }
+
+ if (unlikely(txq->qlen >= MAX_SKB_TXQ_DEPTH)) {
+ mif_err("%s: %s txq->qlen %d >= %d\n", ld->name,
+ get_dev_name(dev), txq->qlen, MAX_SKB_TXQ_DEPTH);
+ dev_kfree_skb_any(skb);
+ goto exit;
+ }
+
+ skb_queue_tail(txq, skb);
+
+ ret = c2c_send_ipc(shmd, dev);
+ if (ret < 0) {
+ mif_err("%s->%s: ERR! c2c_send_ipc fail (err %d)\n",
+ iod->name, ld->name, ret);
+ }
+
+exit:
+ permit_cp_sleep(shmd);
+}
+
+static int c2c_send_udl_cmd(struct shmem_link_device *shmd, int dev,
+ struct io_device *iod, struct sk_buff *skb)
+{
+ struct link_device *ld = &shmd->ld;
+ u8 *buff;
+ u8 *src;
+ u32 qsize;
+ u32 in;
+ int space;
+ int tx_bytes;
+ struct circ_status circ;
+
+ if (iod->format == IPC_BOOT) {
+ pr_ipc(0, "[AP->CP] DL CMD", skb->data,
+ (skb->len > 20 ? 20 : skb->len));
+ } else {
+ pr_ipc(0, "[AP->CP] UL CMD", skb->data,
+ (skb->len > 20 ? 20 : skb->len));
+ }
+
+ /* Get the size of free space in the TXQ */
+ space = get_txq_space(shmd, dev, &circ);
+ if (space < 0) {
+ reset_txq_circ(shmd, dev);
+ tx_bytes = -EIO;
+ goto exit;
+ }
+
+ /* Get the size of data to be sent */
+ tx_bytes = skb->len;
+
+ /* Check the size of free space */
+ if (space < tx_bytes) {
+ mif_err("%s: NOSPC in %s_TXQ {qsize:%u in:%u out:%u}, "
+ "free:%u < tx_bytes:%u\n", ld->name, get_dev_name(dev),
+ circ.qsize, circ.in, circ.out, space, tx_bytes);
+ tx_bytes = -ENOSPC;
+ goto exit;
+ }
+
+ /* Write data to the TXQ */
+ buff = circ.buff;
+ src = skb->data;
+ qsize = circ.qsize;
+ in = circ.in;
+ circ_write(buff, src, qsize, in, tx_bytes);
+
+ /* Update new head (in) pointer */
+ set_txq_head(shmd, dev, circ_new_pointer(qsize, circ.in, tx_bytes));
+
+exit:
+ dev_kfree_skb_any(skb);
+ return tx_bytes;
+}
+
+static int c2c_send_udl_data(struct shmem_link_device *shmd, int dev)
+{
+ struct link_device *ld = &shmd->ld;
+ struct sk_buff_head *txq = ld->skb_txq[dev];
+ struct sk_buff *skb;
+ u8 *src;
+ int tx_bytes;
+ int copied;
+ u8 *buff;
+ u32 qsize;
+ u32 in;
+ u32 out;
+ int space;
+ struct circ_status circ;
+
+ /* Get the size of free space in the TXQ */
+ space = get_txq_space(shmd, dev, &circ);
+ if (space < 0) {
+#ifdef DEBUG_MODEM_IF
+ /* Trigger a enforced CP crash */
+ trigger_forced_cp_crash(shmd);
+#endif
+ /* Empty out the TXQ */
+ reset_txq_circ(shmd, dev);
+ return -EFAULT;
+ }
+
+ buff = circ.buff;
+ qsize = circ.qsize;
+ in = circ.in;
+ out = circ.out;
+ space = circ.size;
+
+ copied = 0;
+ while (1) {
+ skb = skb_dequeue(txq);
+ if (!skb)
+ break;
+
+ /* Get the size of data to be sent */
+ src = skb->data;
+ tx_bytes = skb->len;
+
+ /* Check the free space size comparing with skb->len */
+ if (space < tx_bytes) {
+ /* Set res_required flag for the "dev" */
+ atomic_set(&shmd->res_required[dev], 1);
+
+ /* Take the skb back to the skb_txq */
+ skb_queue_head(txq, skb);
+
+ mif_info("NOSPC in RAW_TXQ {qsize:%u in:%u out:%u}, "
+ "space:%u < tx_bytes:%u\n",
+ qsize, in, out, space, tx_bytes);
+ break;
+ }
+
+ /*
+ ** TX only when there is enough space in the TXQ
+ */
+ circ_write(buff, src, qsize, in, tx_bytes);
+
+ copied += tx_bytes;
+ in = circ_new_pointer(qsize, in, tx_bytes);
+ space -= tx_bytes;
+
+ dev_kfree_skb_any(skb);
+ }
+
+ /* Update new head (in) pointer */
+ if (copied > 0) {
+ in = circ_new_pointer(qsize, circ.in, copied);
+ set_txq_head(shmd, dev, in);
+ }
+
+ return copied;
+}
+
+/**
+ * c2c_send_udl
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @iod: pointer to an instance of the io_device structure
+ * @skb: pointer to an skb that will be transmitted
+ *
+ * 1) Enqueues an skb to the skb_txq for @dev in the link device instance.
+ * 2) Tries to transmit IPC messages in the skb_txq by invoking xmit_ipc_msg()
+ * function.
+ * 3) Sends an interrupt to CP if there is no error from xmit_ipc_msg().
+ * 4) Starts SHMEM flow control if xmit_ipc_msg() returns -ENOSPC.
+ */
+static void c2c_send_udl(struct shmem_link_device *shmd, int dev,
+ struct io_device *iod, struct sk_buff *skb)
+{
+ struct link_device *ld = &shmd->ld;
+ struct sk_buff_head *txq = ld->skb_txq[dev];
+ struct completion *cmpl = &shmd->req_ack_cmpl[dev];
+ struct std_dload_info *dl_info = &shmd->dl_info;
+ struct mem_status mst;
+ u32 timeout = msecs_to_jiffies(RES_ACK_WAIT_TIMEOUT);
+ u32 udl_cmd;
+ int ret;
+ u16 mask = get_mask_send(shmd, dev);
+
+ udl_cmd = std_udl_get_cmd(skb->data);
+ if (iod->format == IPC_RAMDUMP || !std_udl_with_payload(udl_cmd)) {
+ ret = c2c_send_udl_cmd(shmd, dev, iod, skb);
+ if (ret > 0)
+ send_int2cp(shmd, INT_NON_CMD(mask));
+ else
+ mif_err("ERR! c2c_send_udl_cmd fail (err %d)\n", ret);
+ goto exit;
+ }
+
+ skb_queue_tail(txq, skb);
+ if (txq->qlen < dl_info->num_frames)
+ goto exit;
+
+ mask |= get_mask_req_ack(shmd, dev);
+ while (1) {
+ ret = c2c_send_udl_data(shmd, dev);
+ if (ret < 0) {
+ mif_err("ERR! c2c_send_udl_data fail (err %d)\n", ret);
+ skb_queue_purge(txq);
+ break;
+ }
+
+ if (skb_queue_empty(txq)) {
+ send_int2cp(shmd, INT_NON_CMD(mask));
+ break;
+ }
+
+ send_int2cp(shmd, INT_NON_CMD(mask));
+
+ do {
+ ret = wait_for_completion_timeout(cmpl, timeout);
+ get_shmem_status(shmd, TX, &mst);
+ } while (mst.head[dev][TX] != mst.tail[dev][TX]);
+ }
+
+exit:
+ return;
+}
+
+/**
+ * c2c_send
+ * @ld: pointer to an instance of the link_device structure
+ * @iod: pointer to an instance of the io_device structure
+ * @skb: pointer to an skb that will be transmitted
+ *
+ * Returns the length of data transmitted or an error code.
+ *
+ * Normal call flow for an IPC message:
+ * c2c_try_send_ipc -> c2c_send_ipc -> xmit_ipc_msg -> write_ipc_to_txq
+ *
+ * Call flow on congestion in a IPC TXQ:
+ * c2c_try_send_ipc -> c2c_send_ipc -> xmit_ipc_msg ,,, queue_delayed_work
+ * => xxx_tx_work -> wait_for_res_ack
+ * => msg_handler
+ * => process_res_ack -> xmit_ipc_msg (,,, queue_delayed_work ...)
+ */
+static int c2c_send(struct link_device *ld, struct io_device *iod,
+ struct sk_buff *skb)
+{
+ struct shmem_link_device *shmd = to_shmem_link_device(ld);
+ int dev = iod->format;
+ int len = skb->len;
+
+ switch (dev) {
+ case IPC_FMT:
+ case IPC_RAW:
+ if (likely(ld->mode == LINK_MODE_IPC)) {
+ c2c_try_send_ipc(shmd, dev, iod, skb);
+ } else {
+ mif_err("%s->%s: ERR! ld->mode != LINK_MODE_IPC\n",
+ iod->name, ld->name);
+ dev_kfree_skb_any(skb);
+ }
+ return len;
+
+ case IPC_BOOT:
+ case IPC_RAMDUMP:
+ c2c_send_udl(shmd, IPC_RAW, iod, skb);
+ return len;
+
+ default:
+ mif_err("%s: ERR! no TXQ for %s\n", ld->name, iod->name);
+ dev_kfree_skb_any(skb);
+ return -ENODEV;
+ }
+}
+
+#if 1
+/* Functions for BOOT/DUMP and INIT */
+#endif
+
+static int c2c_dload_start(struct link_device *ld, struct io_device *iod)
+{
+ struct shmem_link_device *shmd = to_shmem_link_device(ld);
+ u32 magic;
+
+ ld->mode = LINK_MODE_DLOAD;
+
+ clear_shmem_map(shmd);
+
+ set_magic(shmd, SHM_BOOT_MAGIC);
+ magic = get_magic(shmd);
+ if (magic != SHM_BOOT_MAGIC) {
+ mif_err("%s: ERR! magic 0x%08X != SHM_BOOT_MAGIC 0x%08X\n",
+ ld->name, magic, SHM_BOOT_MAGIC);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/**
+ * c2c_set_dload_info
+ * @ld: pointer to an instance of link_device structure
+ * @iod: pointer to an instance of io_device structure
+ * @arg: pointer to an instance of std_dload_info structure in "user" memory
+ *
+ */
+static int c2c_set_dload_info(struct link_device *ld, struct io_device *iod,
+ unsigned long arg)
+{
+ struct shmem_link_device *shmd = to_shmem_link_device(ld);
+ struct std_dload_info *dl_info = &shmd->dl_info;
+ int ret;
+
+ ret = copy_from_user(dl_info, (void __user *)arg,
+ sizeof(struct std_dload_info));
+ if (ret) {
+ mif_err("ERR! copy_from_user fail!\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int c2c_force_dump(struct link_device *ld, struct io_device *iod)
+{
+ struct shmem_link_device *shmd = to_shmem_link_device(ld);
+ mif_err("+++\n");
+ trigger_forced_cp_crash(shmd);
+ mif_err("---\n");
+ return 0;
+}
+
+static int c2c_dump_start(struct link_device *ld, struct io_device *iod)
+{
+ struct shmem_link_device *shmd = to_shmem_link_device(ld);
+
+ ld->mode = LINK_MODE_ULOAD;
+
+ clear_shmem_map(shmd);
+
+ mif_err("%s: magic = 0x%08X\n", ld->name, SHM_DUMP_MAGIC);
+ set_magic(shmd, SHM_DUMP_MAGIC);
+
+ return 0;
+}
+
+static void c2c_remap_4mb_ipc_region(struct shmem_link_device *shmd)
+{
+ struct shmem_4mb_phys_map *map;
+ struct shmem_ipc_device *dev;
+
+ map = (struct shmem_4mb_phys_map *)shmd->base;
+
+ /* Magic code and access enable fields */
+ shmd->ipc_map.magic = (u32 __iomem *)&map->magic;
+ shmd->ipc_map.access = (u32 __iomem *)&map->access;
+
+ /* FMT */
+ dev = &shmd->ipc_map.dev[IPC_FMT];
+
+ strcpy(dev->name, "FMT");
+ dev->id = IPC_FMT;
+
+ dev->txq.head = (u32 __iomem *)&map->fmt_tx_head;
+ dev->txq.tail = (u32 __iomem *)&map->fmt_tx_tail;
+ dev->txq.buff = (u8 __iomem *)&map->fmt_tx_buff[0];
+ dev->txq.size = SHM_4M_FMT_TX_BUFF_SZ;
+
+ dev->rxq.head = (u32 __iomem *)&map->fmt_rx_head;
+ dev->rxq.tail = (u32 __iomem *)&map->fmt_rx_tail;
+ dev->rxq.buff = (u8 __iomem *)&map->fmt_rx_buff[0];
+ dev->rxq.size = SHM_4M_FMT_RX_BUFF_SZ;
+
+ dev->mask_req_ack = INT_MASK_REQ_ACK_F;
+ dev->mask_res_ack = INT_MASK_RES_ACK_F;
+ dev->mask_send = INT_MASK_SEND_F;
+
+ /* RAW */
+ dev = &shmd->ipc_map.dev[IPC_RAW];
+
+ strcpy(dev->name, "RAW");
+ dev->id = IPC_RAW;
+
+ dev->txq.head = (u32 __iomem *)&map->raw_tx_head;
+ dev->txq.tail = (u32 __iomem *)&map->raw_tx_tail;
+ dev->txq.buff = (u8 __iomem *)&map->raw_tx_buff[0];
+ dev->txq.size = SHM_4M_RAW_TX_BUFF_SZ;
+
+ dev->rxq.head = (u32 __iomem *)&map->raw_rx_head;
+ dev->rxq.tail = (u32 __iomem *)&map->raw_rx_tail;
+ dev->rxq.buff = (u8 __iomem *)&map->raw_rx_buff[0];
+ dev->rxq.size = SHM_4M_RAW_RX_BUFF_SZ;
+
+ dev->mask_req_ack = INT_MASK_REQ_ACK_R;
+ dev->mask_res_ack = INT_MASK_RES_ACK_R;
+ dev->mask_send = INT_MASK_SEND_R;
+
+ /* interrupt ports */
+ shmd->ipc_map.mbx2ap = NULL;
+ shmd->ipc_map.mbx2cp = NULL;
+}
+
+static int c2c_init_ipc_map(struct shmem_link_device *shmd)
+{
+ if (shmd->size >= SHMEM_SIZE_4MB)
+ c2c_remap_4mb_ipc_region(shmd);
+ else
+ return -EINVAL;
+
+ memset(shmd->base, 0, shmd->size);
+
+ shmd->magic = shmd->ipc_map.magic;
+ shmd->access = shmd->ipc_map.access;
+
+ shmd->dev[IPC_FMT] = &shmd->ipc_map.dev[IPC_FMT];
+ shmd->dev[IPC_RAW] = &shmd->ipc_map.dev[IPC_RAW];
+
+ shmd->mbx2ap = shmd->ipc_map.mbx2ap;
+ shmd->mbx2cp = shmd->ipc_map.mbx2cp;
+
+ return 0;
+}
+static int c2c_init_communication(struct link_device *ld, struct io_device *iod)
+{
+ struct shmem_link_device *shmd = to_shmem_link_device(ld);
+ struct io_device *check_iod;
+
+ if (iod->format == IPC_BOOT)
+ return 0;
+
+ /* send 0xC2 */
+ switch(iod->format) {
+ case IPC_FMT:
+ check_iod = link_get_iod_with_format(ld, IPC_RFS);
+ if (check_iod ? atomic_read(&check_iod->opened) : true) {
+ mif_err("%s: Send 0xC2 (INIT_END)\n", ld->name);
+ send_int2cp(shmd, INT_CMD(INT_CMD_INIT_END));
+ } else
+ mif_err("%s defined but not opened\n", check_iod->name);
+ break;
+ case IPC_RFS:
+ check_iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (check_iod && atomic_read(&check_iod->opened)) {
+ mif_err("%s: Send 0xC2 (INIT_END)\n", ld->name);
+ send_int2cp(shmd, INT_CMD(INT_CMD_INIT_END));
+ } else
+ mif_err("not opened\n");
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+#if 0
+static void c2c_link_terminate(struct link_device *ld, struct io_device *iod)
+{
+ if (iod->format == IPC_FMT && ld->mode == LINK_MODE_IPC) {
+ if (!atomic_read(&iod->opened)) {
+ ld->mode = LINK_MODE_OFFLINE;
+ mif_err("%s: %s: link mode changed: IPC -> OFFLINE\n",
+ iod->name, ld->name);
+ }
+ }
+
+ return;
+}
+#endif
+
struct link_device *c2c_create_link_device(struct platform_device *pdev)
{
- struct c2c_link_device *dpld;
+ struct modem_data *modem;
+ struct shmem_link_device *shmd;
struct link_device *ld;
- struct modem_data *pdata;
+ int err;
+ int i;
+ u32 phys_base;
+ u32 offset;
+ u32 size;
+ int irq;
+ unsigned long irq_flags;
+ char name[MIF_MAX_NAME_LEN];
- pdata = pdev->dev.platform_data;
+ /*
+ ** Get the modem (platform) data
+ */
+ modem = (struct modem_data *)pdev->dev.platform_data;
+ if (!modem) {
+ mif_err("ERR! modem == NULL\n");
+ return NULL;
+ }
+ mif_err("%s: %s\n", modem->link_name, modem->name);
- dpld = kzalloc(sizeof(struct c2c_link_device), GFP_KERNEL);
- if (!dpld) {
- mif_err("dpld == NULL\n");
+ if (modem->ipc_version < SIPC_VER_50) {
+ mif_err("%s: %s: ERR! IPC version %d < SIPC_VER_50\n",
+ modem->link_name, modem->name, modem->ipc_version);
return NULL;
}
- wake_lock_init(&dpld->c2c_wake_lock, WAKE_LOCK_SUSPEND, "c2c_wakelock");
- wake_lock(&dpld->c2c_wake_lock);
+ /*
+ ** Alloc an instance of shmem_link_device structure
+ */
+ shmd = kzalloc(sizeof(struct shmem_link_device), GFP_KERNEL);
+ if (!shmd) {
+ mif_err("%s: ERR! shmd kzalloc fail\n", modem->link_name);
+ goto error;
+ }
+ ld = &shmd->ld;
+
+ /*
+ ** Retrieve modem data and SHMEM control data from the modem data
+ */
+ ld->mdm_data = modem;
+ ld->name = modem->link_name;
+ ld->aligned = 1;
+ ld->ipc_version = modem->ipc_version;
+ ld->max_ipc_dev = MAX_SIPC5_DEV;
+
+ /*
+ ** Set attributes as a link device
+ */
+ ld->init_comm = c2c_init_communication;
+#if 0
+ ld->terminate_comm = c2c_link_terminate;
+#endif
+ ld->send = c2c_send;
+ ld->dload_start = c2c_dload_start;
+ ld->firm_update = c2c_set_dload_info;
+ ld->force_dump = c2c_force_dump;
+ ld->dump_start = c2c_dump_start;
+
+ INIT_LIST_HEAD(&ld->list);
- ld = &dpld->ld;
- dpld->pdata = pdata;
+ skb_queue_head_init(&ld->sk_fmt_tx_q);
+ skb_queue_head_init(&ld->sk_raw_tx_q);
+ ld->skb_txq[IPC_FMT] = &ld->sk_fmt_tx_q;
+ ld->skb_txq[IPC_RAW] = &ld->sk_raw_tx_q;
- ld->name = "c2c";
+ skb_queue_head_init(&ld->sk_fmt_rx_q);
+ skb_queue_head_init(&ld->sk_raw_rx_q);
+ ld->skb_rxq[IPC_FMT] = &ld->sk_fmt_rx_q;
+ ld->skb_rxq[IPC_RAW] = &ld->sk_raw_rx_q;
- mif_info("%s is created!!!\n", dpld->ld.name);
+ init_completion(&ld->init_cmpl);
+
+ /*
+ ** Retrieve SHMEM resource
+ */
+ if (modem->link_types & LINKTYPE(LINKDEV_C2C)) {
+ shmd->type = C2C_SHMEM;
+ mif_debug("%s: shmd->type = C2C_SHMEM\n", ld->name);
+ } else if (modem->link_types & LINKTYPE(LINKDEV_SHMEM)) {
+ shmd->type = REAL_SHMEM;
+ mif_debug("%s: shmd->type = REAL_SHMEM\n", ld->name);
+ } else {
+ mif_err("%s: ERR! invalid type\n", ld->name);
+ goto error;
+ }
+
+ phys_base = c2c_get_phys_base();
+ offset = c2c_get_sh_rgn_offset();
+ size = c2c_get_sh_rgn_size();
+ mif_debug("%s: phys_base:0x%08X offset:0x%08X size:%d\n",
+ ld->name, phys_base, offset, size);
+
+ shmd->start = phys_base + offset;
+ shmd->size = size;
+ shmd->base = c2c_request_sh_region(shmd->start, shmd->size);
+ if (!shmd->base) {
+ mif_err("%s: ERR! c2c_request_sh_region fail\n", ld->name);
+ goto error;
+ }
+
+ mif_debug("%s: phys_addr:0x%08X virt_addr:0x%08X size:%d\n",
+ ld->name, shmd->start, (int)shmd->base, shmd->size);
+
+ /*
+ ** Initialize SHMEM maps (physical map -> logical map)
+ */
+ err = c2c_init_ipc_map(shmd);
+ if (err < 0) {
+ mif_err("%s: ERR! c2c_init_ipc_map fail (err %d)\n",
+ ld->name, err);
+ goto error;
+ }
+
+ /*
+ ** Initialize locks, completions, and bottom halves
+ */
+ sprintf(shmd->wlock_name, "%s_wlock", ld->name);
+ wake_lock_init(&shmd->wlock, WAKE_LOCK_SUSPEND, shmd->wlock_name);
+
+ sprintf(shmd->ap_wlock_name, "%s_ap_wlock", ld->name);
+ wake_lock_init(&shmd->ap_wlock, WAKE_LOCK_SUSPEND, shmd->ap_wlock_name);
+
+ sprintf(shmd->cp_wlock_name, "%s_cp_wlock", ld->name);
+ wake_lock_init(&shmd->cp_wlock, WAKE_LOCK_SUSPEND, shmd->cp_wlock_name);
+
+ init_completion(&shmd->udl_cmpl);
+ for (i = 0; i < MAX_SIPC5_DEV; i++)
+ init_completion(&shmd->req_ack_cmpl[i]);
+
+ tasklet_init(&shmd->rx_tsk, msg_rx_task, (unsigned long)shmd);
+ INIT_DELAYED_WORK(&shmd->ipc_rx_dwork, ipc_rx_work);
+ INIT_DELAYED_WORK(&shmd->udl_rx_dwork, udl_rx_work);
+
+ for (i = 0; i < MAX_SIPC5_DEV; i++) {
+ spin_lock_init(&shmd->tx_lock[i]);
+ atomic_set(&shmd->res_required[i], 0);
+ }
+
+ ld->tx_wq = create_singlethread_workqueue("shmem_tx_wq");
+ if (!ld->tx_wq) {
+ mif_err("%s: ERR! fail to create tx_wq\n", ld->name);
+ goto error;
+ }
+ INIT_DELAYED_WORK(&ld->fmt_tx_dwork, fmt_tx_work);
+ INIT_DELAYED_WORK(&ld->raw_tx_dwork, raw_tx_work);
+ ld->tx_dwork[IPC_FMT] = &ld->fmt_tx_dwork;
+ ld->tx_dwork[IPC_RAW] = &ld->raw_tx_dwork;
+
+ spin_lock_init(&shmd->stat_list.lock);
+ spin_lock_init(&shmd->trace_list.lock);
+#ifdef DEBUG_MODEM_IF
+ INIT_DELAYED_WORK(&shmd->dump_dwork, mem_dump_work);
+#endif
+
+ INIT_DELAYED_WORK(&shmd->cp_sleep_dwork, release_cp_wakeup);
+ INIT_DELAYED_WORK(&shmd->link_off_dwork, release_ap_status);
+ spin_lock_init(&shmd->pm_lock);
+
+ /*
+ ** Retrieve SHMEM IRQ GPIO#, IRQ#, and IRQ flags
+ */
+ shmd->gpio_pda_active = modem->gpio_pda_active;
+ mif_err("PDA_ACTIVE gpio# = %d (value %d)\n",
+ shmd->gpio_pda_active, gpio_get_value(shmd->gpio_pda_active));
+
+ shmd->gpio_ap_status = modem->gpio_ap_status;
+ shmd->gpio_ap_wakeup = modem->gpio_ap_wakeup;
+ shmd->irq_ap_wakeup = modem->irq_ap_wakeup;
+ if (!shmd->irq_ap_wakeup) {
+ mif_err("ERR! no irq_ap_wakeup\n");
+ goto error;
+ }
+ mif_debug("CP2AP_WAKEUP IRQ# = %d\n", shmd->irq_ap_wakeup);
+
+ shmd->gpio_cp_wakeup = modem->gpio_cp_wakeup;
+ shmd->gpio_cp_status = modem->gpio_cp_status;
+ shmd->irq_cp_status = modem->irq_cp_status;
+ if (!shmd->irq_cp_status) {
+ mif_err("ERR! no irq_cp_status\n");
+ goto error;
+ }
+ mif_debug("CP2AP_STATUS IRQ# = %d\n", shmd->irq_cp_status);
+
+ c2c_assign_gpio_ap_wakeup(shmd->gpio_ap_wakeup);
+ c2c_assign_gpio_ap_status(shmd->gpio_ap_status);
+ c2c_assign_gpio_cp_wakeup(shmd->gpio_cp_wakeup);
+ c2c_assign_gpio_cp_status(shmd->gpio_cp_status);
+
+ gpio_set_value(shmd->gpio_pda_active, 1);
+ gpio_set_value(shmd->gpio_ap_status, 1);
+
+ /*
+ ** Register interrupt handlers
+ */
+ err = c2c_register_handler(c2c_irq_handler, shmd);
+ if (err) {
+ mif_err("%s: ERR! c2c_register_handler fail (err %d)\n",
+ ld->name, err);
+ goto error;
+ }
+
+ snprintf(name, MIF_MAX_NAME_LEN, "%s_ap_wakeup", ld->name);
+ irq = shmd->irq_ap_wakeup;
+ irq_flags = (IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH);
+ err = mif_register_isr(irq, ap_wakeup_handler, irq_flags, name, shmd);
+ if (err)
+ goto error;
+
+ snprintf(name, MIF_MAX_NAME_LEN, "%s_cp_status", ld->name);
+ irq = shmd->irq_cp_status;
+ irq_flags = (IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH);
+ err = mif_register_isr(irq, cp_status_handler, irq_flags, name, shmd);
+ if (err)
+ goto error;
return ld;
+
+error:
+ mif_err("xxx\n");
+ kfree(shmd);
+ return NULL;
}
+
diff --git a/drivers/misc/modem_if/modem_link_device_c2c.h b/drivers/misc/modem_if/modem_link_device_c2c.h
index 7ec9aa6..9dba90b 100644
--- a/drivers/misc/modem_if/modem_link_device_c2c.h
+++ b/drivers/misc/modem_if/modem_link_device_c2c.h
@@ -1,5 +1,4 @@
/*
- * Copyright (C) 2010 Google, Inc.
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -8,209 +7,18 @@
*
* 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
-#include <linux/wakelock.h>
#ifndef __MODEM_LINK_DEVICE_C2C_H__
#define __MODEM_LINK_DEVICE_C2C_H__
-#define DPRAM_ERR_MSG_LEN 128
-#define DPRAM_ERR_DEVICE "c2cerr"
+#include <mach/c2c.h>
+#include "modem_link_device_shmem.h"
-#define MAX_IDX 2
-
-#define DPRAM_BASE_PTR 0x4000000
-
-#define DPRAM_START_ADDRESS 0
-#define DPRAM_MAGIC_CODE_ADDRESS DPRAM_START_ADDRESS
-#define DPRAM_GOTA_MAGIC_CODE_SIZE 0x4
-#define DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS \
- (DPRAM_START_ADDRESS + DPRAM_GOTA_MAGIC_CODE_SIZE)
-#define BSP_DPRAM_BASE_SIZE 0x1ff8
-#define DPRAM_END_OF_ADDRESS (BSP_DPRAM_BASE_SIZE - 1)
-#define DPRAM_INTERRUPT_SIZE 0x2
-#define DPRAM_PDA2PHONE_INTERRUPT_ADDRESS \
- (DPRAM_START_ADDRESS + BSP_DPRAM_BASE_SIZE - DPRAM_INTERRUPT_SIZE*2)
-#define DPRAM_PHONE2PDA_INTERRUPT_ADDRESS \
- (DPRAM_START_ADDRESS + BSP_DPRAM_BASE_SIZE)
-#define DPRAM_BUFFER_SIZE \
- (DPRAM_PHONE2PDA_INTERRUPT_ADDRESS -\
- DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS)
-#define DPRAM_INDEX_SIZE 0x2
-
-#define MAGIC_DMDL 0x4445444C
-#define MAGIC_UMDL 0x4445444D
-
-#define DPRAM_PACKET_DATA_SIZE 0x3f00
-#define DPRAM_PACKET_HEADER_SIZE 0x7
-
-#define INT_GOTA_MASK_VALID 0xA000
-#define INT_DPRAM_DUMP_MASK_VALID 0xA000
-#define MASK_CMD_RECEIVE_READY_NOTIFICATION 0xA100
-#define MASK_CMD_DOWNLOAD_START_REQUEST 0xA200
-#define MASK_CMD_DOWNLOAD_START_RESPONSE 0xA301
-#define MASK_CMD_IMAGE_SEND_REQUEST 0xA400
-#define MASK_CMD_IMAGE_SEND_RESPONSE 0xA500
-#define MASK_CMD_SEND_DONE_REQUEST 0xA600
-#define MASK_CMD_SEND_DONE_RESPONSE 0xA701
-#define MASK_CMD_STATUS_UPDATE_NOTIFICATION 0xA800
-#define MASK_CMD_UPDATE_DONE_NOTIFICATION 0xA900
-#define MASK_CMD_EFS_CLEAR_RESPONSE 0xAB00
-#define MASK_CMD_ALARM_BOOT_OK 0xAC00
-#define MASK_CMD_ALARM_BOOT_FAIL 0xAD00
-
-#define WRITEIMG_HEADER_SIZE 8
-#define WRITEIMG_TAIL_SIZE 4
-#define WRITEIMG_BODY_SIZE \
- (DPRAM_BUFFER_SIZE - WRITEIMG_HEADER_SIZE - WRITEIMG_TAIL_SIZE)
-
-#define DPDN_DEFAULT_WRITE_LEN WRITEIMG_BODY_SIZE
-#define CMD_DL_START_REQ 0x9200
-#define CMD_IMG_SEND_REQ 0x9400
-#define CMD_DL_SEND_DONE_REQ 0x9600
-
-#define CMD_UL_START_REQ 0x9200
-#define CMD_UL_START_READY 0x9400
-#define CMD_UL_SEND_RESP 0x9601
-#define CMD_UL_SEND_DONE_RESP 0x9801
-#define CMD_UL_SEND_REQ 0xA500
-#define CMD_UL_START_RESPONSE 0xA301
-#define CMD_UL_SEND_DONE_REQ 0xA700
-#define CMD_RECEIVE_READY_NOTIFICATION 0xA100
-
-#define MASK_CMD_RESULT_FAIL 0x0002
-#define MASK_CMD_RESULT_SUCCESS 0x0001
-
-#define START_INDEX 0x007F
-#define END_INDEX 0x007E
-
-#define CMD_IMG_SEND_REQ 0x9400
-
-#define CRC_TAB_SIZE 256
-#define CRC_16_L_SEED 0xFFFF
-
-struct c2c_device {
- /* DPRAM memory addresses */
- u16 *in_head_addr;
- u16 *in_tail_addr;
- u8 *in_buff_addr;
- unsigned long in_buff_size;
-
- u16 *out_head_addr;
- u16 *out_tail_addr;
- u8 *out_buff_addr;
- unsigned long out_buff_size;
-
- unsigned long in_head_saved;
- unsigned long in_tail_saved;
- unsigned long out_head_saved;
- unsigned long out_tail_saved;
-
- u16 mask_req_ack;
- u16 mask_res_ack;
- u16 mask_send;
-};
-
-struct memory_region {
- u8 *control;
- u8 *fmt_out;
- u8 *raw_out;
- u8 *fmt_in;
- u8 *raw_in;
- u8 *mbx;
-};
-
-struct UldDataHeader {
- u8 bop;
- u16 total_frame;
- u16 curr_frame;
- u16 len;
-};
-
-struct c2c_link_device {
- struct link_device ld;
-
- struct modem_data *pdata;
-
- /*only c2c*/
- struct wake_lock c2c_wake_lock;
- atomic_t raw_txq_req_ack_rcvd;
- atomic_t fmt_txq_req_ack_rcvd;
- u8 net_stop_flag;
- int phone_sync;
- u8 phone_status;
-
- struct work_struct xmit_work_struct;
-
- struct workqueue_struct *gota_wq;
- struct work_struct gota_cmd_work;
-
- struct c2c_device dev_map[MAX_IDX];
-
- struct wake_lock dumplock;
-
- u8 c2c_read_data[131072];
-
- int c2c_init_cmd_wait_condition;
- wait_queue_head_t c2c_init_cmd_wait_q;
-
- int modem_pif_init_wait_condition;
- wait_queue_head_t modem_pif_init_done_wait_q;
-
- struct completion gota_download_start_complete;
-
- int gota_send_done_cmd_wait_condition;
- wait_queue_head_t gota_send_done_cmd_wait_q;
-
- int gota_update_done_cmd_wait_condition;
- wait_queue_head_t gota_update_done_cmd_wait_q;
-
- int upload_send_req_wait_condition;
- wait_queue_head_t upload_send_req_wait_q;
-
- int upload_send_done_wait_condition;
- wait_queue_head_t upload_send_done_wait_q;
-
- int upload_start_req_wait_condition;
- wait_queue_head_t upload_start_req_wait_q;
-
- int upload_packet_start_condition;
- wait_queue_head_t upload_packet_start_wait_q;
-
- u16 gota_irq_handler_cmd;
-
- u16 c2c_dump_handler_cmd;
-
- int dump_region_number;
-
- unsigned int is_c2c_err ;
-
- int c2c_dump_start;
- int gota_start;
-
- char c2c_err_buf[DPRAM_ERR_MSG_LEN];
-
- struct fasync_struct *c2c_err_async_q;
-
- void (*clear_interrupt)(struct c2c_link_device *);
-
- struct memory_region m_region;
-
- unsigned long fmt_out_buff_size;
- unsigned long raw_out_buff_size;
- unsigned long fmt_in_buff_size;
- unsigned long raw_in_buff_size;
-
- struct delayed_work delayed_tx;
- struct sk_buff *delayed_skb;
- u8 delayed_count;
-};
-
-/* converts from struct link_device* to struct xxx_link_device* */
-#define to_c2c_link_device(linkdev) \
- container_of(linkdev, struct c2c_link_device, ld)
+#define CP_WAKEUP_HOLD_TIME 500 /* 500 ms */
#endif
+
diff --git a/drivers/misc/modem_if/modem_link_device_dpram.c b/drivers/misc/modem_if/modem_link_device_dpram.c
index a650ed9..a87aff2 100644
--- a/drivers/misc/modem_if/modem_link_device_dpram.c
+++ b/drivers/misc/modem_if/modem_link_device_dpram.c
@@ -25,560 +25,385 @@
#include <linux/if_arp.h>
#include <linux/platform_device.h>
#include <linux/kallsyms.h>
-#include <linux/platform_data/modem.h>
+#include <linux/suspend.h>
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+#include "modem.h"
#include "modem_prj.h"
-#include "modem_link_device_dpram.h"
#include "modem_utils.h"
+#include "modem_link_device_dpram.h"
-/*
-** Function prototypes for basic DPRAM operations
-*/
-static inline void clear_intr(struct dpram_link_device *dpld);
-static inline u16 recv_intr(struct dpram_link_device *dpld);
-static inline void send_intr(struct dpram_link_device *dpld, u16 mask);
-
-static inline u16 get_magic(struct dpram_link_device *dpld);
-static inline void set_magic(struct dpram_link_device *dpld, u16 val);
-static inline u16 get_access(struct dpram_link_device *dpld);
-static inline void set_access(struct dpram_link_device *dpld, u16 val);
-
-static inline u32 get_tx_head(struct dpram_link_device *dpld, int id);
-static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id);
-static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in);
-static inline void set_tx_tail(struct dpram_link_device *dpld, int id, u32 out);
-static inline u8 *get_tx_buff(struct dpram_link_device *dpld, int id);
-static inline u32 get_tx_buff_size(struct dpram_link_device *dpld, int id);
-
-static inline u32 get_rx_head(struct dpram_link_device *dpld, int id);
-static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id);
-static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in);
-static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out);
-static inline u8 *get_rx_buff(struct dpram_link_device *dpld, int id);
-static inline u32 get_rx_buff_size(struct dpram_link_device *dpld, int id);
-
-static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id);
-static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id);
-static inline u16 get_mask_send(struct dpram_link_device *dpld, int id);
-
-static inline bool dpram_circ_valid(u32 size, u32 in, u32 out);
-
-static void handle_cp_crash(struct dpram_link_device *dpld);
-static int trigger_force_cp_crash(struct dpram_link_device *dpld);
-static void dpram_dump_memory(struct link_device *ld, char *buff);
-
-/*
-** Functions for debugging
-*/
-static inline void log_dpram_status(struct dpram_link_device *dpld)
-{
- pr_info("mif: %s: {M:0x%X A:%d} {FMT TI:%u TO:%u RI:%u RO:%u} "
- "{RAW TI:%u TO:%u RI:%u RO:%u} {INT:0x%X}\n",
- dpld->ld.mc->name,
- get_magic(dpld), get_access(dpld),
- get_tx_head(dpld, IPC_FMT), get_tx_tail(dpld, IPC_FMT),
- get_rx_head(dpld, IPC_FMT), get_rx_tail(dpld, IPC_FMT),
- get_tx_head(dpld, IPC_RAW), get_tx_tail(dpld, IPC_RAW),
- get_rx_head(dpld, IPC_RAW), get_rx_tail(dpld, IPC_RAW),
- recv_intr(dpld));
-}
-
-static void set_dpram_map(struct dpram_link_device *dpld,
- struct mif_irq_map *map)
-{
- map->magic = get_magic(dpld);
- map->access = get_access(dpld);
-
- map->fmt_tx_in = get_tx_head(dpld, IPC_FMT);
- map->fmt_tx_out = get_tx_tail(dpld, IPC_FMT);
- map->fmt_rx_in = get_rx_head(dpld, IPC_FMT);
- map->fmt_rx_out = get_rx_tail(dpld, IPC_FMT);
- map->raw_tx_in = get_tx_head(dpld, IPC_RAW);
- map->raw_tx_out = get_tx_tail(dpld, IPC_RAW);
- map->raw_rx_in = get_rx_head(dpld, IPC_RAW);
- map->raw_rx_out = get_rx_tail(dpld, IPC_RAW);
-
- map->cp2ap = recv_intr(dpld);
-}
-
-/*
-** RXB (DPRAM RX buffer) functions
-*/
-static struct dpram_rxb *rxbq_create_pool(unsigned size, int count)
-{
- struct dpram_rxb *rxb;
- u8 *buff;
- int i;
-
- rxb = kzalloc(sizeof(struct dpram_rxb) * count, GFP_KERNEL);
- if (!rxb) {
- mif_info("ERR! kzalloc rxb fail\n");
- return NULL;
- }
-
- buff = kzalloc((size * count), GFP_KERNEL|GFP_DMA);
- if (!buff) {
- mif_info("ERR! kzalloc buff fail\n");
- kfree(rxb);
- return NULL;
- }
-
- for (i = 0; i < count; i++) {
- rxb[i].buff = buff;
- rxb[i].size = size;
- buff += size;
- }
-
- return rxb;
-}
-
-static inline unsigned rxbq_get_page_size(unsigned len)
-{
- return ((len + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT;
-}
-
-static inline bool rxbq_empty(struct dpram_rxb_queue *rxbq)
-{
- return (rxbq->in == rxbq->out) ? true : false;
-}
-
-static inline int rxbq_free_size(struct dpram_rxb_queue *rxbq)
-{
- int in = rxbq->in;
- int out = rxbq->out;
- int qsize = rxbq->size;
- return (in < out) ? (out - in - 1) : (qsize + out - in - 1);
-}
+static void trigger_forced_cp_crash(struct dpram_link_device *dpld);
-static inline struct dpram_rxb *rxbq_get_free_rxb(struct dpram_rxb_queue *rxbq)
+/**
+ * set_circ_pointer
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @dir: direction of communication (TX or RX)
+ * @ptr: type of the queue pointer (HEAD or TAIL)
+ * @addr: address of the queue pointer
+ * @val: value to be written to the queue pointer
+ *
+ * Writes a value to a pointer in a circular queue with verification.
+ */
+static inline void set_circ_pointer(struct dpram_link_device *dpld, int id,
+ int dir, int ptr, void __iomem *addr, u16 val)
{
- struct dpram_rxb *rxb = NULL;
+ struct link_device *ld = &dpld->ld;
+ int cnt = 0;
+ u16 saved = 0;
- if (likely(rxbq_free_size(rxbq) > 0)) {
- rxb = &rxbq->rxb[rxbq->in];
- rxbq->in++;
- if (rxbq->in >= rxbq->size)
- rxbq->in -= rxbq->size;
- rxb->data = rxb->buff;
- }
+ iowrite16(val, addr);
- return rxb;
-}
+ while (1) {
+ /* Check the value written to the address */
+ saved = ioread16(addr);
+ if (likely(saved == val))
+ break;
-static inline int rxbq_size(struct dpram_rxb_queue *rxbq)
-{
- int in = rxbq->in;
- int out = rxbq->out;
- int qsize = rxbq->size;
- return (in >= out) ? (in - out) : (qsize - out + in);
-}
+ cnt++;
+ mif_err("%s: ERR! %s_%s.%s saved(%d) != val(%d), count %d\n",
+ ld->name, get_dev_name(id), circ_dir(dir),
+ circ_ptr(ptr), saved, val, cnt);
+ if (cnt >= MAX_RETRY_CNT) {
+ trigger_forced_cp_crash(dpld);
+ break;
+ }
-static inline struct dpram_rxb *rxbq_get_data_rxb(struct dpram_rxb_queue *rxbq)
-{
- struct dpram_rxb *rxb = NULL;
+ udelay(100);
- if (likely(!rxbq_empty(rxbq))) {
- rxb = &rxbq->rxb[rxbq->out];
- rxbq->out++;
- if (rxbq->out >= rxbq->size)
- rxbq->out -= rxbq->size;
+ /* Write the value again */
+ iowrite16(val, addr);
}
-
- return rxb;
-}
-
-static inline u8 *rxb_put(struct dpram_rxb *rxb, unsigned len)
-{
- rxb->len = len;
- return rxb->data;
}
-static inline void rxb_clear(struct dpram_rxb *rxb)
+/**
+ * recv_int2ap
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Returns the value of the CP-to-AP interrupt register in a DPRAM.
+ */
+static inline u16 recv_int2ap(struct dpram_link_device *dpld)
{
- rxb->data = NULL;
- rxb->len = 0;
+ return ioread16(dpld->mbx2ap);
}
-/*
-** DPRAM operations
-*/
-static int dpram_register_isr(unsigned irq, irqreturn_t (*isr)(int, void*),
- unsigned long flag, const char *name,
- struct dpram_link_device *dpld)
+/**
+ * send_int2cp
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @mask: value to be written to the AP-to-CP interrupt register in a DPRAM
+ */
+static inline void send_int2cp(struct dpram_link_device *dpld, u16 mask)
{
- int ret;
+ struct idpram_pm_op *pm_op = dpld->pm_op;
- ret = request_irq(irq, isr, flag, name, dpld);
- if (ret) {
- mif_info("%s: ERR! request_irq fail (err %d)\n", name, ret);
- return ret;
+ if (pm_op && pm_op->int2cp_possible) {
+ if (!pm_op->int2cp_possible(dpld))
+ return;
}
- ret = enable_irq_wake(irq);
- if (ret)
- mif_info("%s: ERR! enable_irq_wake fail (err %d)\n", name, ret);
-
- mif_info("%s (#%d) handler registered\n", name, irq);
-
- return 0;
-}
-
-static inline void clear_intr(struct dpram_link_device *dpld)
-{
- if (likely(dpld->dpctl->clear_intr))
- dpld->dpctl->clear_intr();
+ iowrite16(mask, dpld->mbx2cp);
}
-static inline u16 recv_intr(struct dpram_link_device *dpld)
-{
- if (likely(dpld->dpctl->recv_intr))
- return dpld->dpctl->recv_intr();
- else
- return ioread16(dpld->mbx2ap);
-}
-
-static inline void send_intr(struct dpram_link_device *dpld, u16 mask)
+/**
+ * read_int2cp
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Returns the value of the AP-to-CP interrupt register in a DPRAM.
+ */
+static inline u16 read_int2cp(struct dpram_link_device *dpld)
{
- if (likely(dpld->dpctl->send_intr))
- dpld->dpctl->send_intr(mask);
- else
- iowrite16(mask, dpld->mbx2cp);
+ return ioread16(dpld->mbx2cp);
}
+/**
+ * get_magic
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Returns the value of the "magic code" field in a DPRAM.
+ */
static inline u16 get_magic(struct dpram_link_device *dpld)
{
return ioread16(dpld->magic);
}
+/**
+ * set_magic
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @val: value to be written to the "magic code" field in a DPRAM
+ */
static inline void set_magic(struct dpram_link_device *dpld, u16 val)
{
iowrite16(val, dpld->magic);
}
+/**
+ * get_access
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Returns the value of the "access enable" field in a DPRAM.
+ */
static inline u16 get_access(struct dpram_link_device *dpld)
{
return ioread16(dpld->access);
}
+/**
+ * set_access
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @val: value to be written to the "access enable" field in a DPRAM
+ */
static inline void set_access(struct dpram_link_device *dpld, u16 val)
{
iowrite16(val, dpld->access);
}
-static inline u32 get_tx_head(struct dpram_link_device *dpld, int id)
+/**
+ * get_txq_head
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a head (in) pointer in a TX queue.
+ */
+static inline u32 get_txq_head(struct dpram_link_device *dpld, int id)
{
return ioread16(dpld->dev[id]->txq.head);
}
-static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id)
+/**
+ * get_txq_tail
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a tail (out) pointer in a TX queue.
+ *
+ * It is useless for an AP to read a tail pointer in a TX queue twice to verify
+ * whether or not the value in the pointer is valid, because it can already have
+ * been updated by a CP after the first access from the AP.
+ */
+static inline u32 get_txq_tail(struct dpram_link_device *dpld, int id)
{
return ioread16(dpld->dev[id]->txq.tail);
}
-static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in)
-{
- int cnt = 3;
- u32 val = 0;
-
- iowrite16((u16)in, dpld->dev[id]->txq.head);
-
- do {
- /* Check head value written */
- val = ioread16(dpld->dev[id]->txq.head);
- if (likely(val == in))
- return;
-
- mif_err("ERR: %s txq.head(%d) != in(%d)\n",
- get_dev_name(id), val, in);
- udelay(100);
-
- /* Write head value again */
- iowrite16((u16)in, dpld->dev[id]->txq.head);
- } while (cnt--);
-
- trigger_force_cp_crash(dpld);
-}
-
-static inline void set_tx_tail(struct dpram_link_device *dpld, int id, u32 out)
-{
- int cnt = 3;
- u32 val = 0;
-
- iowrite16((u16)out, dpld->dev[id]->txq.tail);
-
- do {
- /* Check tail value written */
- val = ioread16(dpld->dev[id]->txq.tail);
- if (likely(val == out))
- return;
-
- mif_err("ERR: %s txq.tail(%d) != out(%d)\n",
- get_dev_name(id), val, out);
- udelay(100);
-
- /* Write tail value again */
- iowrite16((u16)out, dpld->dev[id]->txq.tail);
- } while (cnt--);
-
- trigger_force_cp_crash(dpld);
-}
-
-static inline u8 *get_tx_buff(struct dpram_link_device *dpld, int id)
+/**
+ * get_txq_buff
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the start address of the buffer in a TXQ.
+ */
+static inline u8 *get_txq_buff(struct dpram_link_device *dpld, int id)
{
return dpld->dev[id]->txq.buff;
}
-static inline u32 get_tx_buff_size(struct dpram_link_device *dpld, int id)
+/**
+ * get_txq_buff_size
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the size of the buffer in a TXQ.
+ */
+static inline u32 get_txq_buff_size(struct dpram_link_device *dpld, int id)
{
return dpld->dev[id]->txq.size;
}
-static inline u32 get_rx_head(struct dpram_link_device *dpld, int id)
+/**
+ * get_rxq_head
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a head (in) pointer in an RX queue.
+ *
+ * It is useless for an AP to read a head pointer in an RX queue twice to verify
+ * whether or not the value in the pointer is valid, because it can already have
+ * been updated by a CP after the first access from the AP.
+ */
+static inline u32 get_rxq_head(struct dpram_link_device *dpld, int id)
{
return ioread16(dpld->dev[id]->rxq.head);
}
-static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id)
+/**
+ * get_rxq_tail
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a tail (in) pointer in an RX queue.
+ */
+static inline u32 get_rxq_tail(struct dpram_link_device *dpld, int id)
{
return ioread16(dpld->dev[id]->rxq.tail);
}
-static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in)
-{
- int cnt = 3;
- u32 val = 0;
-
- iowrite16((u16)in, dpld->dev[id]->rxq.head);
-
- do {
- /* Check head value written */
- val = ioread16(dpld->dev[id]->rxq.head);
- if (val == in)
- return;
-
- mif_err("ERR: %s rxq.head(%d) != in(%d)\n",
- get_dev_name(id), val, in);
- udelay(100);
-
- /* Write head value again */
- iowrite16((u16)in, dpld->dev[id]->rxq.head);
- } while (cnt--);
-
- trigger_force_cp_crash(dpld);
-}
-
-static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out)
-{
- int cnt = 3;
- u32 val = 0;
-
- iowrite16((u16)out, dpld->dev[id]->rxq.tail);
-
- do {
- /* Check tail value written */
- val = ioread16(dpld->dev[id]->rxq.tail);
- if (val == out)
- return;
-
- mif_err("ERR: %s rxq.tail(%d) != out(%d)\n",
- get_dev_name(id), val, out);
- udelay(100);
-
- /* Write tail value again */
- iowrite16((u16)out, dpld->dev[id]->rxq.tail);
- } while (cnt--);
-
- trigger_force_cp_crash(dpld);
-}
-
-static inline u8 *get_rx_buff(struct dpram_link_device *dpld, int id)
+/**
+ * get_rxq_buff
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the start address of the buffer in an RXQ.
+ */
+static inline u8 *get_rxq_buff(struct dpram_link_device *dpld, int id)
{
return dpld->dev[id]->rxq.buff;
}
-static inline u32 get_rx_buff_size(struct dpram_link_device *dpld, int id)
+/**
+ * get_rxq_buff_size
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the size of the buffer in an RXQ.
+ */
+static inline u32 get_rxq_buff_size(struct dpram_link_device *dpld, int id)
{
return dpld->dev[id]->rxq.size;
}
-static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id)
+/**
+ * set_txq_head
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @in: value to be written to the head pointer in a TXQ
+ */
+static inline void set_txq_head(struct dpram_link_device *dpld, int id, u32 in)
{
- return dpld->dev[id]->mask_req_ack;
+ set_circ_pointer(dpld, id, TX, HEAD, dpld->dev[id]->txq.head, in);
}
-static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id)
+/**
+ * set_txq_tail
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @out: value to be written to the tail pointer in a TXQ
+ */
+static inline void set_txq_tail(struct dpram_link_device *dpld, int id, u32 out)
{
- return dpld->dev[id]->mask_res_ack;
+ set_circ_pointer(dpld, id, TX, TAIL, dpld->dev[id]->txq.tail, out);
}
-static inline u16 get_mask_send(struct dpram_link_device *dpld, int id)
+/**
+ * set_rxq_head
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @in: value to be written to the head pointer in an RXQ
+ */
+static inline void set_rxq_head(struct dpram_link_device *dpld, int id, u32 in)
{
- return dpld->dev[id]->mask_send;
+ set_circ_pointer(dpld, id, RX, HEAD, dpld->dev[id]->rxq.head, in);
}
-static inline bool dpram_circ_valid(u32 size, u32 in, u32 out)
+/**
+ * set_rxq_tail
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @out: value to be written to the tail pointer in an RXQ
+ */
+static inline void set_rxq_tail(struct dpram_link_device *dpld, int id, u32 out)
{
- if (in >= size)
- return false;
-
- if (out >= size)
- return false;
-
- return true;
+ set_circ_pointer(dpld, id, RX, TAIL, dpld->dev[id]->rxq.tail, out);
}
-/* Get free space in the TXQ as well as in & out pointers */
-static inline int dpram_get_txq_space(struct dpram_link_device *dpld, int dev,
- u32 qsize, u32 *in, u32 *out)
-{
- struct link_device *ld = &dpld->ld;
- int cnt = 3;
- u32 head;
- u32 tail;
- int space;
-
- do {
- head = get_tx_head(dpld, dev);
- tail = get_tx_tail(dpld, dev);
-
- space = (head < tail) ? (tail - head - 1) :
- (qsize + tail - head - 1);
- mif_debug("%s: %s_TXQ qsize[%u] in[%u] out[%u] space[%u]\n",
- ld->name, get_dev_name(dev), qsize, head, tail, space);
-
- if (dpram_circ_valid(qsize, head, tail)) {
- *in = head;
- *out = tail;
- return space;
- }
-
- mif_info("%s: CAUTION! <%pf> "
- "%s_TXQ invalid (size:%d in:%d out:%d)\n",
- ld->name, __builtin_return_address(0),
- get_dev_name(dev), qsize, head, tail);
-
- udelay(100);
- } while (cnt--);
-
- *in = 0;
- *out = 0;
- return -EINVAL;
-}
-
-static void dpram_reset_tx_circ(struct dpram_link_device *dpld, int dev)
+/**
+ * get_mask_req_ack
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the REQ_ACK mask value for the IPC device.
+ */
+static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id)
{
- set_tx_head(dpld, dev, 0);
- set_tx_tail(dpld, dev, 0);
- if (dev == IPC_FMT)
- trigger_force_cp_crash(dpld);
+ return dpld->dev[id]->mask_req_ack;
}
-/* Get data size in the RXQ as well as in & out pointers */
-static inline int dpram_get_rxq_rcvd(struct dpram_link_device *dpld, int dev,
- u32 qsize, u32 *in, u32 *out)
+/**
+ * get_mask_res_ack
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the RES_ACK mask value for the IPC device.
+ */
+static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id)
{
- struct link_device *ld = &dpld->ld;
- int cnt = 3;
- u32 head;
- u32 tail;
- u32 rcvd;
-
- do {
- head = get_rx_head(dpld, dev);
- tail = get_rx_tail(dpld, dev);
- if (head == tail) {
- *in = head;
- *out = tail;
- return 0;
- }
-
- rcvd = (head > tail) ? (head - tail) : (qsize - tail + head);
- mif_debug("%s: %s_RXQ qsize[%u] in[%u] out[%u] rcvd[%u]\n",
- ld->name, get_dev_name(dev), qsize, head, tail, rcvd);
-
- if (dpram_circ_valid(qsize, head, tail)) {
- *in = head;
- *out = tail;
- return rcvd;
- }
-
- mif_info("%s: CAUTION! <%pf> "
- "%s_RXQ invalid (size:%d in:%d out:%d)\n",
- ld->name, __builtin_return_address(0),
- get_dev_name(dev), qsize, head, tail);
-
- udelay(100);
- } while (cnt--);
-
- *in = 0;
- *out = 0;
- return -EINVAL;
+ return dpld->dev[id]->mask_res_ack;
}
-static void dpram_reset_rx_circ(struct dpram_link_device *dpld, int dev)
+/**
+ * get_mask_send
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the SEND mask value for the IPC device.
+ */
+static inline u16 get_mask_send(struct dpram_link_device *dpld, int id)
{
- set_rx_head(dpld, dev, 0);
- set_rx_tail(dpld, dev, 0);
- if (dev == IPC_FMT)
- trigger_force_cp_crash(dpld);
+ return dpld->dev[id]->mask_send;
}
-/*
-** CAUTION : dpram_allow_sleep() MUST be invoked after dpram_wake_up() success
-*/
-static int dpram_wake_up(struct dpram_link_device *dpld)
+/**
+ * reset_txq_circ
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Empties a TXQ by resetting the head (in) pointer with the value in the tail
+ * (out) pointer.
+ */
+static inline void reset_txq_circ(struct dpram_link_device *dpld, int dev)
{
struct link_device *ld = &dpld->ld;
+ u32 head = get_txq_head(dpld, dev);
+ u32 tail = get_txq_tail(dpld, dev);
- if (!dpld->dpctl->wakeup)
- return 0;
-
- if (dpld->dpctl->wakeup() < 0) {
- mif_err("%s: ERR! <%pf> DPRAM wakeup fail once\n",
- ld->name, __builtin_return_address(0));
-
- if (dpld->dpctl->sleep)
- dpld->dpctl->sleep();
+ mif_info("%s: %s_TXQ: HEAD[%u] <== TAIL[%u]\n",
+ ld->name, get_dev_name(dev), head, tail);
- udelay(10);
-
- if (dpld->dpctl->wakeup() < 0) {
- mif_err("%s: ERR! <%pf> DPRAM wakeup fail twice\n",
- ld->name, __builtin_return_address(0));
- return -EACCES;
- }
- }
-
- atomic_inc(&dpld->accessing);
- return 0;
+ set_txq_head(dpld, dev, tail);
}
-static void dpram_allow_sleep(struct dpram_link_device *dpld)
+/**
+ * reset_rxq_circ
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Empties an RXQ by resetting the tail (out) pointer with the value in the head
+ * (in) pointer.
+ */
+static inline void reset_rxq_circ(struct dpram_link_device *dpld, int dev)
{
struct link_device *ld = &dpld->ld;
+ u32 head = get_rxq_head(dpld, dev);
+ u32 tail = get_rxq_tail(dpld, dev);
- if (!dpld->dpctl->sleep)
- return;
+ mif_info("%s: %s_RXQ: TAIL[%u] <== HEAD[%u]\n",
+ ld->name, get_dev_name(dev), tail, head);
- if (atomic_dec_return(&dpld->accessing) <= 0) {
- dpld->dpctl->sleep();
- atomic_set(&dpld->accessing, 0);
- mif_debug("%s: DPRAM sleep possible\n", ld->name);
- }
+ set_rxq_tail(dpld, dev, head);
}
-static int dpram_check_access(struct dpram_link_device *dpld)
+/**
+ * check_magic_access
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Returns 0 if the "magic code" and "access enable" values are valid, otherwise
+ * returns -EACCES.
+ */
+static int check_magic_access(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
int i;
u16 magic = get_magic(dpld);
u16 access = get_access(dpld);
+ /* Returns 0 if the "magic code" and "access enable" are valid */
if (likely(magic == DPRAM_MAGIC_CODE && access == 1))
return 0;
+ /* Retry up to 100 times with 100 us delay per each retry */
for (i = 1; i <= 100; i++) {
- mif_info("%s: ERR! magic:%X access:%X -> retry:%d\n",
+ mif_info("%s: magic:%X access:%X -> retry:%d\n",
ld->name, magic, access, i);
udelay(100);
@@ -592,357 +417,313 @@ static int dpram_check_access(struct dpram_link_device *dpld)
return -EACCES;
}
-static bool dpram_ipc_active(struct dpram_link_device *dpld)
+/**
+ * ipc_active
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Returns whether or not IPC via the dpram_link_device instance is possible.
+ */
+static bool ipc_active(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
/* Check DPRAM mode */
if (ld->mode != LINK_MODE_IPC) {
- mif_info("%s: <%pf> ld->mode != LINK_MODE_IPC\n",
- ld->name, __builtin_return_address(0));
+ mif_err("%s: <called by %pf> ERR! ld->mode != LINK_MODE_IPC\n",
+ ld->name, CALLER);
return false;
}
- if (dpram_check_access(dpld) < 0) {
- mif_info("%s: ERR! <%pf> dpram_check_access fail\n",
- ld->name, __builtin_return_address(0));
+ /* Check "magic code" and "access enable" values */
+ if (check_magic_access(dpld) < 0) {
+ mif_err("%s: <called by %pf> ERR! check_magic_access fail\n",
+ ld->name, CALLER);
return false;
}
return true;
}
-static void dpram_ipc_write(struct dpram_link_device *dpld, int dev,
- u32 qsize, u32 in, u32 out, struct sk_buff *skb)
-{
- struct link_device *ld = &dpld->ld;
- u8 __iomem *buff = get_tx_buff(dpld, dev);
- u8 *src = skb->data;
- u32 len = skb->len;
- u32 inp;
- struct mif_irq_map map;
-
- if (in < out) {
- /* +++++++++ in ---------- out ++++++++++ */
- memcpy((buff + in), src, len);
- } else {
- /* ------ out +++++++++++ in ------------ */
- u32 space = qsize - in;
-
- /* 1) in -> buffer end */
- memcpy((buff + in), src, ((len > space) ? space : len));
-
- /* 2) buffer start -> out */
- if (len > space)
- memcpy(buff, (src + space), (len - space));
- }
-
- /* update new in pointer */
- inp = in + len;
- if (inp >= qsize)
- inp -= qsize;
- set_tx_head(dpld, dev, inp);
+/**
+ * get_dpram_status
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dir: direction of communication (TX or RX)
+ * @stat: pointer to an instance of mem_status structure
+ *
+ * Takes a snapshot of the current status of a DPRAM.
+ */
+static void get_dpram_status(struct dpram_link_device *dpld,
+ enum circ_dir_type dir, struct mem_status *stat)
+{
+#ifdef DEBUG_MODEM_IF
+ getnstimeofday(&stat->ts);
+#endif
+
+ stat->dir = dir;
+ stat->magic = get_magic(dpld);
+ stat->access = get_access(dpld);
+ stat->head[IPC_FMT][TX] = get_txq_head(dpld, IPC_FMT);
+ stat->tail[IPC_FMT][TX] = get_txq_tail(dpld, IPC_FMT);
+ stat->head[IPC_FMT][RX] = get_rxq_head(dpld, IPC_FMT);
+ stat->tail[IPC_FMT][RX] = get_rxq_tail(dpld, IPC_FMT);
+ stat->head[IPC_RAW][TX] = get_txq_head(dpld, IPC_RAW);
+ stat->tail[IPC_RAW][TX] = get_txq_tail(dpld, IPC_RAW);
+ stat->head[IPC_RAW][RX] = get_rxq_head(dpld, IPC_RAW);
+ stat->tail[IPC_RAW][RX] = get_rxq_tail(dpld, IPC_RAW);
+ stat->int2ap = recv_int2ap(dpld);
+ stat->int2cp = read_int2cp(dpld);
+}
+
+#if 0
+/**
+ * save_ipc_trace_work
+ * @work: pointer to an instance of work_struct structure
+ *
+ * Performs actual file operation for saving RX IPC trace.
+ */
+static void save_ipc_trace_work(struct work_struct *work)
+{
+ struct dpram_link_device *dpld;
+ struct link_device *ld;
+ struct trace_data_queue *trq;
+ struct trace_data *trd;
+ struct circ_status *stat;
+ struct file *fp;
+ struct timespec *ts;
+ int dev;
+ u8 *dump;
+ int rcvd;
+ u8 *buff;
+ char *path;
+ struct utc_time utc;
- if (dev == IPC_FMT) {
- set_dpram_map(dpld, &map);
- mif_irq_log(ld->mc->msd, map, "ipc_write", sizeof("ipc_write"));
- mif_ipc_log(MIF_IPC_AP2CP, ld->mc->msd, skb->data, skb->len);
- }
+ dpld = container_of(work, struct dpram_link_device, trace_dwork.work);
+ ld = &dpld->ld;
+ trq = &dpld->trace_list;
+ path = dpld->trace_path;
- if (ld->aligned && memcmp16_to_io((buff + in), src, 4)) {
- mif_err("%s: memcmp16_to_io fail\n", ld->name);
- trigger_force_cp_crash(dpld);
+ buff = kzalloc(dpld->size << 3, GFP_KERNEL);
+ if (!buff) {
+ while (1) {
+ trd = trq_get_data_slot(trq);
+ if (!trd)
+ break;
+
+ ts = &trd->ts;
+ dev = trd->dev;
+ stat = &trd->circ_stat;
+ dump = trd->data;
+ rcvd = trd->size;
+ print_ipc_trace(ld, dev, stat, ts, dump, rcvd);
+
+ kfree(dump);
+ }
+ return;
}
-}
-
-static int dpram_try_ipc_tx(struct dpram_link_device *dpld, int dev)
-{
- struct link_device *ld = &dpld->ld;
- struct sk_buff_head *txq = ld->skb_txq[dev];
- struct sk_buff *skb;
- unsigned long int flags;
- u32 qsize = get_tx_buff_size(dpld, dev);
- u32 in;
- u32 out;
- int space;
- int copied = 0;
-
- spin_lock_irqsave(&dpld->tx_lock[dev], flags);
while (1) {
- space = dpram_get_txq_space(dpld, dev, qsize, &in, &out);
- if (unlikely(space < 0)) {
- spin_unlock_irqrestore(&dpld->tx_lock[dev], flags);
- dpram_reset_tx_circ(dpld, dev);
- return space;
- }
-
- skb = skb_dequeue(txq);
- if (unlikely(!skb))
+ trd = trq_get_data_slot(trq);
+ if (!trd)
break;
- if (unlikely(space < skb->len)) {
- atomic_set(&dpld->res_required[dev], 1);
- skb_queue_head(txq, skb);
- spin_unlock_irqrestore(&dpld->tx_lock[dev], flags);
- mif_info("%s: %s "
- "qsize[%u] in[%u] out[%u] free[%u] < len[%u]\n",
- ld->name, get_dev_name(dev),
- qsize, in, out, space, skb->len);
- return -ENOSPC;
+ ts = &trd->ts;
+ dev = trd->dev;
+ stat = &trd->circ_stat;
+ dump = trd->data;
+ rcvd = trd->size;
+
+ ts2utc(ts, &utc);
+ snprintf(path, MIF_MAX_PATH_LEN,
+ "%s/%s_%s_%d%02d%02d-%02d%02d%02d.lst",
+ MIF_LOG_DIR, ld->name, get_dev_name(dev),
+ utc.year, utc.mon, utc.day, utc.hour, utc.min, utc.sec);
+
+ fp = mif_open_file(path);
+ if (fp) {
+ int len;
+
+ snprintf(buff, MIF_MAX_PATH_LEN,
+ "[%d-%02d-%02d %02d:%02d:%02d.%03d] "
+ "%s %s_RXQ {IN:%u OUT:%u LEN:%d}\n",
+ utc.year, utc.mon, utc.day, utc.hour, utc.min,
+ utc.sec, utc.msec, ld->name, get_dev_name(dev),
+ stat->in, stat->out, stat->size);
+ len = strlen(buff);
+ mif_dump2format4(dump, rcvd, (buff + len), NULL);
+ strcat(buff, "\n");
+ len = strlen(buff);
+
+ mif_save_file(fp, buff, len);
+
+ memset(buff, 0, len);
+ mif_close_file(fp);
+ } else {
+ mif_err("%s: %s open fail\n", ld->name, path);
+ print_ipc_trace(ld, dev, stat, ts, dump, rcvd);
}
- /* TX if there is enough room in the queue */
- dpram_ipc_write(dpld, dev, qsize, in, out, skb);
- copied += skb->len;
- dev_kfree_skb_any(skb);
+ kfree(dump);
}
- spin_unlock_irqrestore(&dpld->tx_lock[dev], flags);
-
- return copied;
-}
-
-static void dpram_ipc_rx_task(unsigned long data)
-{
- struct dpram_link_device *dpld = (struct dpram_link_device *)data;
- struct link_device *ld = &dpld->ld;
- struct io_device *iod;
- struct dpram_rxb *rxb;
- unsigned qlen;
- int i;
-
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- iod = dpld->iod[i];
- qlen = rxbq_size(&dpld->rxbq[i]);
- while (qlen > 0) {
- rxb = rxbq_get_data_rxb(&dpld->rxbq[i]);
- iod->recv(iod, ld, rxb->data, rxb->len);
- rxb_clear(rxb);
- qlen--;
- }
- }
+ kfree(buff);
}
+#endif
-static void dpram_ipc_read(struct dpram_link_device *dpld, int dev, u8 *dst,
- u8 __iomem *src, u32 out, u32 len, u32 qsize)
+/**
+ * set_dpram_map
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @map: pointer to an instance of mif_irq_map structure
+ *
+ * Sets variables in an mif_irq_map instance as current DPRAM status for IPC
+ * logging.
+ */
+static void set_dpram_map(struct dpram_link_device *dpld,
+ struct mif_irq_map *map)
{
- if ((out + len) <= qsize) {
- /* ----- (out) (in) ----- */
- /* ----- 7f 00 00 7e ----- */
- memcpy(dst, (src + out), len);
- } else {
- /* (in) ----------- (out) */
- /* 00 7e ----------- 7f 00 */
- unsigned len1 = qsize - out;
+ map->magic = get_magic(dpld);
+ map->access = get_access(dpld);
- /* 1) out -> buffer end */
- memcpy(dst, (src + out), len1);
+ map->fmt_tx_in = get_txq_head(dpld, IPC_FMT);
+ map->fmt_tx_out = get_txq_tail(dpld, IPC_FMT);
+ map->fmt_rx_in = get_rxq_head(dpld, IPC_FMT);
+ map->fmt_rx_out = get_rxq_tail(dpld, IPC_FMT);
+ map->raw_tx_in = get_txq_head(dpld, IPC_RAW);
+ map->raw_tx_out = get_txq_tail(dpld, IPC_RAW);
+ map->raw_rx_in = get_rxq_head(dpld, IPC_RAW);
+ map->raw_rx_out = get_rxq_tail(dpld, IPC_RAW);
- /* 2) buffer start -> in */
- dst += len1;
- memcpy(dst, src, (len - len1));
- }
+ map->cp2ap = recv_int2ap(dpld);
}
-/*
- ret < 0 : error
- ret == 0 : no data
- ret > 0 : valid data
-*/
-static int dpram_ipc_recv_data_with_rxb(struct dpram_link_device *dpld, int dev)
+/**
+ * dpram_wake_up
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Wakes up a DPRAM if it can sleep and increases the "accessing" counter in the
+ * dpram_link_device instance.
+ *
+ * CAUTION!!! dpram_allow_sleep() MUST be invoked after dpram_wake_up() success
+ * to decrease the "accessing" counter.
+ */
+static int dpram_wake_up(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
- struct dpram_rxb *rxb;
- u8 __iomem *src = get_rx_buff(dpld, dev);
- u32 qsize = get_rx_buff_size(dpld, dev);
- u32 in;
- u32 out;
- u32 rcvd;
- struct mif_irq_map map;
-
- rcvd = dpram_get_rxq_rcvd(dpld, dev, qsize, &in, &out);
- if (rcvd <= 0)
- return rcvd;
- if (dev == IPC_FMT) {
- set_dpram_map(dpld, &map);
- mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv"));
- }
+ if (unlikely(!dpld->need_wake_up))
+ return 0;
- /* Allocate an rxb */
- rxb = rxbq_get_free_rxb(&dpld->rxbq[dev]);
- if (!rxb) {
- mif_info("%s: ERR! %s rxbq_get_free_rxb fail\n",
- ld->name, get_dev_name(dev));
- return -ENOMEM;
+ if (dpld->ext_op->wakeup(dpld) < 0) {
+ mif_err("%s: <called by %pf> ERR! wakeup fail\n",
+ ld->name, CALLER);
+ return -EACCES;
}
- /* Read data from each DPRAM buffer */
- dpram_ipc_read(dpld, dev, rxb_put(rxb, rcvd), src, out, rcvd, qsize);
-
- /* Calculate and set new out */
- out += rcvd;
- if (out >= qsize)
- out -= qsize;
- set_rx_tail(dpld, dev, out);
+ atomic_inc(&dpld->accessing);
- return rcvd;
+ return 0;
}
-/*
- ret < 0 : error
- ret == 0 : no data
- ret > 0 : valid data
-*/
-static int dpram_ipc_recv_data_with_skb(struct dpram_link_device *dpld, int dev)
+/**
+ * dpram_allow_sleep
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Decreases the "accessing" counter in the dpram_link_device instance if it can
+ * sleep and allows the DPRAM to sleep only if the value of "accessing" counter
+ * is less than or equal to 0.
+ *
+ * MUST be invoked after dpram_wake_up() success to decrease the "accessing"
+ * counter.
+ */
+static void dpram_allow_sleep(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
- struct io_device *iod = dpld->iod[dev];
- struct sk_buff *skb;
- u8 __iomem *src = get_rx_buff(dpld, dev);
- u32 qsize = get_rx_buff_size(dpld, dev);
- u32 in;
- u32 out;
- u32 rcvd;
- int rest;
- u8 *frm;
- u8 *dst;
- unsigned int len;
- unsigned int pad;
- unsigned int tot;
- struct mif_irq_map map;
-
- rcvd = dpram_get_rxq_rcvd(dpld, dev, qsize, &in, &out);
- if (rcvd <= 0)
- return rcvd;
-
- if (dev == IPC_FMT) {
- set_dpram_map(dpld, &map);
- mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv"));
- }
-
- rest = rcvd;
- while (rest > 0) {
- frm = src + out;
- if (unlikely(!sipc5_start_valid(frm[0]))) {
- mif_err("%s: ERR! %s invalid start 0x%02X\n",
- ld->name, get_dev_name(dev), frm[0]);
- skb_queue_purge(&dpld->skb_rxq[dev]);
- return -EBADMSG;
- }
-
- len = sipc5_get_frame_sz16(frm);
- if (unlikely(len > rest)) {
- mif_err("%s: ERR! %s len %d > rest %d\n",
- ld->name, get_dev_name(dev), len, rest);
- skb_queue_purge(&dpld->skb_rxq[dev]);
- return -EBADMSG;
- }
-
- pad = sipc5_calc_padding_size(len);
- tot = len + pad;
-
- /* Allocate an skb */
- skb = dev_alloc_skb(tot);
- if (!skb) {
- mif_err("%s: ERR! %s dev_alloc_skb fail\n",
- ld->name, get_dev_name(dev));
- return -ENOMEM;
- }
- /* Read data from each DPRAM buffer */
- dst = skb_put(skb, tot);
- dpram_ipc_read(dpld, dev, dst, src, out, tot, qsize);
- skb_trim(skb, len);
- iod->recv_skb(iod, ld, skb);
+ if (unlikely(!dpld->need_wake_up))
+ return;
- /* Calculate and set new out */
- rest -= tot;
- out += tot;
- if (out >= qsize)
- out -= qsize;
+ if (atomic_dec_return(&dpld->accessing) <= 0) {
+ dpld->ext_op->sleep(dpld);
+ atomic_set(&dpld->accessing, 0);
+ mif_debug("%s: DPRAM sleep possible\n", ld->name);
}
-
- set_rx_tail(dpld, dev, out);
-
- return rcvd;
}
-static void non_command_handler(struct dpram_link_device *dpld, u16 intr)
+static int capture_dpram_snapshot(struct link_device *ld, struct io_device *iod)
{
- struct link_device *ld = &dpld->ld;
- int i = 0;
- int ret = 0;
- u16 tx_mask = 0;
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ struct sk_buff *skb;
+ u32 size = dpld->size;
+ u32 copied = 0;
+ u8 *dump;
- if (!dpram_ipc_active(dpld))
- return;
+ dpram_wake_up(dpld);
+ dump = capture_mem_dump(ld, dpld->base, dpld->size);
+ dpram_allow_sleep(dpld);
- /* Read data from DPRAM */
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- if (dpld->use_skb)
- ret = dpram_ipc_recv_data_with_skb(dpld, i);
- else
- ret = dpram_ipc_recv_data_with_rxb(dpld, i);
- if (ret < 0)
- dpram_reset_rx_circ(dpld, i);
+ if (!dump)
+ return -ENOMEM;
- /* Check and process REQ_ACK (at this time, in == out) */
- if (intr & get_mask_req_ack(dpld, i)) {
- mif_debug("%s: send %s_RES_ACK\n",
- ld->name, get_dev_name(i));
- tx_mask |= get_mask_res_ack(dpld, i);
+ while (copied < size) {
+ skb = alloc_skb(MAX_DUMP_SKB_SIZE, GFP_ATOMIC);
+ if (!skb) {
+ mif_err("ERR! alloc_skb fail\n");
+ kfree(dump);
+ return -ENOMEM;
}
- }
- if (!dpld->use_skb) {
- /* Schedule soft IRQ for RX */
- tasklet_hi_schedule(&dpld->rx_tsk);
- }
+ skb_put(skb, MAX_DUMP_SKB_SIZE);
+ memcpy(skb->data, (dump + copied), MAX_DUMP_SKB_SIZE);
+ copied += MAX_DUMP_SKB_SIZE;
- /* Try TX via DPRAM */
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- if (atomic_read(&dpld->res_required[i]) > 0) {
- ret = dpram_try_ipc_tx(dpld, i);
- if (ret > 0) {
- atomic_set(&dpld->res_required[i], 0);
- tx_mask |= get_mask_send(dpld, i);
- } else if (ret == -ENOSPC) {
- tx_mask |= get_mask_req_ack(dpld, i);
- }
- }
+ skb_queue_tail(&iod->sk_rx_q, skb);
+ wake_up(&iod->wq);
}
- if (tx_mask) {
- send_intr(dpld, INT_NON_CMD(tx_mask));
- mif_debug("%s: send intr 0x%04X\n", ld->name, tx_mask);
- }
+ kfree(dump);
+ return 0;
}
+/**
+ * handle_cp_crash
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Actual handler for the CRASH_EXIT command from a CP.
+ */
static void handle_cp_crash(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
struct io_device *iod;
int i;
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- mif_info("%s: purging %s_skb_txq\b", ld->name, get_dev_name(i));
+ if (dpld->forced_cp_crash)
+ dpld->forced_cp_crash = false;
+
+ /* Stop network interfaces */
+ mif_netif_stop(ld);
+
+ /* Purge the skb_txq in every IPC device (IPC_FMT, IPC_RAW, etc.) */
+ for (i = 0; i < ld->max_ipc_dev; i++)
skb_queue_purge(ld->skb_txq[i]);
- }
+ /* Change the modem state to STATE_CRASH_EXIT for the FMT IO device */
iod = link_get_iod_with_format(ld, IPC_FMT);
- iod->modem_state_changed(iod, STATE_CRASH_EXIT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_EXIT);
+ /* Change the modem state to STATE_CRASH_EXIT for the BOOT IO device */
iod = link_get_iod_with_format(ld, IPC_BOOT);
- iod->modem_state_changed(iod, STATE_CRASH_EXIT);
-
- iod = link_get_iod_with_channel(ld, PS_DATA_CH_0);
if (iod)
- iodevs_for_each(iod->msd, iodev_netif_stop, 0);
+ iod->modem_state_changed(iod, STATE_CRASH_EXIT);
}
-static void handle_no_crash_ack(unsigned long arg)
+/**
+ * handle_no_cp_crash_ack
+ * @arg: pointer to an instance of dpram_link_device structure
+ *
+ * Invokes handle_cp_crash() to enter the CRASH_EXIT state if there was no
+ * CRASH_ACK from a CP in FORCE_CRASH_ACK_TIMEOUT.
+ */
+static void handle_no_cp_crash_ack(unsigned long arg)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)arg;
struct link_device *ld = &dpld->ld;
@@ -955,165 +736,341 @@ static void handle_no_crash_ack(unsigned long arg)
handle_cp_crash(dpld);
}
-static int trigger_force_cp_crash(struct dpram_link_device *dpld)
+/**
+ * trigger_forced_cp_crash
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Triggers an enforced CP crash.
+ */
+static void trigger_forced_cp_crash(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
+#ifdef DEBUG_MODEM_IF
+ struct trace_data *trd;
+ u8 *dump;
+ struct timespec ts;
+ getnstimeofday(&ts);
+#endif
if (ld->mode == LINK_MODE_ULOAD) {
- mif_err("%s: CP crash is already in progress\n", ld->mc->name);
- return 0;
+ mif_err("%s: <called by %pf> ALREADY in progress\n",
+ ld->name, CALLER);
+ return;
}
ld->mode = LINK_MODE_ULOAD;
- mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0));
+ dpld->forced_cp_crash = true;
+
+ disable_irq_nosync(dpld->irq);
+
+ dpram_wake_up(dpld);
+
+#ifdef DEBUG_MODEM_IF
+ dump = capture_mem_dump(ld, dpld->base, dpld->size);
+ if (dump) {
+ trd = trq_get_free_slot(&dpld->trace_list);
+ memcpy(&trd->ts, &ts, sizeof(struct timespec));
+ trd->dev = IPC_DEBUG;
+ trd->data = dump;
+ trd->size = dpld->size;
+ }
+#endif
- if (dpld->dp_type == CP_IDPRAM)
- dpram_wake_up(dpld);
+ enable_irq(dpld->irq);
- send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT));
+ mif_err("%s: <called by %pf>\n", ld->name, CALLER);
+ /* Send CRASH_EXIT command to a CP */
+ send_int2cp(dpld, INT_CMD(INT_CMD_CRASH_EXIT));
+ get_dpram_status(dpld, TX, msq_get_free_slot(&dpld->stat_list));
+
+ /* If there is no CRASH_ACK from a CP in FORCE_CRASH_ACK_TIMEOUT,
+ handle_no_cp_crash_ack() will be executed. */
mif_add_timer(&dpld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
- handle_no_crash_ack, (unsigned long)dpld);
+ handle_no_cp_crash_ack, (unsigned long)dpld);
- return 0;
+ return;
}
-static int dpram_init_ipc(struct dpram_link_device *dpld)
+/**
+ * ext_command_handler
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @cmd: extended DPRAM command from a CP
+ *
+ * Processes an extended command from a CP.
+ */
+static void ext_command_handler(struct dpram_link_device *dpld, u16 cmd)
{
struct link_device *ld = &dpld->ld;
- int i;
-
- if (ld->mode == LINK_MODE_IPC &&
- get_magic(dpld) == DPRAM_MAGIC_CODE &&
- get_access(dpld) == 1)
- mif_info("%s: IPC already initialized\n", ld->name);
+ u16 resp;
- /* Clear pointers in every circular queue */
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- set_tx_head(dpld, i, 0);
- set_tx_tail(dpld, i, 0);
- set_rx_head(dpld, i, 0);
- set_rx_tail(dpld, i, 0);
- }
+ switch (EXT_CMD_MASK(cmd)) {
+ case EXT_CMD_SET_SPEED_LOW:
+ if (dpld->dpram->setup_speed) {
+ dpld->dpram->setup_speed(DPRAM_SPEED_LOW);
+ resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_LOW);
+ send_int2cp(dpld, resp);
+ }
+ break;
- /* Initialize variables for efficient TX/RX processing */
- for (i = 0; i < dpld->max_ipc_dev; i++)
- dpld->iod[i] = link_get_iod_with_format(ld, i);
- dpld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW);
+ case EXT_CMD_SET_SPEED_MID:
+ if (dpld->dpram->setup_speed) {
+ dpld->dpram->setup_speed(DPRAM_SPEED_MID);
+ resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_MID);
+ send_int2cp(dpld, resp);
+ }
+ break;
- if (dpld->iod[IPC_RAW]->recv_skb)
- dpld->use_skb = true;
+ case EXT_CMD_SET_SPEED_HIGH:
+ if (dpld->dpram->setup_speed) {
+ dpld->dpram->setup_speed(DPRAM_SPEED_HIGH);
+ resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_HIGH);
+ send_int2cp(dpld, resp);
+ }
+ break;
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- spin_lock_init(&dpld->tx_lock[i]);
- atomic_set(&dpld->res_required[i], 0);
- skb_queue_purge(&dpld->skb_rxq[i]);
+ default:
+ mif_info("%s: unknown command 0x%04X\n", ld->name, cmd);
+ break;
}
+}
- /* Enable IPC */
- atomic_set(&dpld->accessing, 0);
-
- set_magic(dpld, DPRAM_MAGIC_CODE);
- set_access(dpld, 1);
- if (get_magic(dpld) != DPRAM_MAGIC_CODE || get_access(dpld) != 1)
- return -EACCES;
+/**
+ * udl_command_handler
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @cmd: DPRAM upload/download command from a CP
+ *
+ * Processes a command for upload/download from a CP.
+ */
+static void udl_command_handler(struct dpram_link_device *dpld, u16 cmd)
+{
+ struct link_device *ld = &dpld->ld;
- ld->mode = LINK_MODE_IPC;
+ if (cmd & UDL_RESULT_FAIL) {
+ mif_err("%s: ERR! command fail (0x%04X)\n", ld->name, cmd);
+ return;
+ }
- if (wake_lock_active(&dpld->wlock))
- wake_unlock(&dpld->wlock);
+ switch (UDL_CMD_MASK(cmd)) {
+ case UDL_CMD_RECV_READY:
+ mif_err("%s: [CP->AP] CMD_DL_READY (0x%04X)\n", ld->name, cmd);
+#ifdef CONFIG_CDMA_MODEM_CBP72
+ mif_err("%s: [AP->CP] CMD_DL_START_REQ (0x%04X)\n",
+ ld->name, CMD_DL_START_REQ);
+ send_int2cp(dpld, CMD_DL_START_REQ);
+#else
+ complete(&dpld->udl_cmpl);
+#endif
+ break;
- return 0;
+ default:
+ complete(&dpld->udl_cmpl);
+ }
}
+/**
+ * cmd_req_active_handler
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Handles the REQ_ACTIVE command from a CP.
+ */
static void cmd_req_active_handler(struct dpram_link_device *dpld)
{
- send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE));
+ send_int2cp(dpld, INT_CMD(INT_CMD_RES_ACTIVE));
}
+/**
+ * cmd_crash_reset_handler
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Handles the CRASH_RESET command from a CP.
+ */
static void cmd_crash_reset_handler(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
struct io_device *iod = NULL;
+ int i;
ld->mode = LINK_MODE_ULOAD;
if (!wake_lock_active(&dpld->wlock))
wake_lock(&dpld->wlock);
+ /* Stop network interfaces */
+ mif_netif_stop(ld);
+
+ /* Purge the skb_txq in every IPC device (IPC_FMT, IPC_RAW, etc.) */
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ skb_queue_purge(ld->skb_txq[i]);
+
mif_err("%s: Recv 0xC7 (CRASH_RESET)\n", ld->name);
+ /* Change the modem state to STATE_CRASH_RESET for the FMT IO device */
iod = link_get_iod_with_format(ld, IPC_FMT);
iod->modem_state_changed(iod, STATE_CRASH_RESET);
+ /* Change the modem state to STATE_CRASH_RESET for the BOOT IO device */
iod = link_get_iod_with_format(ld, IPC_BOOT);
iod->modem_state_changed(iod, STATE_CRASH_RESET);
}
+/**
+ * cmd_crash_exit_handler
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Handles the CRASH_EXIT command from a CP.
+ */
static void cmd_crash_exit_handler(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
- u32 size = dpld->dpctl->dp_size;
- char *dpram_buff = NULL;
+#ifdef DEBUG_MODEM_IF
+ struct trace_data *trd;
+ u8 *dump;
+ struct timespec ts;
+ getnstimeofday(&ts);
+#endif
ld->mode = LINK_MODE_ULOAD;
if (!wake_lock_active(&dpld->wlock))
wake_lock(&dpld->wlock);
- mif_err("%s: Recv 0xC9 (CRASH_EXIT)\n", ld->name);
-
- if (dpld->dp_type == CP_IDPRAM)
- dpram_wake_up(dpld);
+ del_timer(&dpld->crash_ack_timer);
- dpram_buff = kzalloc(size + (MAX_MIF_SEPA_SIZE * 2), GFP_ATOMIC);
- if (!dpram_buff) {
- mif_err("DPRAM dump failed!!\n");
- } else {
- memset(dpram_buff, 0, size + (MAX_MIF_SEPA_SIZE * 2));
- memcpy(dpram_buff, MIF_SEPARATOR_DPRAM, MAX_MIF_SEPA_SIZE);
- memcpy(dpram_buff + MAX_MIF_SEPA_SIZE, &size, sizeof(u32));
- dpram_buff += (MAX_MIF_SEPA_SIZE * 2);
- dpram_dump_memory(ld, dpram_buff);
+ dpram_wake_up(dpld);
+
+#ifdef DEBUG_MODEM_IF
+ if (!dpld->forced_cp_crash) {
+ dump = capture_mem_dump(ld, dpld->base, dpld->size);
+ if (dump) {
+ trd = trq_get_free_slot(&dpld->trace_list);
+ memcpy(&trd->ts, &ts, sizeof(struct timespec));
+ trd->dev = IPC_DEBUG;
+ trd->data = dump;
+ trd->size = dpld->size;
+ }
}
-
- del_timer(&dpld->crash_ack_timer);
+#endif
if (dpld->ext_op && dpld->ext_op->crash_log)
dpld->ext_op->crash_log(dpld);
+ mif_err("%s: Recv 0xC9 (CRASH_EXIT)\n", ld->name);
+
handle_cp_crash(dpld);
}
-static void cmd_phone_start_handler(struct dpram_link_device *dpld)
+/**
+ * init_dpram_ipc
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Initializes IPC via DPRAM.
+ */
+static int init_dpram_ipc(struct dpram_link_device *dpld)
{
struct link_device *ld = &dpld->ld;
- struct io_device *iod = NULL;
+ int i;
+
+ if (ld->mode == LINK_MODE_IPC &&
+ get_magic(dpld) == DPRAM_MAGIC_CODE &&
+ get_access(dpld) == 1)
+ mif_info("%s: IPC already initialized\n", ld->name);
+
+ /* Clear pointers in every circular queue */
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ set_txq_head(dpld, i, 0);
+ set_txq_tail(dpld, i, 0);
+ set_rxq_head(dpld, i, 0);
+ set_rxq_tail(dpld, i, 0);
+ }
+
+ /* Initialize variables for efficient TX/RX processing */
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ dpld->iod[i] = link_get_iod_with_format(ld, i);
+ dpld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW);
+
+ /* Initialize variables for TX flow control */
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ atomic_set(&dpld->res_required[i], 0);
+
+ /* Enable IPC */
+ if (wake_lock_active(&dpld->wlock))
+ wake_unlock(&dpld->wlock);
+
+ atomic_set(&dpld->accessing, 0);
+
+ set_magic(dpld, DPRAM_MAGIC_CODE);
+ set_access(dpld, 1);
+ if (get_magic(dpld) != DPRAM_MAGIC_CODE || get_access(dpld) != 1)
+ return -EACCES;
+
+ ld->mode = LINK_MODE_IPC;
+
+ return 0;
+}
+
+/**
+ * reset_dpram_ipc
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Reset DPRAM with IPC map.
+ */
+static void reset_dpram_ipc(struct dpram_link_device *dpld)
+{
+ int i;
+ struct link_device *ld = &dpld->ld;
+
+ dpld->set_access(dpld, 0);
+
+ /* Clear pointers in every circular queue */
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ dpld->set_txq_head(dpld, i, 0);
+ dpld->set_txq_tail(dpld, i, 0);
+ dpld->set_rxq_head(dpld, i, 0);
+ dpld->set_rxq_tail(dpld, i, 0);
+ }
- mif_info("%s: Recv 0xC8 (CP_START)\n", ld->name);
+ dpld->set_magic(dpld, DPRAM_MAGIC_CODE);
+ dpld->set_access(dpld, 1);
+}
+
+/**
+ * cmd_phone_start_handler
+ * @dpld: pointer to an instance of dpram_link_device structure
+ *
+ * Handles the PHONE_START command from a CP.
+ */
+static void cmd_phone_start_handler(struct dpram_link_device *dpld)
+{
+ struct link_device *ld = &dpld->ld;
+ struct io_device *iod;
- dpram_init_ipc(dpld);
+ mif_err("%s: Recv 0xC8 (CP_START)\n", ld->name);
iod = link_get_iod_with_format(ld, IPC_FMT);
if (!iod) {
- mif_info("%s: ERR! no iod\n", ld->name);
+ mif_err("%s: ERR! no iod\n", ld->name);
return;
}
- if (dpld->ext_op && dpld->ext_op->cp_start_handler)
- dpld->ext_op->cp_start_handler(dpld);
+ init_dpram_ipc(dpld);
- if (ld->mc->phone_state != STATE_ONLINE) {
- mif_info("%s: phone_state: %d -> ONLINE\n",
- ld->name, ld->mc->phone_state);
- iod->modem_state_changed(iod, STATE_ONLINE);
- }
+ iod->modem_state_changed(iod, STATE_ONLINE);
- mif_info("%s: Send 0xC2 (INIT_END)\n", ld->name);
- send_intr(dpld, INT_CMD(INT_CMD_INIT_END));
+ if (dpld->ext_op && dpld->ext_op->cp_start_handler) {
+ dpld->ext_op->cp_start_handler(dpld);
+ } else {
+ mif_err("%s: Send 0xC2 (INIT_END)\n", ld->name);
+ send_int2cp(dpld, INT_CMD(INT_CMD_INIT_END));
+ }
}
-static void command_handler(struct dpram_link_device *dpld, u16 cmd)
+/**
+ * cmd_handler: processes a DPRAM command from a CP
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @cmd: DPRAM command from a CP
+ */
+static void cmd_handler(struct dpram_link_device *dpld, u16 cmd)
{
struct link_device *ld = &dpld->ld;
@@ -1123,19 +1080,19 @@ static void command_handler(struct dpram_link_device *dpld, u16 cmd)
break;
case INT_CMD_CRASH_RESET:
- dpld->dpram_init_status = DPRAM_INIT_STATE_NONE;
+ dpld->init_status = DPRAM_INIT_STATE_NONE;
cmd_crash_reset_handler(dpld);
break;
case INT_CMD_CRASH_EXIT:
- dpld->dpram_init_status = DPRAM_INIT_STATE_NONE;
+ dpld->init_status = DPRAM_INIT_STATE_NONE;
cmd_crash_exit_handler(dpld);
break;
case INT_CMD_PHONE_START:
- dpld->dpram_init_status = DPRAM_INIT_STATE_READY;
+ dpld->init_status = DPRAM_INIT_STATE_READY;
cmd_phone_start_handler(dpld);
- complete_all(&dpld->dpram_init_cmd);
+ complete_all(&ld->init_cmpl);
break;
case INT_CMD_NV_REBUILDING:
@@ -1143,14 +1100,14 @@ static void command_handler(struct dpram_link_device *dpld, u16 cmd)
break;
case INT_CMD_PIF_INIT_DONE:
- complete_all(&dpld->modem_pif_init_done);
+ complete_all(&ld->pif_cmpl);
break;
case INT_CMD_SILENT_NV_REBUILDING:
mif_info("%s: SILENT_NV_REBUILDING\n", ld->name);
break;
- case INT_CMD_NORMAL_PWR_OFF:
+ case INT_CMD_NORMAL_POWER_OFF:
/*ToDo:*/
/*kernel_sec_set_cp_ack()*/;
break;
@@ -1165,72 +1122,437 @@ static void command_handler(struct dpram_link_device *dpld, u16 cmd)
}
}
-static void ext_command_handler(struct dpram_link_device *dpld, u16 cmd)
+/**
+ * ipc_rx_work
+ * @work: pointer to an instance of the work_struct structure
+ *
+ * Invokes the recv method in the io_device instance to perform receiving IPC
+ * messages from each skb.
+ */
+static void ipc_rx_work(struct work_struct *work)
+{
+ struct dpram_link_device *dpld;
+ struct link_device *ld;
+ struct io_device *iod;
+ struct sk_buff *skb;
+ int i;
+
+ dpld = container_of(work, struct dpram_link_device, rx_dwork.work);
+ ld = &dpld->ld;
+
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ iod = dpld->iod[i];
+ while (1) {
+ skb = skb_dequeue(ld->skb_rxq[i]);
+ if (!skb)
+ break;
+
+ if (iod->recv_skb) {
+ iod->recv_skb(iod, ld, skb);
+ } else {
+ iod->recv(iod, ld, skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+ }
+ }
+ }
+}
+
+/**
+ * get_rxq_rcvd
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ * OUT @dcst: pointer to an instance of circ_status structure
+ *
+ * Stores {start address of the buffer in a RXQ, size of the buffer, in & out
+ * pointer values, size of received data} into the 'stat' instance.
+ *
+ * Returns an error code.
+ */
+static int get_rxq_rcvd(struct dpram_link_device *dpld, int dev,
+ struct mem_status *mst, struct circ_status *dcst)
{
struct link_device *ld = &dpld->ld;
- u16 resp;
- switch (EXT_CMD_MASK(cmd)) {
- case EXT_CMD_SET_SPEED_LOW:
- if (dpld->dpctl->setup_speed) {
- dpld->dpctl->setup_speed(DPRAM_SPEED_LOW);
- resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_LOW);
- send_intr(dpld, resp);
+ dcst->buff = get_rxq_buff(dpld, dev);
+ dcst->qsize = get_rxq_buff_size(dpld, dev);
+ dcst->in = mst->head[dev][RX];
+ dcst->out = mst->tail[dev][RX];
+ dcst->size = circ_get_usage(dcst->qsize, dcst->in, dcst->out);
+
+ if (circ_valid(dcst->qsize, dcst->in, dcst->out)) {
+ mif_debug("%s: %s_RXQ qsize[%u] in[%u] out[%u] rcvd[%u]\n",
+ ld->name, get_dev_name(dev), dcst->qsize, dcst->in,
+ dcst->out, dcst->size);
+ return 0;
+ } else {
+ mif_err("%s: ERR! %s_RXQ invalid (qsize[%d] in[%d] out[%d])\n",
+ ld->name, get_dev_name(dev), dcst->qsize, dcst->in,
+ dcst->out);
+ return -EIO;
+ }
+}
+
+/**
+ * rx_sipc4_frames
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Returns
+ * ret < 0 : error
+ * ret == 0 : ILLEGAL status
+ * ret > 0 : valid data
+ *
+ * Must be invoked only when there is data in the corresponding RXQ.
+ *
+ * Requires a bottom half (e.g. ipc_rx_task) that will invoke the recv method in
+ * the io_device instance.
+ */
+static int rx_sipc4_frames(struct dpram_link_device *dpld, int dev,
+ struct mem_status *mst)
+{
+ struct link_device *ld = &dpld->ld;
+ struct sk_buff *skb;
+ u8 *dst;
+ struct circ_status dcst;
+ int rcvd;
+
+ rcvd = get_rxq_rcvd(dpld, dev, mst, &dcst);
+ if (unlikely(rcvd < 0)) {
+#ifdef DEBUG_MODEM_IF
+ trigger_forced_cp_crash(dpld);
+#endif
+ goto exit;
+ }
+ rcvd = dcst.size;
+
+ /* Allocate an skb */
+ skb = dev_alloc_skb(rcvd);
+ if (!skb) {
+ mif_info("%s: ERR! %s dev_alloc_skb fail\n",
+ ld->name, get_dev_name(dev));
+ rcvd = -ENOMEM;
+ goto exit;
+ }
+
+ /* Read data from the RXQ */
+ dst = skb_put(skb, rcvd);
+ circ_read16_from_io(dst, dcst.buff, dcst.qsize, dcst.out, rcvd);
+
+ /* Store the skb to the corresponding skb_rxq */
+ skb_queue_tail(ld->skb_rxq[dev], skb);
+
+exit:
+ /* Update tail (out) pointer to empty out the RXQ */
+ set_rxq_tail(dpld, dev, dcst.in);
+
+ return rcvd;
+}
+
+/**
+ * rx_sipc5_frames
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Returns
+ * ret < 0 : error
+ * ret == 0 : ILLEGAL status
+ * ret > 0 : valid data
+ *
+ * Must be invoked only when there is data in the corresponding RXQ.
+ *
+ * Requires a recv_skb method in the io_device instance, so this function must
+ * be used for only SIPC5.
+ */
+static int rx_sipc5_frames(struct dpram_link_device *dpld, int dev,
+ struct mem_status *mst)
+{
+ struct link_device *ld = &dpld->ld;
+ struct sk_buff *skb;
+ /**
+ * variables for the status of the circular queue
+ */
+ u8 __iomem *src;
+ u8 hdr[SIPC5_MIN_HEADER_SIZE];
+ struct circ_status dcst;
+ /**
+ * variables for RX processing
+ */
+ int qsize; /* size of the queue */
+ int rcvd; /* size of data in the RXQ or error */
+ int rest; /* size of the rest data */
+ int idx; /* index to the start of current frame */
+ u8 *frm; /* pointer to current frame */
+ u8 *dst; /* pointer to the destination buffer */
+ int tot; /* total length including padding data */
+ /**
+ * variables for debug logging
+ */
+ struct mif_irq_map map;
+
+ /* Get data size in the RXQ and in/out pointer values */
+ rcvd = get_rxq_rcvd(dpld, dev, mst, &dcst);
+ if (unlikely(rcvd < 0)) {
+ mif_err("%s: ERR! rcvd %d < 0\n", ld->name, rcvd);
+ goto exit;
+ }
+
+ rcvd = dcst.size;
+ src = dcst.buff;
+ qsize = dcst.qsize;
+ idx = dcst.out;
+
+ if (dev == IPC_FMT) {
+ set_dpram_map(dpld, &map);
+ mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv"));
+ }
+
+#if 0
+ skb = dev_alloc_skb(rcvd);
+
+ /*
+ ** If there is enough free space for an skb to store received
+ ** data at once,
+ */
+ if (skb) {
+ /* Read all data from the RXQ to the skb */
+ dst = skb_put(skb, rcvd);
+ if (unlikely(dpld->strict_io_access))
+ circ_read16_from_io(dst, src, qsize, idx, rcvd);
+ else
+ circ_read(dst, src, qsize, idx, rcvd);
+
+#ifdef DEBUG_MODEM_IF
+ /* Verify data copied to the skb */
+ if (ld->aligned && memcmp16_to_io((src + idx), dst, 4)) {
+ mif_err("%s: memcmp16_to_io fail\n", ld->name);
+ rcvd = -EIO;
+ goto exit;
}
- break;
+#endif
- case EXT_CMD_SET_SPEED_MID:
- if (dpld->dpctl->setup_speed) {
- dpld->dpctl->setup_speed(DPRAM_SPEED_MID);
- resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_MID);
- send_intr(dpld, resp);
+ /* Store the skb to the corresponding skb_rxq */
+ skb_queue_tail(ld->skb_rxq[dev], skb);
+
+ goto exit;
+ }
+
+ /*
+ ** If there was no enough space to store received data at once,
+ */
+#endif
+
+ rest = rcvd;
+ while (rest > 0) {
+ /* Calculate the start of an SIPC5 frame */
+ frm = src + idx;
+
+ /* Copy the header in the frame to the header buffer */
+ if (unlikely(dpld->strict_io_access))
+ memcpy16_from_io(hdr, frm, SIPC5_MIN_HEADER_SIZE);
+ else
+ memcpy(hdr, frm, SIPC5_MIN_HEADER_SIZE);
+
+ /* Check the config field in the header */
+ if (unlikely(!sipc5_start_valid(hdr))) {
+ char str[MIF_MAX_STR_LEN];
+ snprintf(str, MIF_MAX_STR_LEN, "%s: BAD CONFIG",
+ ld->mc->name);
+ mif_err("%s: ERR! %s INVALID config 0x%02X\n",
+ ld->name, get_dev_name(dev), hdr[0]);
+ pr_ipc(1, str, hdr, 4);
+ rcvd = -EBADMSG;
+ goto exit;
}
- break;
- case EXT_CMD_SET_SPEED_HIGH:
- if (dpld->dpctl->setup_speed) {
- dpld->dpctl->setup_speed(DPRAM_SPEED_HIGH);
- resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_HIGH);
- send_intr(dpld, resp);
+ /* Verify the total length of the frame (data + padding) */
+ tot = sipc5_get_total_len(hdr);
+ if (unlikely(tot > rest)) {
+ char str[MIF_MAX_STR_LEN];
+ snprintf(str, MIF_MAX_STR_LEN, "%s: BAD LENGTH",
+ ld->mc->name);
+ mif_err("%s: ERR! %s tot %d > rest %d\n",
+ ld->name, get_dev_name(dev), tot, rest);
+ pr_ipc(1, str, hdr, 4);
+ rcvd = -EBADMSG;
+#if defined(CONFIG_MACH_C1_KOR_SKT) || defined(CONFIG_MACH_C1_KOR_KT) || defined(CONFIG_MACH_C1_KOR_LGT)
+ return rcvd;
+#else
+ goto exit;
+#endif
}
- break;
- default:
- mif_info("%s: unknown command 0x%04X\n", ld->name, cmd);
- break;
+ /* Allocate an skb */
+ skb = dev_alloc_skb(tot);
+ if (!skb) {
+ mif_err("%s: ERR! %s dev_alloc_skb fail\n",
+ ld->name, get_dev_name(dev));
+ rcvd = -ENOMEM;
+ goto exit;
+ }
+
+ /* Set the attribute of the skb as "single frame" */
+ skbpriv(skb)->single_frame = true;
+
+ /* Read the frame from the RXQ */
+ dst = skb_put(skb, tot);
+ if (unlikely(dpld->strict_io_access))
+ circ_read16_from_io(dst, src, qsize, idx, tot);
+ else
+ circ_read(dst, src, qsize, idx, tot);
+
+#ifdef DEBUG_MODEM_IF
+ /* Take a log for debugging */
+ if (unlikely(dev == IPC_FMT)) {
+ size_t len = (skb->len > 32) ? 32 : skb->len;
+ char str[MIF_MAX_STR_LEN];
+ snprintf(str, MIF_MAX_STR_LEN, "%s: CP2MIF",
+ ld->mc->name);
+ pr_ipc(0, str, skb->data, len);
+ }
+#endif
+
+#ifdef DEBUG_MODEM_IF
+ /* Verify data copied to the skb */
+ if (ld->aligned && memcmp16_to_io((src + idx), dst, 4)) {
+ mif_err("%s: memcmp16_to_io fail\n", ld->name);
+ rcvd = -EIO;
+ goto exit;
+ }
+#endif
+
+ /* Store the skb to the corresponding skb_rxq */
+ skb_queue_tail(ld->skb_rxq[dev], skb);
+
+ /* Calculate new idx value */
+ rest -= tot;
+ idx += tot;
+ if (unlikely(idx >= qsize))
+ idx -= qsize;
}
+
+exit:
+#ifdef DEBUG_MODEM_IF
+ if (rcvd < 0)
+ trigger_forced_cp_crash(dpld);
+#endif
+
+ /* Update tail (out) pointer to empty out the RXQ */
+ set_rxq_tail(dpld, dev, dcst.in);
+
+ return rcvd;
}
-static void udl_command_handler(struct dpram_link_device *dpld, u16 cmd)
+/**
+ * msg_handler: receives IPC messages from every RXQ
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @stat: pointer to an instance of mem_status structure
+ *
+ * 1) Receives all IPC message frames currently in every DPRAM RXQ.
+ * 2) Sends RES_ACK responses if there are REQ_ACK requests from a CP.
+ * 3) Completes all threads waiting for the corresponding RES_ACK from a CP if
+ * there is any RES_ACK response.
+ */
+static void msg_handler(struct dpram_link_device *dpld, struct mem_status *stat)
{
struct link_device *ld = &dpld->ld;
+ int i = 0;
+ int ret = 0;
+ u16 mask = 0;
+ u16 intr = stat->int2ap;
- if (cmd & UDL_RESULT_FAIL) {
- mif_info("%s: ERR! Command failed: %04x\n", ld->name, cmd);
+ if (!ipc_active(dpld))
return;
+
+ /* Read data from DPRAM */
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ /* Invoke an RX function only when there is data in the RXQ */
+ if (unlikely(stat->head[i][RX] == stat->tail[i][RX])) {
+ mif_debug("%s: %s_RXQ is empty\n",
+ ld->name, get_dev_name(i));
+ } else {
+ if (unlikely(ld->ipc_version < SIPC_VER_50))
+ ret = rx_sipc4_frames(dpld, i, stat);
+ else
+ ret = rx_sipc5_frames(dpld, i, stat);
+ if (ret < 0)
+ reset_rxq_circ(dpld, i);
+ }
}
- switch (UDL_CMD_MASK(cmd)) {
- case UDL_CMD_RECV_READY:
- mif_debug("%s: Send CP-->AP RECEIVE_READY\n", ld->name);
- send_intr(dpld, CMD_IMG_START_REQ);
- break;
- default:
- complete_all(&dpld->udl_cmd_complete);
+ /* Schedule soft IRQ for RX */
+ queue_delayed_work(system_nrt_wq, &dpld->rx_dwork, 0);
+
+ /* Check and process REQ_ACK (at this time, in == out) */
+ if (unlikely(intr & INT_MASK_REQ_ACK_SET)) {
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ if (intr & get_mask_req_ack(dpld, i)) {
+ mif_debug("%s: set %s_RES_ACK\n",
+ ld->name, get_dev_name(i));
+ mask |= get_mask_res_ack(dpld, i);
+ }
+ }
+
+ send_int2cp(dpld, INT_NON_CMD(mask));
+ }
+
+ /* Check and process RES_ACK */
+ if (unlikely(intr & INT_MASK_RES_ACK_SET)) {
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ if (intr & get_mask_res_ack(dpld, i)) {
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: recv %s_RES_ACK\n",
+ ld->name, get_dev_name(i));
+ print_circ_status(ld, i, stat);
+#endif
+ complete(&dpld->req_ack_cmpl[i]);
+ }
+ }
}
}
-static inline void dpram_ipc_rx(struct dpram_link_device *dpld, u16 intr)
+/**
+ * cmd_msg_handler: processes a DPRAM command or receives IPC messages
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @stat: pointer to an instance of mem_status structure
+ *
+ * Invokes cmd_handler for a DPRAM command or msg_handler for IPC messages.
+ */
+static inline void cmd_msg_handler(struct dpram_link_device *dpld,
+ struct mem_status *stat)
{
- if (unlikely(INT_CMD_VALID(intr)))
- command_handler(dpld, intr);
- else
- non_command_handler(dpld, intr);
+ struct dpram_ext_op *ext_op = dpld->ext_op;
+ struct mem_status *mst = msq_get_free_slot(&dpld->stat_list);
+ u16 intr = stat->int2ap;
+
+ memcpy(mst, stat, sizeof(struct mem_status));
+
+ if (unlikely(INT_CMD_VALID(intr))) {
+ if (ext_op && ext_op->cmd_handler)
+ ext_op->cmd_handler(dpld, intr);
+ else
+ cmd_handler(dpld, intr);
+ } else {
+ msg_handler(dpld, stat);
+ }
}
-static inline void dpram_intr_handler(struct dpram_link_device *dpld, u16 intr)
+/**
+ * intr_handler: processes an interrupt from a CP
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @stat: pointer to an instance of mem_status structure
+ *
+ * Call flow for normal interrupt handling:
+ * cmd_msg_handler -> cmd_handler -> cmd_xxx_handler
+ * cmd_msg_handler -> msg_handler -> rx_sipc5_frames -> ...
+ */
+static inline void intr_handler(struct dpram_link_device *dpld,
+ struct mem_status *stat)
{
char *name = dpld->ld.name;
+ u16 intr = stat->int2ap;
if (unlikely(intr == INT_POWERSAFE_FAIL)) {
mif_info("%s: intr == INT_POWERSAFE_FAIL\n", name);
@@ -1247,131 +1569,696 @@ static inline void dpram_intr_handler(struct dpram_link_device *dpld, u16 intr)
mif_info("%s: ERR! invalid intr 0x%04X\n",
name, intr);
} else {
- mif_info("%s: ERR! invalid intr 0x%04X\n", name, intr);
+ mif_err("%s: ERR! invalid intr 0x%04X\n", name, intr);
}
+
return;
}
if (likely(INT_VALID(intr)))
- dpram_ipc_rx(dpld, intr);
+ cmd_msg_handler(dpld, stat);
else
- mif_info("%s: ERR! invalid intr 0x%04X\n", name, intr);
+ mif_err("%s: ERR! invalid intr 0x%04X\n", name, intr);
}
+/**
+ * ap_idpram_irq_handler: interrupt handler for an internal DPRAM in an AP
+ * @irq: IRQ number
+ * @data: pointer to a data
+ *
+ * 1) Reads the interrupt value
+ * 2) Performs interrupt handling
+ */
static irqreturn_t ap_idpram_irq_handler(int irq, void *data)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)data;
struct link_device *ld = (struct link_device *)&dpld->ld;
- u16 int2ap = recv_intr(dpld);
+ struct modemlink_dpram_data *dpram = dpld->dpram;
+ struct mem_status stat;
if (unlikely(ld->mode == LINK_MODE_OFFLINE))
return IRQ_HANDLED;
- dpram_intr_handler(dpld, int2ap);
+ get_dpram_status(dpld, RX, &stat);
+
+ intr_handler(dpld, &stat);
+
+ if (likely(dpram->clear_int2ap))
+ dpram->clear_int2ap();
return IRQ_HANDLED;
}
+/**
+ * cp_idpram_irq_handler: interrupt handler for an internal DPRAM in a CP
+ * @irq: IRQ number
+ * @data: pointer to a data
+ *
+ * 1) Wakes up the DPRAM
+ * 2) Reads the interrupt value
+ * 3) Performs interrupt handling
+ * 4) Clears the interrupt port (port = memory or register)
+ * 5) Allows the DPRAM to sleep
+ */
static irqreturn_t cp_idpram_irq_handler(int irq, void *data)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)data;
struct link_device *ld = (struct link_device *)&dpld->ld;
- u16 int2ap;
-
- if (unlikely(ld->mode == LINK_MODE_OFFLINE))
+ struct dpram_ext_op *ext_op = dpld->ext_op;
+ struct mem_status stat;
+
+ if (unlikely(ld->mode == LINK_MODE_OFFLINE)) {
+ mif_err("%s: ERR! ld->mode == LINK_MODE_OFFLINE\n", ld->name);
+ get_dpram_status(dpld, RX, &stat);
+#ifdef DEBUG_MODEM_IF
+ print_mem_status(ld, &stat);
+#endif
return IRQ_HANDLED;
+ }
if (dpram_wake_up(dpld) < 0) {
- log_dpram_status(dpld);
- trigger_force_cp_crash(dpld);
+ trigger_forced_cp_crash(dpld);
return IRQ_HANDLED;
}
- int2ap = recv_intr(dpld);
+ get_dpram_status(dpld, RX, &stat);
- dpram_intr_handler(dpld, int2ap);
+ intr_handler(dpld, &stat);
- clear_intr(dpld);
+ if (likely(ext_op && ext_op->clear_int2ap))
+ ext_op->clear_int2ap(dpld);
dpram_allow_sleep(dpld);
return IRQ_HANDLED;
}
+/**
+ * ext_dpram_irq_handler: interrupt handler for a normal external DPRAM
+ * @irq: IRQ number
+ * @data: pointer to a data
+ *
+ * 1) Reads the interrupt value
+ * 2) Performs interrupt handling
+ */
static irqreturn_t ext_dpram_irq_handler(int irq, void *data)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)data;
struct link_device *ld = (struct link_device *)&dpld->ld;
- u16 int2ap = recv_intr(dpld);
+ struct mem_status stat;
if (unlikely(ld->mode == LINK_MODE_OFFLINE))
return IRQ_HANDLED;
- dpram_intr_handler(dpld, int2ap);
+ get_dpram_status(dpld, RX, &stat);
+
+ intr_handler(dpld, &stat);
return IRQ_HANDLED;
}
-static void dpram_send_ipc(struct link_device *ld, int dev,
- struct io_device *iod, struct sk_buff *skb)
+/**
+ * get_txq_space
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * OUT @stat: pointer to an instance of circ_status structure
+ *
+ * Stores {start address of the buffer in a TXQ, size of the buffer, in & out
+ * pointer values, size of free space} into the 'stat' instance.
+ *
+ * Returns the size of free space in the buffer or an error code.
+ */
+static int get_txq_space(struct dpram_link_device *dpld, int dev,
+ struct circ_status *stat)
{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ struct link_device *ld = &dpld->ld;
+ int cnt = 0;
+ u32 qsize;
+ u32 head;
+ u32 tail;
+ int space;
+
+ while (1) {
+ qsize = get_txq_buff_size(dpld, dev);
+ head = get_txq_head(dpld, dev);
+ tail = get_txq_tail(dpld, dev);
+ space = circ_get_space(qsize, head, tail);
+
+ mif_debug("%s: %s_TXQ{qsize:%u in:%u out:%u space:%u}\n",
+ ld->name, get_dev_name(dev), qsize, head, tail, space);
+
+ if (circ_valid(qsize, head, tail))
+ break;
+
+ cnt++;
+ mif_err("%s: ERR! invalid %s_TXQ{qsize:%d in:%d out:%d "
+ "space:%d}, count %d\n",
+ ld->name, get_dev_name(dev), qsize, head, tail,
+ space, cnt);
+ if (cnt >= MAX_RETRY_CNT) {
+ space = -EIO;
+ break;
+ }
+
+ udelay(100);
+ }
+
+ stat->buff = get_txq_buff(dpld, dev);
+ stat->qsize = qsize;
+ stat->in = head;
+ stat->out = tail;
+ stat->size = space;
+
+ return space;
+}
+
+/**
+ * write_ipc_to_txq
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @stat: pointer to an instance of circ_status structure
+ * @skb: pointer to an instance of sk_buff structure
+ *
+ * Must be invoked only when there is enough space in the TXQ.
+ */
+static void write_ipc_to_txq(struct dpram_link_device *dpld, int dev,
+ struct circ_status *stat, struct sk_buff *skb)
+{
+ struct link_device *ld = &dpld->ld;
+ u8 __iomem *buff = stat->buff;
+ u32 qsize = stat->qsize;
+ u32 in = stat->in;
+ u8 *src = skb->data;
+ u32 len = skb->len;
+ struct mif_irq_map map;
+
+ /* Write data to the TXQ */
+ if (unlikely(dpld->strict_io_access))
+ circ_write16_to_io(buff, src, qsize, in, len);
+ else
+ circ_write(buff, src, qsize, in, len);
+
+ /* Update new head (in) pointer */
+ set_txq_head(dpld, dev, circ_new_pointer(qsize, in, len));
+
+ /* Take a log for debugging */
+ if (dev == IPC_FMT) {
+#ifdef DEBUG_MODEM_IF
+ char tag[MIF_MAX_STR_LEN];
+ snprintf(tag, MIF_MAX_STR_LEN, "%s: MIF2CP", ld->mc->name);
+ pr_ipc(0, tag, src, (len > 32 ? 32 : len));
+#endif
+ set_dpram_map(dpld, &map);
+ mif_irq_log(ld->mc->msd, map, "ipc_write", sizeof("ipc_write"));
+ mif_ipc_log(MIF_IPC_AP2CP, ld->mc->msd, skb->data, skb->len);
+ }
+
+#ifdef DEBUG_MODEM_IF
+ /* Verify data written to the TXQ */
+ if (ld->aligned && memcmp16_to_io((buff + in), src, 4)) {
+ mif_err("%s: memcmp16_to_io fail\n", ld->name);
+ trigger_forced_cp_crash(dpld);
+ }
+#endif
+}
+
+/**
+ * xmit_ipc_msg
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Tries to transmit IPC messages in the skb_txq of @dev as many as possible.
+ *
+ * Returns total length of IPC messages transmitted or an error code.
+ */
+static int xmit_ipc_msg(struct dpram_link_device *dpld, int dev)
+{
+ struct link_device *ld = &dpld->ld;
struct sk_buff_head *txq = ld->skb_txq[dev];
+ struct sk_buff *skb;
+ unsigned long flags;
+ struct circ_status stat;
+ int space;
+ int copied = 0;
+
+ /* Acquire the spin lock for a TXQ */
+ spin_lock_irqsave(&dpld->tx_lock[dev], flags);
+
+ while (1) {
+ /* Get the size of free space in the TXQ */
+ space = get_txq_space(dpld, dev, &stat);
+ if (unlikely(space < 0)) {
+#ifdef DEBUG_MODEM_IF
+ /* Trigger a enforced CP crash */
+ trigger_forced_cp_crash(dpld);
+#endif
+ /* Empty out the TXQ */
+ reset_txq_circ(dpld, dev);
+ copied = -EIO;
+ break;
+ }
+
+ skb = skb_dequeue(txq);
+ if (unlikely(!skb))
+ break;
+
+ /* Check the free space size comparing with skb->len */
+ if (unlikely(space < skb->len)) {
+#ifdef DEBUG_MODEM_IF
+ struct mem_status mst;
+#endif
+ /* Set res_required flag for the "dev" */
+ atomic_set(&dpld->res_required[dev], 1);
+
+ /* Take the skb back to the skb_txq */
+ skb_queue_head(txq, skb);
+
+ mif_info("%s: <called by %pf> NOSPC in %s_TXQ"
+ "{qsize:%u in:%u out:%u}, free:%u < len:%u\n",
+ ld->name, CALLER, get_dev_name(dev),
+ stat.qsize, stat.in, stat.out, space, skb->len);
+#ifdef DEBUG_MODEM_IF
+ get_dpram_status(dpld, TX, &mst);
+ print_circ_status(ld, dev, &mst);
+#endif
+ copied = -ENOSPC;
+ break;
+ }
+
+ /* TX only when there is enough space in the TXQ */
+ write_ipc_to_txq(dpld, dev, &stat, skb);
+ copied += skb->len;
+ dev_kfree_skb_any(skb);
+ }
+
+ /* Release the spin lock */
+ spin_unlock_irqrestore(&dpld->tx_lock[dev], flags);
+
+ return copied;
+}
+
+/**
+ * wait_for_res_ack
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * 1) Sends an REQ_ACK interrupt for @dev to CP.
+ * 2) Waits for the corresponding RES_ACK for @dev from CP.
+ *
+ * Returns the return value from wait_for_completion_interruptible_timeout().
+ */
+static int wait_for_res_ack(struct dpram_link_device *dpld, int dev)
+{
+ struct link_device *ld = &dpld->ld;
+ struct completion *cmpl = &dpld->req_ack_cmpl[dev];
+ unsigned long timeout = msecs_to_jiffies(dpld->res_ack_wait_timeout);
int ret;
u16 mask;
- skb_queue_tail(txq, skb);
- if (txq->qlen > 1024) {
- mif_debug("%s: %s txq->qlen %d > 1024\n",
- ld->name, get_dev_name(dev), txq->qlen);
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: send %s_REQ_ACK\n", ld->name, get_dev_name(dev));
+#endif
+
+ mask = get_mask_req_ack(dpld, dev);
+ send_int2cp(dpld, INT_NON_CMD(mask));
+
+ ret = wait_for_completion_interruptible_timeout(cmpl, timeout);
+ /* ret == 0 on timeout, ret < 0 if interrupted */
+ if (ret < 0) {
+ mif_info("%s: %s: wait_for_completion interrupted! (ret %d)\n",
+ ld->name, get_dev_name(dev), ret);
+ goto exit;
}
- if (dpld->dp_type == CP_IDPRAM) {
- if (dpram_wake_up(dpld) < 0) {
- trigger_force_cp_crash(dpld);
- return;
+ if (ret == 0) {
+ struct mem_status mst;
+ get_dpram_status(dpld, TX, &mst);
+
+ mif_info("%s: wait_for_completion TIMEOUT! (no %s_RES_ACK)\n",
+ ld->name, get_dev_name(dev));
+
+ /*
+ ** The TXQ must be checked whether or not it is empty, because
+ ** an interrupt mask can be overwritten by the next interrupt.
+ */
+ if (mst.head[dev][TX] == mst.tail[dev][TX]) {
+ ret = get_txq_buff_size(dpld, dev);
+#ifdef DEBUG_MODEM_IF
+ mif_info("%s: %s_TXQ has been emptied\n",
+ ld->name, get_dev_name(dev));
+ print_circ_status(ld, dev, &mst);
+#endif
}
}
- if (!dpram_ipc_active(dpld))
- goto exit;
+exit:
+ return ret;
+}
+
+/**
+ * process_res_ack
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * 1) Tries to transmit IPC messages in the skb_txq by invoking xmit_ipc_msg()
+ * function.
+ * 2) Sends an interrupt to CP if there is no error from xmit_ipc_msg().
+ * 3) Restarts DPRAM flow control if xmit_ipc_msg() returns -ENOSPC.
+ *
+ * Returns the return value from xmit_ipc_msg().
+ */
+static int process_res_ack(struct dpram_link_device *dpld, int dev)
+{
+ int ret;
+ u16 mask;
+
+ ret = xmit_ipc_msg(dpld, dev);
+ if (ret > 0) {
+ mask = get_mask_send(dpld, dev);
+ send_int2cp(dpld, INT_NON_CMD(mask));
+ get_dpram_status(dpld, TX, msq_get_free_slot(&dpld->stat_list));
+ }
+
+ if (ret >= 0)
+ atomic_set(&dpld->res_required[dev], 0);
+
+ return ret;
+}
+
+/**
+ * fmt_tx_work: performs TX for FMT IPC device under DPRAM flow control
+ * @work: pointer to an instance of the work_struct structure
+ *
+ * 1) Starts waiting for RES_ACK of FMT IPC device.
+ * 2) Returns immediately if the wait is interrupted.
+ * 3) Restarts DPRAM flow control if there is a timeout from the wait.
+ * 4) Otherwise, it performs processing RES_ACK for FMT IPC device.
+ */
+static void fmt_tx_work(struct work_struct *work)
+{
+ struct link_device *ld;
+ struct dpram_link_device *dpld;
+ unsigned long delay = 0;
+ int ret;
+
+ ld = container_of(work, struct link_device, fmt_tx_dwork.work);
+ dpld = to_dpram_link_device(ld);
+
+ ret = wait_for_res_ack(dpld, IPC_FMT);
+ /* ret < 0 if interrupted */
+ if (ret < 0)
+ return;
+
+ /* ret == 0 on timeout */
+ if (ret == 0) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_FMT], 0);
+ return;
+ }
+
+ ret = process_res_ack(dpld, IPC_FMT);
+ if (ret >= 0) {
+ dpram_allow_sleep(dpld);
+ return;
+ }
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC)
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_FMT], delay);
+}
+
+/**
+ * raw_tx_work: performs TX for RAW IPC device under DPRAM flow control.
+ * @work: pointer to an instance of the work_struct structure
+ *
+ * 1) Starts waiting for RES_ACK of RAW IPC device.
+ * 2) Returns immediately if the wait is interrupted.
+ * 3) Restarts DPRAM flow control if there is a timeout from the wait.
+ * 4) Otherwise, it performs processing RES_ACK for RAW IPC device.
+ */
+static void raw_tx_work(struct work_struct *work)
+{
+ struct link_device *ld;
+ struct dpram_link_device *dpld;
+ unsigned long delay = 0;
+ int ret;
+
+ ld = container_of(work, struct link_device, raw_tx_dwork.work);
+ dpld = to_dpram_link_device(ld);
+
+ ret = wait_for_res_ack(dpld, IPC_RAW);
+ /* ret < 0 if interrupted */
+ if (ret < 0)
+ return;
+
+ /* ret == 0 on timeout */
+ if (ret == 0) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_RAW], 0);
+ return;
+ }
+
+ ret = process_res_ack(dpld, IPC_RAW);
+ if (ret >= 0) {
+ dpram_allow_sleep(dpld);
+ mif_netif_wake(ld);
+ return;
+ }
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC)
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_RAW], delay);
+}
+
+/**
+ * rfs_tx_work: performs TX for RFS IPC device under DPRAM flow control
+ * @work: pointer to an instance of the work_struct structure
+ *
+ * 1) Starts waiting for RES_ACK of RFS IPC device.
+ * 2) Returns immediately if the wait is interrupted.
+ * 3) Restarts DPRAM flow control if there is a timeout from the wait.
+ * 4) Otherwise, it performs processing RES_ACK for RFS IPC device.
+ */
+static void rfs_tx_work(struct work_struct *work)
+{
+ struct link_device *ld;
+ struct dpram_link_device *dpld;
+ unsigned long delay = 0;
+ int ret;
+
+ ld = container_of(work, struct link_device, rfs_tx_dwork.work);
+ dpld = to_dpram_link_device(ld);
+
+ ret = wait_for_res_ack(dpld, IPC_RFS);
+ /* ret < 0 if interrupted */
+ if (ret < 0)
+ return;
+
+ /* ret == 0 on timeout */
+ if (ret == 0) {
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_RFS], 0);
+ return;
+ }
+
+ ret = process_res_ack(dpld, IPC_RFS);
+ if (ret >= 0) {
+ dpram_allow_sleep(dpld);
+ return;
+ }
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC)
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[IPC_RFS], delay);
+}
+
+/**
+ * dpram_send_ipc
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * 1) Tries to transmit IPC messages in the skb_txq by invoking xmit_ipc_msg()
+ * function.
+ * 2) Sends an interrupt to CP if there is no error from xmit_ipc_msg().
+ * 3) Starts DPRAM flow control if xmit_ipc_msg() returns -ENOSPC.
+ */
+static int dpram_send_ipc(struct dpram_link_device *dpld, int dev)
+{
+ struct link_device *ld = &dpld->ld;
+ int ret;
+ u16 mask;
if (atomic_read(&dpld->res_required[dev]) > 0) {
- mif_debug("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev));
+ mif_info("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev));
+ return 0;
+ }
+
+ if (dpram_wake_up(dpld) < 0) {
+ trigger_forced_cp_crash(dpld);
+ return -EIO;
+ }
+
+ if (!ipc_active(dpld)) {
+ mif_info("%s: IPC is NOT active\n", ld->name);
+ ret = -EIO;
goto exit;
}
- ret = dpram_try_ipc_tx(dpld, dev);
- if (ret > 0) {
+ ret = xmit_ipc_msg(dpld, dev);
+ if (likely(ret > 0)) {
mask = get_mask_send(dpld, dev);
- send_intr(dpld, INT_NON_CMD(mask));
- } else if (ret == -ENOSPC) {
- mask = get_mask_req_ack(dpld, dev);
- send_intr(dpld, INT_NON_CMD(mask));
- mif_info("%s: Send REQ_ACK 0x%04X\n", ld->name, mask);
- } else {
- mif_info("%s: dpram_try_ipc_tx fail (err %d)\n", ld->name, ret);
+ send_int2cp(dpld, INT_NON_CMD(mask));
+ get_dpram_status(dpld, TX, msq_get_free_slot(&dpld->stat_list));
+ goto exit;
+ }
+
+ /* If there was no TX, just exit */
+ if (ret == 0)
+ goto exit;
+
+ /* At this point, ret < 0 */
+ if (ret == -ENOSPC) {
+ /* Prohibit DPRAM from sleeping until the TXQ buffer is empty */
+ if (dpram_wake_up(dpld) < 0) {
+ trigger_forced_cp_crash(dpld);
+ goto exit;
+ }
+
+ /*----------------------------------------------------*/
+ /* dpld->res_required[dev] was set in xmit_ipc_msg(). */
+ /*----------------------------------------------------*/
+
+ if (dev == IPC_RAW)
+ mif_netif_stop(ld);
+
+ queue_delayed_work(ld->tx_wq, ld->tx_dwork[dev], 0);
}
exit:
- if (dpld->dp_type == CP_IDPRAM)
- dpram_allow_sleep(dpld);
+ dpram_allow_sleep(dpld);
+ return ret;
+}
+
+/**
+ * pm_tx_work: performs TX while DPRAM PM is locked
+ * @work: pointer to an instance of the work_struct structure
+ */
+static void pm_tx_work(struct work_struct *work)
+{
+ struct idpram_pm_data *pm_data;
+ struct idpram_pm_op *pm_op;
+ struct dpram_link_device *dpld;
+ struct link_device *ld;
+ struct workqueue_struct *pm_wq = system_nrt_wq;
+ int i;
+ int ret;
+ unsigned long delay = 0;
+
+ pm_data = container_of(work, struct idpram_pm_data, tx_dwork.work);
+ dpld = container_of(pm_data, struct dpram_link_device, pm_data);
+ ld = &dpld->ld;
+ pm_op = dpld->pm_op;
+
+ if (pm_op->locked(dpld)) {
+ queue_delayed_work(pm_wq, &pm_data->tx_dwork, delay);
+ return;
+ }
+
+ /* Here, PM is not locked. */
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ ret = dpram_send_ipc(dpld, i);
+ if (ret < 0) {
+ struct io_device *iod = dpld->iod[i];
+ mif_err("%s->%s: ERR! dpram_send_ipc fail (err %d)\n",
+ iod->name, ld->name, ret);
+ }
+ }
+}
+
+/**
+ * dpram_try_send_ipc
+ * @dpld: pointer to an instance of dpram_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @iod: pointer to an instance of the io_device structure
+ * @skb: pointer to an skb that will be transmitted
+ *
+ * 1) Enqueues an skb to the skb_txq for @dev in the link device instance.
+ * 2) Tries to transmit IPC messages in the skb_txq by invoking xmit_ipc_msg()
+ * function.
+ * 3) Sends an interrupt to CP if there is no error from xmit_ipc_msg().
+ * 4) Starts DPRAM flow control if xmit_ipc_msg() returns -ENOSPC.
+ */
+static void dpram_try_send_ipc(struct dpram_link_device *dpld, int dev,
+ struct io_device *iod, struct sk_buff *skb)
+{
+ struct link_device *ld = &dpld->ld;
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ struct idpram_pm_op *pm_op = dpld->pm_op;
+ struct workqueue_struct *pm_wq = system_nrt_wq;
+ unsigned long delay = msecs_to_jiffies(10);
+ struct sk_buff_head *txq = ld->skb_txq[dev];
+ int ret;
+
+ if (unlikely(txq->qlen >= MAX_SKB_TXQ_DEPTH)) {
+ mif_info("%s: %s txq->qlen %d >= %d\n", ld->name,
+ get_dev_name(dev), txq->qlen, MAX_SKB_TXQ_DEPTH);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ skb_queue_tail(txq, skb);
+
+ if (pm_op && pm_op->locked) {
+ if (pm_op->locked(dpld)) {
+ queue_delayed_work(pm_wq, &pm_data->tx_dwork, delay);
+ return;
+ }
+
+ /* Here, PM is not locked. */
+ if (work_pending(&pm_data->tx_dwork.work))
+ cancel_delayed_work_sync(&pm_data->tx_dwork);
+ }
+
+ ret = dpram_send_ipc(dpld, dev);
+ if (ret < 0) {
+ mif_err("%s->%s: ERR! dpram_send_ipc fail (err %d)\n",
+ iod->name, ld->name, ret);
+ }
}
static int dpram_send_cp_binary(struct link_device *ld, struct sk_buff *skb)
{
struct dpram_link_device *dpld = to_dpram_link_device(ld);
- if (dpld->ext_op && dpld->ext_op->download_binary)
- return dpld->ext_op->download_binary(dpld, skb);
+ if (dpld->ext_op && dpld->ext_op->xmit_binary)
+ return dpld->ext_op->xmit_binary(dpld, skb);
else
return -ENODEV;
}
+/**
+ * dpram_send
+ * @ld: pointer to an instance of the link_device structure
+ * @iod: pointer to an instance of the io_device structure
+ * @skb: pointer to an skb that will be transmitted
+ *
+ * Returns the length of data transmitted or an error code.
+ *
+ * Normal call flow for an IPC message:
+ * dpram_try_send_ipc -> dpram_send_ipc -> xmit_ipc_msg -> write_ipc_to_txq
+ *
+ * Call flow on PM lock in a DPRAM IPC TXQ:
+ * dpram_try_send_ipc ,,, queue_delayed_work
+ * => pm_tx_work -> dpram_send_ipc -> xmit_ipc_msg -> write_ipc_to_txq
+ *
+ * Call flow on congestion in a DPRAM IPC TXQ:
+ * dpram_try_send_ipc -> xmit_ipc_msg ,,, queue_delayed_work
+ * => xxx_tx_work -> wait_for_res_ack
+ * => msg_handler
+ * => process_res_ack -> xmit_ipc_msg (,,, queue_delayed_work ...)
+ */
static int dpram_send(struct link_device *ld, struct io_device *iod,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
- enum dev_format dev = iod->format;
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ int dev = iod->format;
int len = skb->len;
switch (dev) {
@@ -1379,7 +2266,7 @@ static int dpram_send(struct link_device *ld, struct io_device *iod,
case IPC_RAW:
case IPC_RFS:
if (likely(ld->mode == LINK_MODE_IPC)) {
- dpram_send_ipc(ld, dev, iod, skb);
+ dpram_try_send_ipc(dpld, dev, iod, skb);
} else {
mif_info("%s: ld->mode != LINK_MODE_IPC\n", ld->name);
dev_kfree_skb_any(skb);
@@ -1396,23 +2283,45 @@ static int dpram_send(struct link_device *ld, struct io_device *iod,
}
}
-static int dpram_force_dump(struct link_device *ld, struct io_device *iod)
+static int dpram_xmit_boot(struct link_device *ld, struct io_device *iod,
+ unsigned long arg)
+{
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+
+ if (dpld->ext_op && dpld->ext_op->xmit_boot)
+ return dpld->ext_op->xmit_boot(dpld, arg);
+ else
+ return -ENODEV;
+}
+
+static int dpram_set_dload_magic(struct link_device *ld, struct io_device *iod)
{
struct dpram_link_device *dpld = to_dpram_link_device(ld);
- trigger_force_cp_crash(dpld);
+
+ ld->mode = LINK_MODE_DLOAD;
+
+ mif_err("%s: magic = 0x%08X\n", ld->name, DP_MAGIC_DMDL);
+ iowrite32(DP_MAGIC_DMDL, dpld->dl_map.magic);
+
return 0;
}
-static void dpram_dump_memory(struct link_device *ld, char *buff)
+static int dpram_dload_firmware(struct link_device *ld, struct io_device *iod,
+ unsigned long arg)
{
struct dpram_link_device *dpld = to_dpram_link_device(ld);
- u8 __iomem *base = dpld->dpctl->dp_base;
- u32 size = dpld->dpctl->dp_size;
- if (dpld->dp_type == CP_IDPRAM)
- dpram_wake_up(dpld);
+ if (dpld->ext_op && dpld->ext_op->firm_update)
+ return dpld->ext_op->firm_update(dpld, arg);
+ else
+ return -ENODEV;
+}
- memcpy(buff, base, size);
+static int dpram_force_dump(struct link_device *ld, struct io_device *iod)
+{
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ trigger_forced_cp_crash(dpld);
+ return 0;
}
static int dpram_dump_start(struct link_device *ld, struct io_device *iod)
@@ -1431,13 +2340,24 @@ static int dpram_dump_update(struct link_device *ld, struct io_device *iod,
struct dpram_link_device *dpld = to_dpram_link_device(ld);
if (dpld->ext_op && dpld->ext_op->dump_update)
- return dpld->ext_op->dump_update(dpld, (void *)arg);
+ return dpld->ext_op->dump_update(dpld, arg);
+ else
+ return -ENODEV;
+}
+
+static int dpram_dump_finish(struct link_device *ld, struct io_device *iod,
+ unsigned long arg)
+{
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+
+ if (dpld->ext_op && dpld->ext_op->dump_finish)
+ return dpld->ext_op->dump_finish(dpld, arg);
else
return -ENODEV;
}
static int dpram_ioctl(struct link_device *ld, struct io_device *iod,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct dpram_link_device *dpld = to_dpram_link_device(ld);
int err = 0;
@@ -1447,17 +2367,21 @@ static int dpram_ioctl(struct link_device *ld, struct io_device *iod,
switch (cmd) {
case IOCTL_DPRAM_INIT_STATUS:
mif_debug("%s: get dpram init status\n", ld->name);
- return dpld->dpram_init_status;
+ return dpld->init_status;
- default:
- if (dpld->ext_ioctl) {
- err = dpld->ext_ioctl(dpld, iod, cmd, arg);
- } else {
- mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd);
- err = -EINVAL;
- }
+ case IOCTL_MIF_DPRAM_DUMP:
+ if (copy_to_user((void __user *)arg, &dpld->size, sizeof(u32)))
+ return -EFAULT;
+ capture_dpram_snapshot(ld, iod);
break;
+
+ default:
+ if (dpld->ext_ioctl)
+ return dpld->ext_ioctl(dpld, iod, cmd, arg);
+
+ mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd);
+ return -EINVAL;
}
return err;
@@ -1468,9 +2392,9 @@ static void dpram_remap_std_16k_region(struct dpram_link_device *dpld)
struct dpram_ipc_16k_map *dpram_map;
struct dpram_ipc_device *dev;
- dpram_map = (struct dpram_ipc_16k_map *)dpld->dp_base;
+ dpram_map = (struct dpram_ipc_16k_map *)dpld->base;
- /* magic code and access enable fields */
+ /* "magic code" and "access enable" fields */
dpld->ipc_map.magic = (u16 __iomem *)&dpram_map->magic;
dpld->ipc_map.access = (u16 __iomem *)&dpram_map->access;
@@ -1519,167 +2443,201 @@ static void dpram_remap_std_16k_region(struct dpram_link_device *dpld)
dpld->ipc_map.mbx_ap2cp = (u16 __iomem *)&dpram_map->mbx_ap2cp;
}
-static int dpram_table_init(struct dpram_link_device *dpld)
+static int dpram_init_boot_map(struct dpram_link_device *dpld)
{
- struct link_device *ld = &dpld->ld;
- u8 __iomem *dp_base;
- int i;
+ u8 __iomem *dp_base = dpld->base;
+ u32 magic_size = DP_DLOAD_MAGIC_SIZE;
+ u32 mbx_size = DP_MBX_SET_SIZE;
- if (!dpld->dp_base) {
- mif_info("%s: ERR! dpld->dp_base == NULL\n", ld->name);
- return -EINVAL;
- }
- dp_base = dpld->dp_base;
-
- /* Map for IPC */
- if (dpld->dpctl->ipc_map) {
- memcpy(&dpld->ipc_map, dpld->dpctl->ipc_map,
- sizeof(struct dpram_ipc_map));
- } else {
- if (dpld->dp_size == DPRAM_SIZE_16KB)
- dpram_remap_std_16k_region(dpld);
- else
- return -EINVAL;
- }
-
- dpld->magic = dpld->ipc_map.magic;
- dpld->access = dpld->ipc_map.access;
- for (i = 0; i < dpld->max_ipc_dev; i++)
- dpld->dev[i] = &dpld->ipc_map.dev[i];
- dpld->mbx2ap = dpld->ipc_map.mbx_cp2ap;
- dpld->mbx2cp = dpld->ipc_map.mbx_ap2cp;
-
- /* Map for booting */
if (dpld->ext_op && dpld->ext_op->init_boot_map) {
dpld->ext_op->init_boot_map(dpld);
} else {
dpld->bt_map.magic = (u32 *)(dp_base);
- dpld->bt_map.buff = (u8 *)(dp_base + DP_BOOT_BUFF_OFFSET);
- dpld->bt_map.size = dpld->dp_size - 8;
+ dpld->bt_map.buff = (u8 *)(dp_base + magic_size);
+ dpld->bt_map.space = dpld->size - (magic_size + mbx_size);
}
- /* Map for download (FOTA, UDL, etc.) */
+ return 0;
+}
+
+static int dpram_init_dload_map(struct dpram_link_device *dpld)
+{
+ u8 __iomem *dp_base = dpld->base;
+ u32 magic_size = DP_DLOAD_MAGIC_SIZE;
+ u32 mbx_size = DP_MBX_SET_SIZE;
+
if (dpld->ext_op && dpld->ext_op->init_dl_map) {
dpld->ext_op->init_dl_map(dpld);
} else {
dpld->dl_map.magic = (u32 *)(dp_base);
- dpld->dl_map.buff = (u8 *)(dp_base + DP_DLOAD_BUFF_OFFSET);
+ dpld->dl_map.buff = (u8 *)(dp_base + magic_size);
+ dpld->dl_map.space = dpld->size - (magic_size + mbx_size);
}
- /* Map for upload mode */
+ return 0;
+}
+
+static int dpram_init_uload_map(struct dpram_link_device *dpld)
+{
+ u8 __iomem *dp_base = dpld->base;
+ u32 magic_size = DP_DLOAD_MAGIC_SIZE;
+ u32 mbx_size = DP_MBX_SET_SIZE;
+
if (dpld->ext_op && dpld->ext_op->init_ul_map) {
dpld->ext_op->init_ul_map(dpld);
} else {
dpld->ul_map.magic = (u32 *)(dp_base);
dpld->ul_map.buff = (u8 *)(dp_base + DP_ULOAD_BUFF_OFFSET);
+ dpld->ul_map.space = dpld->size - (magic_size + mbx_size);
}
return 0;
}
+static int dpram_init_ipc_map(struct dpram_link_device *dpld)
+{
+ int i;
+ struct link_device *ld = &dpld->ld;
+
+ if (dpld->ext_op && dpld->ext_op->init_ipc_map) {
+ dpld->ext_op->init_ipc_map(dpld);
+ } else if (dpld->dpram->ipc_map) {
+ memcpy(&dpld->ipc_map, dpld->dpram->ipc_map,
+ sizeof(struct dpram_ipc_map));
+ } else {
+ if (dpld->size == DPRAM_SIZE_16KB)
+ dpram_remap_std_16k_region(dpld);
+ else
+ return -EINVAL;
+ }
+
+ dpld->magic = dpld->ipc_map.magic;
+ dpld->access = dpld->ipc_map.access;
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ dpld->dev[i] = &dpld->ipc_map.dev[i];
+ dpld->mbx2ap = dpld->ipc_map.mbx_cp2ap;
+ dpld->mbx2cp = dpld->ipc_map.mbx_ap2cp;
+
+ return 0;
+}
+
static void dpram_setup_common_op(struct dpram_link_device *dpld)
{
- dpld->clear_intr = clear_intr;
- dpld->recv_intr = recv_intr;
- dpld->send_intr = send_intr;
+ dpld->recv_intr = recv_int2ap;
+ dpld->send_intr = send_int2cp;
dpld->get_magic = get_magic;
dpld->set_magic = set_magic;
dpld->get_access = get_access;
dpld->set_access = set_access;
- dpld->get_tx_head = get_tx_head;
- dpld->get_tx_tail = get_tx_tail;
- dpld->set_tx_head = set_tx_head;
- dpld->set_tx_tail = set_tx_tail;
- dpld->get_tx_buff = get_tx_buff;
- dpld->get_tx_buff_size = get_tx_buff_size;
- dpld->get_rx_head = get_rx_head;
- dpld->get_rx_tail = get_rx_tail;
- dpld->set_rx_head = set_rx_head;
- dpld->set_rx_tail = set_rx_tail;
- dpld->get_rx_buff = get_rx_buff;
- dpld->get_rx_buff_size = get_rx_buff_size;
+ dpld->get_txq_head = get_txq_head;
+ dpld->get_txq_tail = get_txq_tail;
+ dpld->set_txq_head = set_txq_head;
+ dpld->set_txq_tail = set_txq_tail;
+ dpld->get_txq_buff = get_txq_buff;
+ dpld->get_txq_buff_size = get_txq_buff_size;
+ dpld->get_rxq_head = get_rxq_head;
+ dpld->get_rxq_tail = get_rxq_tail;
+ dpld->set_rxq_head = set_rxq_head;
+ dpld->set_rxq_tail = set_rxq_tail;
+ dpld->get_rxq_buff = get_rxq_buff;
+ dpld->get_rxq_buff_size = get_rxq_buff_size;
dpld->get_mask_req_ack = get_mask_req_ack;
dpld->get_mask_res_ack = get_mask_res_ack;
dpld->get_mask_send = get_mask_send;
- dpld->ipc_rx_handler = dpram_ipc_rx;
-}
-
-static int dpram_link_init(struct link_device *ld, struct io_device *iod)
-{
- return 0;
+ dpld->get_dpram_status = get_dpram_status;
+ dpld->ipc_rx_handler = cmd_msg_handler;
+ dpld->reset_dpram_ipc = reset_dpram_ipc;
}
static void dpram_link_terminate(struct link_device *ld, struct io_device *iod)
{
+ if (iod->format == IPC_FMT && ld->mode == LINK_MODE_IPC) {
+ if (!atomic_read(&iod->opened)) {
+ ld->mode = LINK_MODE_OFFLINE;
+ mif_err("%s: %s: link mode is changed: IPC->OFFLINE\n",
+ iod->name, ld->name);
+ }
+ }
+
return;
}
struct link_device *dpram_create_link_device(struct platform_device *pdev)
{
- struct modem_data *mdm_data = NULL;
struct dpram_link_device *dpld = NULL;
struct link_device *ld = NULL;
+ struct modem_data *modem = NULL;
+ struct modemlink_dpram_data *dpram = NULL;
struct resource *res = NULL;
resource_size_t res_size;
- struct modemlink_dpram_control *dpctl = NULL;
- unsigned long task_data;
int ret = 0;
int i = 0;
- int bsize;
- int qsize;
- /* Get the platform data */
- mdm_data = (struct modem_data *)pdev->dev.platform_data;
- if (!mdm_data) {
- mif_info("ERR! mdm_data == NULL\n");
+ /*
+ ** Alloc an instance of dpram_link_device structure
+ */
+ dpld = kzalloc(sizeof(struct dpram_link_device), GFP_KERNEL);
+ if (!dpld) {
+ mif_err("ERR! kzalloc dpld fail\n");
goto err;
}
- mif_info("modem = %s\n", mdm_data->name);
- mif_info("link device = %s\n", mdm_data->link_name);
+ ld = &dpld->ld;
- if (!mdm_data->dpram_ctl) {
- mif_info("ERR! mdm_data->dpram_ctl == NULL\n");
+ /*
+ ** Get the modem (platform) data
+ */
+ modem = (struct modem_data *)pdev->dev.platform_data;
+ if (!modem) {
+ mif_err("ERR! modem == NULL\n");
goto err;
}
- dpctl = mdm_data->dpram_ctl;
-
- /* Alloc DPRAM link device structure */
- dpld = kzalloc(sizeof(struct dpram_link_device), GFP_KERNEL);
- if (!dpld) {
- mif_info("ERR! kzalloc dpld fail\n");
+ mif_info("modem = %s\n", modem->name);
+ mif_info("link device = %s\n", modem->link_name);
+
+ /*
+ ** Retrieve modem data and DPRAM control data from the modem data
+ */
+ ld->mdm_data = modem;
+ ld->name = modem->link_name;
+ ld->ipc_version = modem->ipc_version;
+
+ if (!modem->dpram) {
+ mif_err("ERR! no modem->dpram\n");
goto err;
}
- ld = &dpld->ld;
+ dpram = modem->dpram;
- /* Retrieve modem data and DPRAM control data from the modem data */
- ld->mdm_data = mdm_data;
- ld->name = mdm_data->link_name;
- ld->ipc_version = mdm_data->ipc_version;
+ dpld->dpram = dpram;
+ dpld->type = dpram->type;
+ dpld->ap = dpram->ap;
+ dpld->strict_io_access = dpram->strict_io_access;
- /* Retrieve the most basic data for IPC from the modem data */
- dpld->dpctl = dpctl;
- dpld->dp_type = dpctl->dp_type;
-
- if (mdm_data->ipc_version < SIPC_VER_50) {
- if (!dpctl->max_ipc_dev) {
- mif_info("ERR! no max_ipc_dev\n");
+ if (ld->ipc_version < SIPC_VER_50) {
+ if (!modem->max_ipc_dev) {
+ mif_err("%s: ERR! no max_ipc_dev\n", ld->name);
goto err;
}
- ld->aligned = dpctl->aligned;
- dpld->max_ipc_dev = dpctl->max_ipc_dev;
+ ld->aligned = dpram->aligned;
+ ld->max_ipc_dev = modem->max_ipc_dev;
} else {
ld->aligned = 1;
- dpld->max_ipc_dev = MAX_SIPC5_DEV;
+ ld->max_ipc_dev = MAX_SIPC5_DEV;
}
- /* Set attributes as a link device */
- ld->init_comm = dpram_link_init;
+ /*
+ ** Set attributes as a link device
+ */
ld->terminate_comm = dpram_link_terminate;
ld->send = dpram_send;
+ ld->xmit_boot = dpram_xmit_boot;
+ ld->dload_start = dpram_set_dload_magic;
+ ld->firm_update = dpram_dload_firmware;
ld->force_dump = dpram_force_dump;
ld->dump_start = dpram_dump_start;
ld->dump_update = dpram_dump_update;
+ ld->dump_finish = dpram_dump_finish;
+ /* IOCTL extension */
ld->ioctl = dpram_ioctl;
INIT_LIST_HEAD(&ld->list);
@@ -1691,129 +2649,217 @@ struct link_device *dpram_create_link_device(struct platform_device *pdev)
ld->skb_txq[IPC_RAW] = &ld->sk_raw_tx_q;
ld->skb_txq[IPC_RFS] = &ld->sk_rfs_tx_q;
- /* Set up function pointers */
+ skb_queue_head_init(&ld->sk_fmt_rx_q);
+ skb_queue_head_init(&ld->sk_raw_rx_q);
+ skb_queue_head_init(&ld->sk_rfs_rx_q);
+ ld->skb_rxq[IPC_FMT] = &ld->sk_fmt_rx_q;
+ ld->skb_rxq[IPC_RAW] = &ld->sk_raw_rx_q;
+ ld->skb_rxq[IPC_RFS] = &ld->sk_rfs_rx_q;
+
+ init_completion(&ld->init_cmpl);
+ init_completion(&ld->pif_cmpl);
+
+ /*
+ ** Set up function pointers
+ */
dpram_setup_common_op(dpld);
- dpld->dpram_dump = dpram_dump_memory;
- dpld->ext_op = dpram_get_ext_op(mdm_data->modem_type);
- if (dpld->ext_op && dpld->ext_op->ioctl)
- dpld->ext_ioctl = dpld->ext_op->ioctl;
-
- /* Retrieve DPRAM resource */
- if (!dpctl->dp_base) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dpld->ext_op = dpram_get_ext_op(modem->modem_type);
+ if (dpld->ext_op) {
+ if (dpld->ext_op->ioctl)
+ dpld->ext_ioctl = dpld->ext_op->ioctl;
+
+ if (dpld->ext_op->wakeup && dpld->ext_op->sleep)
+ dpld->need_wake_up = true;
+ }
+
+ /*
+ ** Retrieve DPRAM resource
+ */
+ if (!dpram->base) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ STR_DPRAM_BASE);
if (!res) {
- mif_info("%s: ERR! platform_get_resource fail\n",
+ mif_err("%s: ERR! no DPRAM resource\n", ld->name);
+ goto err;
+ }
+ res_size = resource_size(res);
+
+ dpram->base = ioremap_nocache(res->start, res_size);
+ if (!dpram->base) {
+ mif_err("%s: ERR! ioremap_nocache for BASE fail\n",
ld->name);
goto err;
}
+ dpram->size = res_size;
+ }
+ dpld->base = dpram->base;
+ dpld->size = dpram->size;
+
+ mif_info("%s: type %d, aligned %d, base 0x%08X, size %d\n",
+ ld->name, dpld->type, ld->aligned, (int)dpld->base, dpld->size);
+
+ /*
+ ** Retrieve DPRAM SFR resource if exists
+ */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ STR_DPRAM_SFR_BASE);
+ if (res) {
res_size = resource_size(res);
+ dpld->sfr_base = ioremap_nocache(res->start, res_size);
+ if (!dpld->sfr_base) {
+ mif_err("%s: ERR! ioremap_nocache for SFR fail\n",
+ ld->name);
+ goto err;
+ }
+ }
+
+ /*
+ ** Initialize DPRAM maps (physical map -> logical map)
+ */
+ ret = dpram_init_boot_map(dpld);
+ if (ret < 0) {
+ mif_err("%s: ERR! dpram_init_boot_map fail (err %d)\n",
+ ld->name, ret);
+ goto err;
+ }
- dpctl->dp_base = ioremap_nocache(res->start, res_size);
- dpctl->dp_size = res_size;
+ ret = dpram_init_dload_map(dpld);
+ if (ret < 0) {
+ mif_err("%s: ERR! dpram_init_dload_map fail (err %d)\n",
+ ld->name, ret);
+ goto err;
}
- dpld->dp_base = dpctl->dp_base;
- dpld->dp_size = dpctl->dp_size;
- mif_info("%s: dp_type %d, aligned %d, dp_base 0x%08X, dp_size %d\n",
- ld->name, dpld->dp_type, ld->aligned, (int)dpld->dp_base,
- dpld->dp_size);
+ ret = dpram_init_uload_map(dpld);
+ if (ret < 0) {
+ mif_err("%s: ERR! dpram_init_uload_map fail (err %d)\n",
+ ld->name, ret);
+ goto err;
+ }
- /* Initialize DPRAM map (physical map -> logical map) */
- ret = dpram_table_init(dpld);
+ ret = dpram_init_ipc_map(dpld);
if (ret < 0) {
- mif_info("%s: ERR! dpram_table_init fail (err %d)\n",
+ mif_err("%s: ERR! dpram_init_ipc_map fail (err %d)\n",
ld->name, ret);
goto err;
}
+ if (dpram->res_ack_wait_timeout > 0)
+ dpld->res_ack_wait_timeout = dpram->res_ack_wait_timeout;
+ else
+ dpld->res_ack_wait_timeout = RES_ACK_WAIT_TIMEOUT;
+
/* Disable IPC */
- set_magic(dpld, 0);
- set_access(dpld, 0);
- dpld->dpram_init_status = DPRAM_INIT_STATE_NONE;
+ if (!dpram->disabled) {
+ set_magic(dpld, 0);
+ set_access(dpld, 0);
+ }
+ dpld->init_status = DPRAM_INIT_STATE_NONE;
- /* Initialize locks, completions, and bottom halves */
- snprintf(dpld->wlock_name, DP_MAX_NAME_LEN, "%s_wlock", ld->name);
+ /*
+ ** Initialize locks, completions, and bottom halves
+ */
+ snprintf(dpld->wlock_name, MIF_MAX_NAME_LEN, "%s_wlock", ld->name);
wake_lock_init(&dpld->wlock, WAKE_LOCK_SUSPEND, dpld->wlock_name);
- init_completion(&dpld->dpram_init_cmd);
- init_completion(&dpld->modem_pif_init_done);
- init_completion(&dpld->udl_start_complete);
- init_completion(&dpld->udl_cmd_complete);
- init_completion(&dpld->dump_start_complete);
- init_completion(&dpld->dump_recv_done);
-
- task_data = (unsigned long)dpld;
- tasklet_init(&dpld->rx_tsk, dpram_ipc_rx_task, task_data);
-
- /* Prepare SKB queue head for RX processing */
- for (i = 0; i < dpld->max_ipc_dev; i++)
- skb_queue_head_init(&dpld->skb_rxq[i]);
-
- /* Prepare RXB queue */
- qsize = DPRAM_MAX_RXBQ_SIZE;
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- bsize = rxbq_get_page_size(get_rx_buff_size(dpld, i));
- dpld->rxbq[i].size = qsize;
- dpld->rxbq[i].in = 0;
- dpld->rxbq[i].out = 0;
- dpld->rxbq[i].rxb = rxbq_create_pool(bsize, qsize);
- if (!dpld->rxbq[i].rxb) {
- mif_info("%s: ERR! %s rxbq_create_pool fail\n",
- ld->name, get_dev_name(i));
- goto err;
- }
- mif_info("%s: %s rxbq_pool created (bsize:%d, qsize:%d)\n",
- ld->name, get_dev_name(i), bsize, qsize);
+ init_completion(&dpld->udl_cmpl);
+ init_completion(&dpld->crash_cmpl);
+
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ init_completion(&dpld->req_ack_cmpl[i]);
+
+ INIT_DELAYED_WORK(&dpld->rx_dwork, ipc_rx_work);
+
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ spin_lock_init(&dpld->tx_lock[i]);
+ atomic_set(&dpld->res_required[i], 0);
+ }
+
+ ld->tx_wq = create_singlethread_workqueue("dpram_tx_wq");
+ if (!ld->tx_wq) {
+ mif_err("%s: ERR! fail to create tx_wq\n", ld->name);
+ goto err;
}
+ INIT_DELAYED_WORK(&ld->fmt_tx_dwork, fmt_tx_work);
+ INIT_DELAYED_WORK(&ld->raw_tx_dwork, raw_tx_work);
+ INIT_DELAYED_WORK(&ld->rfs_tx_dwork, rfs_tx_work);
+ ld->tx_dwork[IPC_FMT] = &ld->fmt_tx_dwork;
+ ld->tx_dwork[IPC_RAW] = &ld->raw_tx_dwork;
+ ld->tx_dwork[IPC_RFS] = &ld->rfs_tx_dwork;
+
+#ifdef DEBUG_MODEM_IF
+ spin_lock_init(&dpld->stat_list.lock);
+ spin_lock_init(&dpld->trace_list.lock);
+#endif
/* Prepare a multi-purpose miscellaneous buffer */
- dpld->buff = kzalloc(dpld->dp_size, GFP_KERNEL);
+ dpld->buff = kzalloc(dpld->size, GFP_KERNEL);
if (!dpld->buff) {
- mif_info("%s: ERR! kzalloc dpld->buff fail\n", ld->name);
+ mif_err("%s: ERR! kzalloc dpld->buff fail\n", ld->name);
goto err;
}
- /* Retrieve DPRAM IRQ GPIO# */
- dpld->gpio_dpram_int = mdm_data->gpio_dpram_int;
-
- /* Retrieve DPRAM IRQ# */
- if (!dpctl->dpram_irq) {
- dpctl->dpram_irq = platform_get_irq_byname(pdev, "dpram_irq");
- if (dpctl->dpram_irq < 0) {
- mif_info("%s: ERR! platform_get_irq_byname fail\n",
- ld->name);
+ /*
+ ** Retrieve DPRAM IRQ GPIO#, IRQ#, and IRQ flags
+ */
+ dpld->gpio_int2ap = modem->gpio_ipc_int2ap;
+ dpld->gpio_cp_status = modem->gpio_cp_status;
+ dpld->gpio_cp_wakeup = modem->gpio_cp_wakeup;
+ if (dpram->type == AP_IDPRAM) {
+ if (!modem->gpio_ipc_int2cp) {
+ mif_err("%s: ERR! no gpio_ipc_int2cp\n", ld->name);
goto err;
}
+ dpld->gpio_int2cp = modem->gpio_ipc_int2cp;
}
- dpld->irq = dpctl->dpram_irq;
- /* Retrieve DPRAM IRQ flags */
- if (!dpctl->dpram_irq_flags)
- dpctl->dpram_irq_flags = (IRQF_NO_SUSPEND | IRQF_TRIGGER_LOW);
- dpld->irq_flags = dpctl->dpram_irq_flags;
+ dpld->irq = modem->irq_ipc_int2ap;
+
+ if (modem->irqf_ipc_int2ap)
+ dpld->irq_flags = modem->irqf_ipc_int2ap;
+ else
+ dpld->irq_flags = (IRQF_NO_SUSPEND | IRQF_TRIGGER_LOW);
+
+ /*
+ ** Initialize power management (PM) for AP_IDPRAM
+ */
+ if (dpld->type == AP_IDPRAM) {
+ dpld->pm_op = idpram_get_pm_op(dpld->ap);
+ if (!dpld->pm_op) {
+ mif_err("%s: no pm_op for AP_IDPRAM\n", ld->name);
+ goto err;
+ }
+
+ ret = dpld->pm_op->pm_init(dpld, modem, pm_tx_work);
+ if (ret) {
+ mif_err("%s: pm_init fail (err %d)\n", ld->name, ret);
+ goto err;
+ }
+ }
- /* Register DPRAM interrupt handler */
- snprintf(dpld->irq_name, DP_MAX_NAME_LEN, "%s_irq", ld->name);
+ /*
+ ** Register DPRAM interrupt handler
+ */
+ snprintf(dpld->irq_name, MIF_MAX_NAME_LEN, "%s_irq", ld->name);
if (dpld->ext_op && dpld->ext_op->irq_handler)
dpld->irq_handler = dpld->ext_op->irq_handler;
- else if (dpld->dp_type == CP_IDPRAM)
+ else if (dpld->type == CP_IDPRAM)
dpld->irq_handler = cp_idpram_irq_handler;
- else if (dpld->dp_type == AP_IDPRAM)
+ else if (dpld->type == AP_IDPRAM)
dpld->irq_handler = ap_idpram_irq_handler;
else
dpld->irq_handler = ext_dpram_irq_handler;
- ret = dpram_register_isr(dpld->irq, dpld->irq_handler, dpld->irq_flags,
+ ret = mif_register_isr(dpld->irq, dpld->irq_handler, dpld->irq_flags,
dpld->irq_name, dpld);
if (ret)
goto err;
- else
- return ld;
+
+ return ld;
err:
if (dpld) {
- if (dpld->buff)
- kfree(dpld->buff);
+ kfree(dpld->buff);
kfree(dpld);
}
diff --git a/drivers/misc/modem_if/modem_link_device_dpram.h b/drivers/misc/modem_if/modem_link_device_dpram.h
index c651e51..d9ef251 100644
--- a/drivers/misc/modem_if/modem_link_device_dpram.h
+++ b/drivers/misc/modem_if/modem_link_device_dpram.h
@@ -1,5 +1,4 @@
/*
- * Copyright (C) 2011 Google, Inc.
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -12,227 +11,11 @@
* GNU General Public License for more details.
*
*/
+
#ifndef __MODEM_LINK_DEVICE_DPRAM_H__
#define __MODEM_LINK_DEVICE_DPRAM_H__
-#include <linux/spinlock.h>
-#include <linux/wakelock.h>
-#include <linux/workqueue.h>
-#include <linux/timer.h>
-#include <linux/platform_data/modem.h>
-
-#include "modem_prj.h"
-
-#define DPRAM_MAGIC_CODE 0xAA
-
-/* interrupt masks.*/
-#define INT_MASK_VALID 0x0080
-#define INT_MASK_CMD 0x0040
-#define INT_VALID(x) ((x) & INT_MASK_VALID)
-#define INT_CMD_VALID(x) ((x) & INT_MASK_CMD)
-#define INT_NON_CMD(x) (INT_MASK_VALID | (x))
-#define INT_CMD(x) (INT_MASK_VALID | INT_MASK_CMD | (x))
-
-#define EXT_UDL_MASK 0xF000
-#define EXT_UDL_CMD(x) ((x) & EXT_UDL_MASK)
-#define EXT_INT_VALID_MASK 0x8000
-#define EXT_CMD_VALID_MASK 0x4000
-#define UDL_CMD_VALID_MASK 0x2000
-#define EXT_INT_VALID(x) ((x) & EXT_INT_VALID_MASK)
-#define EXT_CMD_VALID(x) ((x) & EXT_CMD_VALID_MASK)
-#define UDL_CMD_VALID(x) ((x) & UDL_CMD_VALID_MASK)
-#define INT_EXT_CMD(x) (EXT_INT_VALID_MASK | EXT_CMD_VALID_MASK | (x))
-
-#define EXT_CMD_MASK(x) ((x) & 0x0FFF)
-#define EXT_CMD_SET_SPEED_LOW 0x0011
-#define EXT_CMD_SET_SPEED_MID 0x0012
-#define EXT_CMD_SET_SPEED_HIGH 0x0013
-
-#define UDL_RESULT_SUCCESS 0x1
-#define UDL_RESULT_FAIL 0x2
-
-#define UDL_CMD_MASK(x) (((x) >> 8) & 0xF)
-#define UDL_CMD_RECV_READY 0x1
-#define UDL_CMD_DL_START_REQ 0x2
-#define UDL_CMD_DL_START_RESP 0x3
-#define UDL_CMD_IMAGE_SEND_REQ 0x4
-#define UDL_CMD_SEND_DONE_RESP 0x5
-#define UDL_CMD_SEND_DONE_REQ 0x6
-#define UDL_CMD_UPDATE_DONE 0x7
-#define UDL_CMD_STATUS_UPDATE 0x8
-#define UDL_CMD_IMAGE_SEND_RESP 0x9
-#define UDL_CMD_EFS_CLEAR_RESP 0xB
-#define UDL_CMD_ALARM_BOOT_OK 0xC
-#define UDL_CMD_ALARM_BOOT_FAIL 0xD
-
-#define CMD_IMG_START_REQ 0x9200
-#define CMD_IMG_SEND_REQ 0x9400
-#define CMD_DL_SEND_DONE_REQ 0x9600
-#define CMD_UL_RECV_RESP 0x9601
-#define CMD_UL_RECV_DONE_RESP 0x9801
-
-/* special interrupt cmd indicating modem boot failure. */
-#define INT_POWERSAFE_FAIL 0xDEAD
-
-#define INT_MASK_REQ_ACK_RFS 0x0400 /* Request RES_ACK_RFS */
-#define INT_MASK_RES_ACK_RFS 0x0200 /* Response of REQ_ACK_RFS */
-#define INT_MASK_SEND_RFS 0x0100 /* Indicate sending RFS data */
-
-#define INT_MASK_REQ_ACK_F 0x0020
-#define INT_MASK_REQ_ACK_R 0x0010
-#define INT_MASK_RES_ACK_F 0x0008
-#define INT_MASK_RES_ACK_R 0x0004
-#define INT_MASK_SEND_F 0x0002
-#define INT_MASK_SEND_R 0x0001
-
-#define INT_MASK_RES_ACK_SET \
- (INT_MASK_RES_ACK_F | INT_MASK_RES_ACK_R | INT_MASK_RES_ACK_RFS)
-
-#define INT_MASK_SEND_SET \
- (INT_MASK_SEND_F | INT_MASK_SEND_R | INT_MASK_SEND_RFS)
-
-#define INT_CMD_MASK(x) ((x) & 0xF)
-#define INT_CMD_INIT_START 0x1
-#define INT_CMD_INIT_END 0x2
-#define INT_CMD_REQ_ACTIVE 0x3
-#define INT_CMD_RES_ACTIVE 0x4
-#define INT_CMD_REQ_TIME_SYNC 0x5
-#define INT_CMD_CRASH_RESET 0x7
-#define INT_CMD_PHONE_START 0x8
-#define INT_CMD_ERR_DISPLAY 0x9
-#define INT_CMD_CRASH_EXIT 0x9
-#define INT_CMD_CP_DEEP_SLEEP 0xA
-#define INT_CMD_NV_REBUILDING 0xB
-#define INT_CMD_EMER_DOWN 0xC
-#define INT_CMD_PIF_INIT_DONE 0xD
-#define INT_CMD_SILENT_NV_REBUILDING 0xE
-#define INT_CMD_NORMAL_PWR_OFF 0xF
-
-#define START_FLAG 0x7F
-#define END_FLAG 0x7E
-
-#define DP_MAGIC_DMDL 0x4445444C
-#define DP_MAGIC_UMDL 0x4445444D
-#define DP_DPRAM_SIZE 0x4000
-#define DP_DEFAULT_WRITE_LEN 8168
-#define DP_DEFAULT_DUMP_LEN 16128
-#define DP_DUMP_HEADER_SIZE 7
-
-#define UDL_TIMEOUT (50 * HZ)
-#define UDL_SEND_TIMEOUT (200 * HZ)
-#define FORCE_CRASH_ACK_TIMEOUT (5 * HZ)
-#define DUMP_TIMEOUT (30 * HZ)
-#define DUMP_START_TIMEOUT (100 * HZ)
-#define DUMP_WAIT_TIMEOUT (HZ >> 10) /* 1/1024 second */
-
-enum host_boot_mode {
- HOST_BOOT_MODE_NORMAL,
- HOST_BOOT_MODE_DUMP,
-};
-
-enum dpram_init_status {
- DPRAM_INIT_STATE_NONE,
- DPRAM_INIT_STATE_READY,
-};
-
-struct dpram_boot_img {
- char *addr;
- int size;
- enum host_boot_mode mode;
- unsigned req;
- unsigned resp;
-};
-
-#define MAX_PAYLOAD_SIZE 0x2000
-struct dpram_boot_frame {
- unsigned req; /* AP->CP request */
- unsigned resp; /* response expected by AP */
- ssize_t len; /* data size in the buffer */
- unsigned offset; /* offset to write into DPRAM */
- char data[MAX_PAYLOAD_SIZE];
-};
-
-/* buffer type for modem image */
-struct dpram_dump_arg {
- char *buff; /* pointer to the buffer */
- int buff_size; /* buffer size */
- unsigned req; /* AP->CP request */
- unsigned resp; /* CP->AP response */
- bool cmd; /* AP->CP command */
-};
-
-struct dpram_boot_map {
- u32 __iomem *magic;
- u8 __iomem *buff;
- u32 __iomem *req;
- u32 __iomem *resp;
- u32 size;
-};
-
-struct qc_dpram_boot_map {
- u8 __iomem *buff;
- u16 __iomem *frame_size;
- u16 __iomem *tag;
- u16 __iomem *count;
-};
-
-struct dpram_dload_map {
- u32 __iomem *magic;
- u8 __iomem *buff;
-};
-
-struct dpram_uload_map {
- u32 __iomem *magic;
- u8 __iomem *buff;
-};
-
-struct ul_header {
- u8 bop;
- u16 total_frame;
- u16 curr_frame;
- u16 len;
-} __packed;
-
-struct dpram_udl_param {
- unsigned char *addr;
- unsigned int size;
- unsigned int count;
- unsigned int tag;
-};
-
-struct dpram_udl_check {
- unsigned int total_size;
- unsigned int rest_size;
- unsigned int send_size;
- unsigned int copy_start;
- unsigned int copy_complete;
- unsigned int boot_complete;
-};
-
-#define DP_BOOT_BUFF_OFFSET 4
-#define DP_DLOAD_BUFF_OFFSET 4
-#define DP_ULOAD_BUFF_OFFSET 4
-#define DP_BOOT_REQ_OFFSET 0
-#define DP_BOOT_RESP_OFFSET 8
-
-#define MAX_WQ_NAME_LENGTH 64
-
-#define DPRAM_MAX_RXBQ_SIZE 256
-
-struct dpram_rxb {
- u8 *buff;
- unsigned size;
-
- u8 *data;
- unsigned len;
-};
-
-struct dpram_rxb_queue {
- int size;
- int in;
- int out;
- struct dpram_rxb *rxb;
-};
+#include "modem_link_device_memory.h"
/*
magic_code +
@@ -282,38 +65,110 @@ struct dpram_ipc_16k_map {
u16 mbx_ap2cp;
};
-#define DP_MAX_NAME_LEN 32
+enum dpram_init_status {
+ DPRAM_INIT_STATE_NONE,
+ DPRAM_INIT_STATE_READY,
+};
+
+struct dpram_boot_frame {
+ unsigned req; /* AP->CP request */
+ unsigned resp; /* response expected by AP */
+ ssize_t len; /* data size in the buffer */
+ unsigned offset; /* offset to write into DPRAM */
+ char data[DP_MAX_PAYLOAD_SIZE];
+};
+
+struct dpram_dump_arg {
+ char *buff; /* pointer to the buffer */
+ int buff_size; /* buffer size */
+ unsigned req; /* AP->CP request */
+ unsigned resp; /* CP->AP response */
+ int cmd; /* AP->CP command */
+};
+
+/* DPRAM upload/download header */
+struct dpram_udl_header {
+ u8 bop;
+ u16 num_frames;
+ u16 curr_frame;
+ u16 len;
+#ifdef CONFIG_CDMA_MODEM_CBP82
+ u8 pad;
+#endif
+} __packed;
+
+#define MAX_DUMP_SKB_SIZE 4096
+
+enum idpram_link_pm_states {
+ IDPRAM_PM_SUSPEND_PREPARE,
+ IDPRAM_PM_DPRAM_POWER_DOWN,
+ IDPRAM_PM_SUSPEND_START,
+ IDPRAM_PM_RESUME_START,
+ IDPRAM_PM_ACTIVE,
+};
+
+struct idpram_pm_data {
+ atomic_t pm_lock;
+
+ enum idpram_link_pm_states pm_state;
+
+ struct completion down_cmpl;
+
+ struct wake_lock ap_wlock;
+ struct wake_lock hold_wlock;
+ struct delayed_work tx_dwork;
+ struct delayed_work resume_dwork;
+
+ struct notifier_block pm_noti;
+
+ unsigned resume_try_cnt;
+
+ /* the last value in the mbx_cp2ap */
+ unsigned last_msg;
+};
+
+struct dpram_link_device;
struct dpram_ext_op;
+struct idpram_pm_op;
struct dpram_link_device {
struct link_device ld;
+ enum dpram_type type; /* DPRAM type */
+ enum ap_type ap; /* AP type for AP_IDPRAM */
+
+ /* Stirct I/O access (e.g. ioread16(), etc.) is required */
+ bool strict_io_access;
+
/* DPRAM address and size */
- u8 __iomem *dp_base; /* DPRAM base virtual address */
- u32 dp_size; /* DPRAM size */
- enum dpram_type dp_type; /* DPRAM type */
+ u8 __iomem *base; /* Virtual address of DPRAM */
+ u32 size; /* DPRAM size */
+
+ /* DPRAM SFR */
+ u8 __iomem *sfr_base; /* Virtual address of SFR */
+
+ /* Whether or not this DPRAM can go asleep */
+ bool need_wake_up;
/* DPRAM IRQ GPIO# */
- unsigned gpio_dpram_int;
+ unsigned gpio_int2ap;
+ unsigned gpio_cp_status;
+ unsigned gpio_cp_wakeup;
+ unsigned gpio_int2cp;
/* DPRAM IRQ from CP */
int irq;
unsigned long irq_flags;
- char irq_name[DP_MAX_NAME_LEN];
+ char irq_name[MIF_MAX_NAME_LEN];
/* Link to DPRAM control functions dependent on each platform */
- int max_ipc_dev;
- struct modemlink_dpram_control *dpctl;
+ struct modemlink_dpram_data *dpram;
/* Physical configuration -> logical configuration */
- union {
- struct dpram_boot_map bt_map;
- struct qc_dpram_boot_map qc_bt_map;
- };
-
- struct dpram_dload_map dl_map;
- struct dpram_uload_map ul_map;
+ struct memif_boot_map bt_map;
+ struct memif_dload_map dl_map;
+ struct memif_uload_map ul_map;
/* IPC device map */
struct dpram_ipc_map ipc_map;
@@ -327,40 +182,40 @@ struct dpram_link_device {
/* Wakelock for DPRAM device */
struct wake_lock wlock;
- char wlock_name[DP_MAX_NAME_LEN];
+ char wlock_name[MIF_MAX_NAME_LEN];
/* For booting */
unsigned boot_start_complete;
- struct completion dpram_init_cmd;
- struct completion modem_pif_init_done;
/* For UDL */
- struct tasklet_struct ul_tsk;
struct tasklet_struct dl_tsk;
- struct completion udl_start_complete;
- struct completion udl_cmd_complete;
- struct dpram_udl_check udl_check;
- struct dpram_udl_param udl_param;
+ struct completion udl_cmpl;
- /* For CP RAM dump */
+ /*
+ ** For CP crash dump
+ */
+ bool forced_cp_crash;
struct timer_list crash_ack_timer;
- struct completion dump_start_complete;
- struct completion dump_recv_done;
- struct timer_list dump_timer;
- int dump_rcvd; /* Count of dump packets received */
+ struct timer_list crash_timer;
+ struct completion crash_cmpl;
+ /* If this field is wanted to be used, it must be initialized only in
+ * the "ld->dump_start" method.
+ */
+ struct delayed_work crash_dwork;
+ /* Count of CP crash dump packets received */
+ int crash_rcvd;
/* For locking TX process */
spinlock_t tx_lock[MAX_IPC_DEV];
+ /* For retransmission under DPRAM flow control after TXQ full state */
+ unsigned long res_ack_wait_timeout;
+ atomic_t res_required[MAX_IPC_DEV];
+ struct completion req_ack_cmpl[MAX_IPC_DEV];
+
/* For efficient RX process */
- struct tasklet_struct rx_tsk;
- struct dpram_rxb_queue rxbq[MAX_IPC_DEV];
+ struct delayed_work rx_dwork;
struct io_device *iod[MAX_IPC_DEV];
- bool use_skb;
- struct sk_buff_head skb_rxq[MAX_IPC_DEV];
-
- /* For retransmission after buffer full state */
- atomic_t res_required[MAX_IPC_DEV];
/* For wake-up/sleep control */
atomic_t accessing;
@@ -369,45 +224,53 @@ struct dpram_link_device {
u8 *buff;
/* DPRAM IPC initialization status */
- int dpram_init_status;
+ int init_status;
/* Alias to device-specific IOCTL function */
int (*ext_ioctl)(struct dpram_link_device *dpld, struct io_device *iod,
unsigned int cmd, unsigned long arg);
/* Alias to DPRAM IRQ handler */
- irqreturn_t (*irq_handler)(int irq, void *data);
+ irq_handler_t irq_handler;
- /* For DPRAM dump */
- void (*dpram_dump)(struct link_device *ld, char *buff);
+ /* For DPRAM logging */
+ struct mem_status_queue stat_list;
+ struct trace_data_queue trace_list;
/* Common operations for each DPRAM */
- void (*clear_intr)(struct dpram_link_device *dpld);
u16 (*recv_intr)(struct dpram_link_device *dpld);
void (*send_intr)(struct dpram_link_device *dpld, u16 mask);
u16 (*get_magic)(struct dpram_link_device *dpld);
void (*set_magic)(struct dpram_link_device *dpld, u16 value);
u16 (*get_access)(struct dpram_link_device *dpld);
void (*set_access)(struct dpram_link_device *dpld, u16 value);
- u32 (*get_tx_head)(struct dpram_link_device *dpld, int id);
- u32 (*get_tx_tail)(struct dpram_link_device *dpld, int id);
- void (*set_tx_head)(struct dpram_link_device *dpld, int id, u32 head);
- void (*set_tx_tail)(struct dpram_link_device *dpld, int id, u32 tail);
- u8 *(*get_tx_buff)(struct dpram_link_device *dpld, int id);
- u32 (*get_tx_buff_size)(struct dpram_link_device *dpld, int id);
- u32 (*get_rx_head)(struct dpram_link_device *dpld, int id);
- u32 (*get_rx_tail)(struct dpram_link_device *dpld, int id);
- void (*set_rx_head)(struct dpram_link_device *dpld, int id, u32 head);
- void (*set_rx_tail)(struct dpram_link_device *dpld, int id, u32 tail);
- u8 *(*get_rx_buff)(struct dpram_link_device *dpld, int id);
- u32 (*get_rx_buff_size)(struct dpram_link_device *dpld, int id);
+ u32 (*get_txq_head)(struct dpram_link_device *dpld, int id);
+ u32 (*get_txq_tail)(struct dpram_link_device *dpld, int id);
+ void (*set_txq_head)(struct dpram_link_device *dpld, int id, u32 in);
+ void (*set_txq_tail)(struct dpram_link_device *dpld, int id, u32 out);
+ u8 *(*get_txq_buff)(struct dpram_link_device *dpld, int id);
+ u32 (*get_txq_buff_size)(struct dpram_link_device *dpld, int id);
+ u32 (*get_rxq_head)(struct dpram_link_device *dpld, int id);
+ u32 (*get_rxq_tail)(struct dpram_link_device *dpld, int id);
+ void (*set_rxq_head)(struct dpram_link_device *dpld, int id, u32 in);
+ void (*set_rxq_tail)(struct dpram_link_device *dpld, int id, u32 out);
+ u8 *(*get_rxq_buff)(struct dpram_link_device *dpld, int id);
+ u32 (*get_rxq_buff_size)(struct dpram_link_device *dpld, int id);
u16 (*get_mask_req_ack)(struct dpram_link_device *dpld, int id);
u16 (*get_mask_res_ack)(struct dpram_link_device *dpld, int id);
u16 (*get_mask_send)(struct dpram_link_device *dpld, int id);
- void (*ipc_rx_handler)(struct dpram_link_device *dpld, u16 int2ap);
+ void (*get_dpram_status)(struct dpram_link_device *dpld,
+ enum circ_dir_type, struct mem_status *stat);
+ void (*ipc_rx_handler)(struct dpram_link_device *dpld,
+ struct mem_status *stat);
+ void (*reset_dpram_ipc)(struct dpram_link_device *dpld);
/* Extended operations for various modems */
struct dpram_ext_op *ext_op;
+
+ /* Power management (PM) for AP_IDPRAM */
+ struct idpram_pm_data pm_data;
+ struct idpram_pm_op *pm_op;
};
/* converts from struct link_device* to struct xxx_link_device* */
@@ -415,27 +278,65 @@ struct dpram_link_device {
container_of(linkdev, struct dpram_link_device, ld)
struct dpram_ext_op {
+ /* flag for checking whether or not a dpram_ext_op instance exists */
int exist;
+ /* methods for setting up DPRAM maps */
void (*init_boot_map)(struct dpram_link_device *dpld);
void (*init_dl_map)(struct dpram_link_device *dpld);
void (*init_ul_map)(struct dpram_link_device *dpld);
+ void (*init_ipc_map)(struct dpram_link_device *dpld);
- int (*download_binary)(struct dpram_link_device *dpld,
- struct sk_buff *skb);
+ /* methods for CP booting */
+ int (*xmit_boot)(struct dpram_link_device *dpld, unsigned long arg);
+ int (*xmit_binary)(struct dpram_link_device *dpld, struct sk_buff *skb);
+ /* methods for DPRAM command handling */
+ void (*cmd_handler)(struct dpram_link_device *dpld, u16 cmd);
void (*cp_start_handler)(struct dpram_link_device *dpld);
+ /* method for CP firmware upgrade */
+ int (*firm_update)(struct dpram_link_device *dpld, unsigned long arg);
+
+ /* methods for CP crash dump */
void (*crash_log)(struct dpram_link_device *dpld);
int (*dump_start)(struct dpram_link_device *dpld);
- int (*dump_update)(struct dpram_link_device *dpld, void *arg);
+ int (*dump_update)(struct dpram_link_device *dpld, unsigned long arg);
+ int (*dump_finish)(struct dpram_link_device *dpld, unsigned long arg);
+ /* IOCTL extension */
int (*ioctl)(struct dpram_link_device *dpld, struct io_device *iod,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
- irqreturn_t (*irq_handler)(int irq, void *data);
+ /* methods for interrupt handling */
+ irq_handler_t irq_handler;
+ void (*clear_int2ap)(struct dpram_link_device *dpld);
+
+ /* methods for power management */
+ int (*wakeup)(struct dpram_link_device *dpld);
+ void (*sleep)(struct dpram_link_device *dpld);
};
struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem);
+struct idpram_pm_op {
+ /* flag for checking whether or not a idpram_pm_op instance exists */
+ int exist;
+ int (*pm_init)(struct dpram_link_device *dpld, struct modem_data *modem,
+ void (*pm_tx_func)(struct work_struct *work));
+ void (*power_down)(struct dpram_link_device *dpld);
+ void (*power_up)(struct dpram_link_device *dpld);
+ void (*halt_suspend)(struct dpram_link_device *dpld);
+ bool (*locked)(struct dpram_link_device *dpld);
+ bool (*int2cp_possible)(struct dpram_link_device *dpld);
+};
+
+struct idpram_pm_op *idpram_get_pm_op(enum ap_type id);
+
+#if 1
+#endif
+
+extern void set_sromc_access(bool access);
+
#endif
+
diff --git a/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c b/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c
index 1475a46..edaf6e5 100644
--- a/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c
+++ b/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c
@@ -25,103 +25,82 @@
#include <linux/if_arp.h>
#include <linux/platform_device.h>
#include <linux/kallsyms.h>
-#include <linux/platform_data/modem.h>
+#include <linux/suspend.h>
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+#include "modem.h"
#include "modem_prj.h"
-#include "modem_link_device_dpram.h"
#include "modem_utils.h"
+#include "modem_link_device_dpram.h"
-#if defined(CONFIG_LTE_MODEM_CMC221)
-/*
-** For host (flashless) booting via DPRAM
-*/
-#define CMC22x_AP_BOOT_DOWN_DONE 0x54329876
-#define CMC22x_CP_REQ_MAIN_BIN 0xA5A5A5A5
-#define CMC22x_CP_REQ_NV_DATA 0x5A5A5A5A
-#define CMC22x_CP_DUMP_MAGIC 0xDEADDEAD
-
-#define CMC22x_HOST_DOWN_START 0x1234
-#define CMC22x_HOST_DOWN_END 0x4321
-#define CMC22x_REG_NV_DOWN_END 0xABCD
-#define CMC22x_CAL_NV_DOWN_END 0xDCBA
-
-#define CMC22x_1ST_BUFF_READY 0xAAAA
-#define CMC22x_2ND_BUFF_READY 0xBBBB
-#define CMC22x_1ST_BUFF_FULL 0x1111
-#define CMC22x_2ND_BUFF_FULL 0x2222
-
-#define CMC22x_CP_RECV_NV_END 0x8888
-#define CMC22x_CP_CAL_OK 0x4F4B
-#define CMC22x_CP_CAL_BAD 0x4552
-#define CMC22x_CP_DUMP_END 0xFADE
-
-#define CMC22x_DUMP_BUFF_SIZE 8192 /* 8 KB */
-#endif
-
-#if defined(CONFIG_CDMA_MODEM_CBP72)
-static void cbp72_init_boot_map(struct dpram_link_device *dpld)
+#if defined(CONFIG_CDMA_MODEM_CBP72) || defined(CONFIG_CDMA_MODEM_CBP82)
+static void cbp_init_boot_map(struct dpram_link_device *dpld)
{
- struct dpram_boot_map *bt_map = &dpld->bt_map;
+ struct memif_boot_map *bt_map = &dpld->bt_map;
- bt_map->magic = (u32 *)dpld->dp_base;
- bt_map->buff = (u8 *)(dpld->dp_base + DP_BOOT_BUFF_OFFSET);
- bt_map->size = dpld->dp_size - 4;
+ bt_map->magic = (u32 *)dpld->base;
+ bt_map->buff = (u8 *)(dpld->base + DP_BOOT_BUFF_OFFSET);
+ bt_map->space = dpld->size - 4;
}
-static void cbp72_init_dl_map(struct dpram_link_device *dpld)
+static void cbp_init_dl_map(struct dpram_link_device *dpld)
{
- dpld->dl_map.magic = (u32 *)dpld->dp_base;
- dpld->dl_map.buff = (u8 *)(dpld->dp_base + DP_DLOAD_BUFF_OFFSET);
+ dpld->dl_map.magic = (u32 *)dpld->base;
+ dpld->dl_map.buff = (u8 *)(dpld->base + DP_DLOAD_BUFF_OFFSET);
}
-static int _cbp72_edpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
+static int cbp_udl_wait_resp(struct dpram_link_device *dpld, u32 resp)
{
- struct link_device *ld = &dpld->ld;
int ret;
- int int2cp;
+ int int2ap;
- ret = wait_for_completion_interruptible_timeout(
- &dpld->udl_cmd_complete, UDL_TIMEOUT);
+ mif_debug("wait for 0x%04X\n", resp);
+ ret = wait_for_completion_timeout(&dpld->udl_cmpl, UDL_TIMEOUT);
if (!ret) {
- mif_info("%s: ERR! No UDL_CMD_RESP!!!\n", ld->name);
- return -ENXIO;
+ mif_info("ERR! No UDL_CMD_RESP!!!\n");
+ return -EIO;
}
- int2cp = dpld->recv_intr(dpld);
- mif_debug("%s: int2cp = 0x%x\n", ld->name, int2cp);
- if (resp == int2cp || int2cp == 0xA700)
- return int2cp;
- else
+ int2ap = dpld->recv_intr(dpld);
+ if (resp == int2ap || int2ap == CMD_UL_RECV_DONE_REQ) {
+ mif_debug("int2ap = 0x%04X\n", int2ap);
+ return int2ap;
+ } else {
+ mif_err("ERR! int2ap 0x%04X != resp 0x%04X\n", int2ap, resp);
return -EINVAL;
+ }
}
-static int _cbp72_edpram_download_bin(struct dpram_link_device *dpld,
+static int cbp_xmit_binary(struct dpram_link_device *dpld,
struct sk_buff *skb)
{
- struct link_device *ld = &dpld->ld;
struct dpram_boot_frame *bf = (struct dpram_boot_frame *)skb->data;
u8 __iomem *buff = dpld->bt_map.buff;
int err = 0;
- if (bf->len > dpld->bt_map.size) {
- mif_info("%s: ERR! Out of DPRAM boundary\n", ld->name);
- err = -EINVAL;
+ if (bf->len > dpld->bt_map.space) {
+ mif_info("ERR! Out of DPRAM boundary\n");
+ err = -ERANGE;
goto exit;
}
if (bf->len)
- memcpy(buff, bf->data, bf->len);
+ memcpy16_to_io(buff, bf->data, bf->len);
- init_completion(&dpld->udl_cmd_complete);
+#ifdef CONFIG_CDMA_MODEM_CBP72
+ init_completion(&dpld->udl_cmpl);
+#endif
- if (bf->req)
+ if (bf->req) {
dpld->send_intr(dpld, (u16)bf->req);
+ mif_debug("send intr 0x%04X\n", (u16)bf->req);
+ }
if (bf->resp) {
- err = _cbp72_edpram_wait_resp(dpld, bf->resp);
+ err = cbp_udl_wait_resp(dpld, bf->resp);
if (err < 0) {
- mif_info("%s: ERR! wait_response fail (%d)\n",
- ld->name, err);
+ mif_err("ERR! cbp_udl_wait_resp fail (err %d)\n", err);
goto exit;
} else if (err == bf->resp) {
err = skb->len;
@@ -133,24 +112,14 @@ exit:
return err;
}
-static int cbp72_download_binary(struct dpram_link_device *dpld,
- struct sk_buff *skb)
-{
- if (dpld->dp_type == EXT_DPRAM)
- return _cbp72_edpram_download_bin(dpld, skb);
- else
- return -ENODEV;
-}
-
-static int cbp72_dump_start(struct dpram_link_device *dpld)
+static int cbp_dump_start(struct dpram_link_device *dpld)
{
- struct link_device *ld = &dpld->ld;
u8 *dest = dpld->ul_map.buff;
int ret;
- ld->mode = LINK_MODE_ULOAD;
+ dpld->ld.mode = LINK_MODE_ULOAD;
- ret = del_timer(&dpld->dump_timer);
+ ret = del_timer(&dpld->crash_timer);
wake_lock(&dpld->wlock);
iowrite32(DP_MAGIC_UMDL, dpld->ul_map.magic);
@@ -161,53 +130,65 @@ static int cbp72_dump_start(struct dpram_link_device *dpld)
iowrite8((u8)0x0, dest + 3);
iowrite8((u8)END_FLAG, dest + 4);
- init_completion(&dpld->dump_start_complete);
+ init_completion(&dpld->crash_cmpl);
return 0;
}
-static int _cbp72_edpram_upload(struct dpram_link_device *dpld,
- struct dpram_dump_arg *dump, unsigned char __user *target)
+static int cbp_dump_update(struct dpram_link_device *dpld, unsigned long arg)
{
- struct link_device *ld = &dpld->ld;
- struct ul_header header;
+ struct dpram_dump_arg dump;
+ struct dpram_udl_header header;
+ unsigned char __user *target = (unsigned char __user *)arg;
+ int err = 0;
+ int resp = 0;
u8 *dest = NULL;
u8 *buff = NULL;
- u16 plen = 0;
- int err = 0;
- int ret = 0;
+ u8 *header_buff = NULL;
int buff_size = 0;
+ u16 plen = 0;
- mif_debug("\n");
-
- init_completion(&dpld->udl_cmd_complete);
-
- mif_debug("%s: req %x, resp %x", ld->name, dump->req, dump->resp);
+ err = copy_from_user(&dump, (void __user *)arg, sizeof(dump));
+ if (err < 0) {
+ mif_err("ERR! ARG copy_from_user fail (err %d)\n", err);
+ goto exit;
+ }
+ mif_debug("req %x, resp %x", dump.req, dump.resp);
- if (dump->req)
- dpld->send_intr(dpld, (u16)dump->req);
+ if (dump.req)
+ dpld->send_intr(dpld, (u16)dump.req);
- if (dump->resp) {
- err = _cbp72_edpram_wait_resp(dpld, dump->resp);
+ if (dump.resp) {
+ resp = err = cbp_udl_wait_resp(dpld, dump.resp);
if (err < 0) {
- mif_info("%s: ERR! wait_response fail (%d)\n",
- ld->name, err);
+ mif_info("ERR! wait_response fail (err %d)\n", err);
goto exit;
}
}
- if (dump->cmd)
- return err;
+ if (dump.cmd)
+ goto exit;
dest = (u8 *)dpld->ul_map.buff;
- header.bop = *(u8 *)(dest);
- header.total_frame = *(u16 *)(dest + 1);
- header.curr_frame = *(u16 *)(dest + 3);
- header.len = *(u16 *)(dest + 5);
+ header_buff = vmalloc(sizeof(struct dpram_udl_header));
+ if (!header_buff) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ memcpy16_from_io(header_buff, dest, sizeof(struct dpram_udl_header));
+
+ header.bop = *(u8 *)(header_buff);
+ header.num_frames = *(u16 *)(header_buff + 1);
+ header.curr_frame = *(u16 *)(header_buff + 3);
+ header.len = *(u16 *)(header_buff + 5);
+#ifdef CONFIG_CDMA_MODEM_CBP82
+ header.pad = *(u8 *)(header_buff + 7);
+#endif
- mif_debug("%s: total frame:%d, current frame:%d, data len:%d\n",
- ld->name, header.total_frame, header.curr_frame, header.len);
+ mif_debug("total frames:%d, current frame:%d, data len:%d\n",
+ header.num_frames, header.curr_frame, header.len);
plen = min_t(u16, header.len, DP_DEFAULT_DUMP_LEN);
@@ -217,22 +198,26 @@ static int _cbp72_edpram_upload(struct dpram_link_device *dpld,
goto exit;
}
- memcpy(buff, dest + sizeof(struct ul_header), plen);
- ret = copy_to_user(dump->buff, buff, plen);
- if (ret < 0) {
- mif_info("%s: ERR! dump copy_to_user fail\n", ld->name);
+ memcpy16_from_io(buff, dest + sizeof(struct dpram_udl_header), plen);
+ err = copy_to_user(dump.buff, buff, plen);
+ if (err) {
+ mif_info("ERR! DUMP copy_to_user fail\n");
err = -EIO;
goto exit;
}
- buff_size = plen;
- ret = copy_to_user(target + 4, &buff_size, sizeof(int));
- if (ret < 0) {
- mif_info("%s: ERR! size copy_to_user fail\n", ld->name);
+ buff_size = plen;
+ err = copy_to_user(target + 4, &buff_size, sizeof(int));
+ if (err) {
+ mif_info("ERR! SIZE copy_to_user fail\n");
err = -EIO;
goto exit;
}
+ /* Return response value */
+ if (err == 0)
+ err = resp;
+
vfree(buff);
return err;
@@ -243,82 +228,169 @@ exit:
wake_unlock(&dpld->wlock);
return err;
}
+#endif
-static int cbp72_dump_update(struct dpram_link_device *dpld, void *arg)
-{
- struct link_device *ld = &dpld->ld;
- struct dpram_dump_arg dump;
- int ret;
+#if defined(CONFIG_LTE_MODEM_CMC221)
+/*
+** For CMC221 SFR for IDPRAM
+*/
+#define CMC_INT2CP_REG 0x10 /* Interrupt to CP */
+#define CMC_INT2AP_REG 0x50
+#define CMC_CLR_INT_REG 0x28 /* Clear Interrupt to AP */
+#define CMC_RESET_REG 0x3C
+#define CMC_PUT_REG 0x40 /* AP->CP reg for hostbooting */
+#define CMC_GET_REG 0x50 /* CP->AP reg for hostbooting */
- ret = copy_from_user(&dump, (void __user *)arg, sizeof(dump));
- if (ret < 0) {
- mif_info("%s: ERR! copy_from_user fail\n", ld->name);
- return ret;
- }
+/*
+** For host (flashless) booting via DPRAM
+*/
+#define CMC22x_AP_BOOT_DOWN_DONE 0x54329876
+#define CMC22x_CP_REQ_MAIN_BIN 0xA5A5A5A5
+#define CMC22x_CP_REQ_NV_DATA 0x5A5A5A5A
+#define CMC22x_CP_DUMP_MAGIC 0xDEADDEAD
- return _cbp72_edpram_upload(dpld, &dump, (unsigned char __user *)arg);
-}
+#define CMC22x_HOST_DOWN_START 0x1234
+#define CMC22x_HOST_DOWN_END 0x4321
+#define CMC22x_REG_NV_DOWN_END 0xABCD
+#define CMC22x_CAL_NV_DOWN_END 0xDCBA
-static int cbp72_set_dl_magic(struct link_device *ld, struct io_device *iod)
-{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
+#define CMC22x_1ST_BUFF_READY 0xAAAA
+#define CMC22x_2ND_BUFF_READY 0xBBBB
+#define CMC22x_1ST_BUFF_FULL 0x1111
+#define CMC22x_2ND_BUFF_FULL 0x2222
+
+#define CMC22x_CP_RECV_NV_END 0x8888
+#define CMC22x_CP_CAL_OK 0x4F4B
+#define CMC22x_CP_CAL_BAD 0x4552
+#define CMC22x_CP_DUMP_END 0xFADE
- ld->mode = LINK_MODE_DLOAD;
+#define CMC22x_DUMP_BUFF_SIZE 8192
- iowrite32(DP_MAGIC_DMDL, dpld->dl_map.magic);
+/* CMC221 IDPRAM SFR */
+struct cmc221_idpram_sfr {
+ u16 __iomem *int2cp;
+ u16 __iomem *int2ap;
+ u16 __iomem *clr_int2ap;
+ u16 __iomem *reset;
+ u16 __iomem *msg2cp;
+ u16 __iomem *msg2ap;
+};
- return 0;
-}
+struct cmc221_boot_img {
+ char *addr;
+ int size;
+ enum cp_boot_mode mode;
+ unsigned req;
+ unsigned resp;
+};
-static int cbp72_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
- unsigned int cmd, unsigned long arg)
+static struct cmc221_idpram_sfr cmc_sfr;
+
+static void cmc221_init_boot_map(struct dpram_link_device *dpld)
{
- struct link_device *ld = &dpld->ld;
- int err = 0;
+ struct memif_boot_map *bt_map = &dpld->bt_map;
- switch (cmd) {
- case IOCTL_MODEM_DL_START:
- err = cbp72_set_dl_magic(ld, iod);
- if (err < 0)
- mif_err("%s: ERR! set_dl_magic fail\n", ld->name);
- break;
+ bt_map->buff = dpld->base;
+ bt_map->space = dpld->size;
+ bt_map->req = (u32 *)(dpld->base + DP_BOOT_REQ_OFFSET);
+ bt_map->resp = (u32 *)(dpld->base + DP_BOOT_RESP_OFFSET);
+}
- default:
- mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd);
- err = -EINVAL;
- break;
- }
+static void cmc221_init_dl_map(struct dpram_link_device *dpld)
+{
+ dpld->dl_map.magic = (u32 *)dpld->base;
+ dpld->dl_map.buff = (u8 *)dpld->base;
+}
- return err;
+static void cmc221_init_ul_map(struct dpram_link_device *dpld)
+{
+ dpld->ul_map.magic = (u32 *)dpld->base;
+ dpld->ul_map.buff = (u8 *)dpld->base;
}
-#endif
-#if defined(CONFIG_LTE_MODEM_CMC221)
-static void cmc221_init_boot_map(struct dpram_link_device *dpld)
+static void cmc221_init_ipc_map(struct dpram_link_device *dpld)
{
- struct dpram_boot_map *bt_map = &dpld->bt_map;
+ struct dpram_ipc_16k_map *dpram_map;
+ struct dpram_ipc_device *dev;
+ u8 __iomem *sfr_base = dpld->sfr_base;
+
+ dpram_map = (struct dpram_ipc_16k_map *)dpld->base;
+
+ /* Magic code and access enable fields */
+ dpld->ipc_map.magic = (u16 __iomem *)&dpram_map->magic;
+ dpld->ipc_map.access = (u16 __iomem *)&dpram_map->access;
+
+ /* FMT */
+ dev = &dpld->ipc_map.dev[IPC_FMT];
+
+ strcpy(dev->name, "FMT");
+ dev->id = IPC_FMT;
+
+ dev->txq.head = (u16 __iomem *)&dpram_map->fmt_tx_head;
+ dev->txq.tail = (u16 __iomem *)&dpram_map->fmt_tx_tail;
+ dev->txq.buff = (u8 __iomem *)&dpram_map->fmt_tx_buff[0];
+ dev->txq.size = DP_16K_FMT_TX_BUFF_SZ;
+
+ dev->rxq.head = (u16 __iomem *)&dpram_map->fmt_rx_head;
+ dev->rxq.tail = (u16 __iomem *)&dpram_map->fmt_rx_tail;
+ dev->rxq.buff = (u8 __iomem *)&dpram_map->fmt_rx_buff[0];
+ dev->rxq.size = DP_16K_FMT_RX_BUFF_SZ;
+
+ dev->mask_req_ack = INT_MASK_REQ_ACK_F;
+ dev->mask_res_ack = INT_MASK_RES_ACK_F;
+ dev->mask_send = INT_MASK_SEND_F;
+
+ /* RAW */
+ dev = &dpld->ipc_map.dev[IPC_RAW];
+
+ strcpy(dev->name, "RAW");
+ dev->id = IPC_RAW;
+
+ dev->txq.head = (u16 __iomem *)&dpram_map->raw_tx_head;
+ dev->txq.tail = (u16 __iomem *)&dpram_map->raw_tx_tail;
+ dev->txq.buff = (u8 __iomem *)&dpram_map->raw_tx_buff[0];
+ dev->txq.size = DP_16K_RAW_TX_BUFF_SZ;
+
+ dev->rxq.head = (u16 __iomem *)&dpram_map->raw_rx_head;
+ dev->rxq.tail = (u16 __iomem *)&dpram_map->raw_rx_tail;
+ dev->rxq.buff = (u8 __iomem *)&dpram_map->raw_rx_buff[0];
+ dev->rxq.size = DP_16K_RAW_RX_BUFF_SZ;
+
+ dev->mask_req_ack = INT_MASK_REQ_ACK_R;
+ dev->mask_res_ack = INT_MASK_RES_ACK_R;
+ dev->mask_send = INT_MASK_SEND_R;
+
+ /* SFR */
+ cmc_sfr.int2cp = (u16 __iomem *)(sfr_base + CMC_INT2CP_REG);
+ cmc_sfr.int2ap = (u16 __iomem *)(sfr_base + CMC_INT2AP_REG);
+ cmc_sfr.clr_int2ap = (u16 __iomem *)(sfr_base + CMC_CLR_INT_REG);
+ cmc_sfr.reset = (u16 __iomem *)(sfr_base + CMC_RESET_REG);
+ cmc_sfr.msg2cp = (u16 __iomem *)(sfr_base + CMC_PUT_REG);
+ cmc_sfr.msg2ap = (u16 __iomem *)(sfr_base + CMC_GET_REG);
+
+ /* Interrupt ports */
+ dpld->ipc_map.mbx_cp2ap = cmc_sfr.int2ap;
+ dpld->ipc_map.mbx_ap2cp = cmc_sfr.int2cp;
+}
- bt_map->buff = dpld->dp_base;
- bt_map->size = dpld->dp_size;
- bt_map->req = (u32 *)(dpld->dp_base + DP_BOOT_REQ_OFFSET);
- bt_map->resp = (u32 *)(dpld->dp_base + DP_BOOT_RESP_OFFSET);
+static inline void cmc221_idpram_reset(struct dpram_link_device *dpld)
+{
+ iowrite16(1, cmc_sfr.reset);
}
-static void cmc221_init_dl_map(struct dpram_link_device *dpld)
+static inline u16 cmc221_idpram_recv_msg(struct dpram_link_device *dpld)
{
- dpld->dl_map.magic = (u32 *)dpld->dp_base;
- dpld->dl_map.buff = (u8 *)dpld->dp_base;
+ return ioread16(cmc_sfr.msg2ap);
}
-static void cmc221_init_ul_map(struct dpram_link_device *dpld)
+static inline void cmc221_idpram_send_msg(struct dpram_link_device *dpld,
+ u16 msg)
{
- dpld->ul_map.magic = (u32 *)dpld->dp_base;
- dpld->ul_map.buff = (u8 *)dpld->dp_base;
+ iowrite16(msg, cmc_sfr.msg2cp);
}
-static int _cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
+static int cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
{
- struct link_device *ld = &dpld->ld;
int count = 50000;
u32 rcvd = 0;
@@ -328,16 +400,14 @@ static int _cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
if (rcvd == resp)
break;
- rcvd = dpld->dpctl->recv_msg();
+ rcvd = cmc221_idpram_recv_msg(dpld);
if (rcvd == 0x9999) {
- mif_info("%s: Invalid resp 0x%04X\n",
- ld->name, rcvd);
+ mif_info("invalid resp 0x%04X\n", rcvd);
panic("CP Crash ... BAD CRC in CP");
}
if (count-- < 0) {
- mif_info("%s: Invalid resp 0x%08X\n",
- ld->name, rcvd);
+ mif_info("invalid resp 0x%08X\n", rcvd);
return -EAGAIN;
}
@@ -345,20 +415,19 @@ static int _cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
}
} else {
while (1) {
- rcvd = dpld->dpctl->recv_msg();
+ rcvd = cmc221_idpram_recv_msg(dpld);
if (rcvd == resp)
break;
if (resp == CMC22x_CP_RECV_NV_END &&
rcvd == CMC22x_CP_CAL_BAD) {
- mif_info("%s: CMC22x_CP_CAL_BAD\n", ld->name);
+ mif_info("invalid resp CMC22x_CP_CAL_BAD\n");
break;
}
if (count-- < 0) {
- mif_info("%s: Invalid resp 0x%04X\n",
- ld->name, rcvd);
+ mif_info("invalid resp 0x%04X\n", rcvd);
return -EAGAIN;
}
@@ -369,110 +438,104 @@ static int _cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
return rcvd;
}
-static int _cmc221_idpram_send_boot(struct dpram_link_device *dpld, void *arg)
+static int cmc221_xmit_boot(struct dpram_link_device *dpld, unsigned long arg)
{
struct link_device *ld = &dpld->ld;
u8 __iomem *bt_buff = dpld->bt_map.buff;
- struct dpram_boot_img cp_img;
+ struct cmc221_boot_img cp_img;
u8 *img_buff = NULL;
int err = 0;
int cnt = 0;
+ mif_info("+++\n");
ld->mode = LINK_MODE_BOOT;
- dpld->dpctl->setup_speed(DPRAM_SPEED_LOW);
+ dpld->dpram->setup_speed(DPRAM_SPEED_LOW);
/* Test memory... After testing, memory is cleared. */
- if (mif_test_dpram(ld->name, bt_buff, dpld->bt_map.size) < 0) {
- mif_info("%s: ERR! mif_test_dpram fail!\n", ld->name);
+ if (mif_test_dpram(ld->name, bt_buff, dpld->bt_map.space) < 0) {
+ mif_info("ERR! mif_test_dpram fail!\n");
ld->mode = LINK_MODE_OFFLINE;
return -EIO;
}
- memset(&cp_img, 0, sizeof(struct dpram_boot_img));
+ memset(&cp_img, 0, sizeof(struct cmc221_boot_img));
/* Get information about the boot image */
- err = copy_from_user(&cp_img, arg, sizeof(cp_img));
- mif_info("%s: CP image addr = 0x%08X, size = %d\n",
- ld->name, (int)cp_img.addr, cp_img.size);
+ err = copy_from_user(&cp_img, (void __user *)arg, sizeof(cp_img));
+ mif_info("CP image addr = 0x%08X, size = %d\n",
+ (int)cp_img.addr, cp_img.size);
/* Alloc a buffer for the boot image */
- img_buff = kzalloc(dpld->bt_map.size, GFP_KERNEL);
+ img_buff = kzalloc(dpld->bt_map.space, GFP_KERNEL);
if (!img_buff) {
- mif_info("%s: ERR! kzalloc fail\n", ld->name);
+ mif_info("ERR! kzalloc fail\n");
ld->mode = LINK_MODE_OFFLINE;
return -ENOMEM;
}
/* Copy boot image from the user space to the image buffer */
- err = copy_from_user(img_buff, cp_img.addr, cp_img.size);
+ err = copy_from_user(img_buff, (void __user *)cp_img.addr, cp_img.size);
/* Copy boot image to DPRAM and verify it */
memcpy(bt_buff, img_buff, cp_img.size);
if (memcmp16_to_io(bt_buff, img_buff, cp_img.size)) {
- mif_info("%s: ERR! Boot may be broken!!!\n", ld->name);
+ mif_info("ERR! Boot may be broken!!!\n");
goto err;
}
- dpld->dpctl->reset();
+ cmc221_idpram_reset(dpld);
usleep_range(1000, 2000);
- if (cp_img.mode == HOST_BOOT_MODE_NORMAL) {
- mif_info("%s: HOST_BOOT_MODE_NORMAL\n", ld->name);
- mif_info("%s: Send req 0x%08X\n", ld->name, cp_img.req);
+ if (cp_img.mode == CP_BOOT_MODE_NORMAL) {
+ mif_info("CP_BOOT_MODE_NORMAL\n");
+ mif_info("send req 0x%08X\n", cp_img.req);
iowrite32(cp_img.req, dpld->bt_map.req);
/* Wait for cp_img.resp for up to 2 seconds */
- mif_info("%s: Wait resp 0x%08X\n", ld->name, cp_img.resp);
+ mif_info("wait resp 0x%08X\n", cp_img.resp);
while (ioread32(dpld->bt_map.resp) != cp_img.resp) {
cnt++;
usleep_range(1000, 2000);
if (cnt > 1000) {
- mif_info("%s: ERR! Invalid resp 0x%08X\n",
- ld->name, ioread32(dpld->bt_map.resp));
+ mif_info("ERR! invalid resp 0x%08X\n",
+ ioread32(dpld->bt_map.resp));
goto err;
}
}
} else {
- mif_info("%s: HOST_BOOT_MODE_DUMP\n", ld->name);
+ mif_info("CP_BOOT_MODE_DUMP\n");
}
kfree(img_buff);
- mif_info("%s: Send BOOT done\n", ld->name);
+ mif_info("send BOOT done\n");
- dpld->dpctl->setup_speed(DPRAM_SPEED_HIGH);
+ dpld->dpram->setup_speed(DPRAM_SPEED_HIGH);
+ mif_info("---\n");
return 0;
err:
ld->mode = LINK_MODE_OFFLINE;
kfree(img_buff);
- mif_info("%s: ERR! Boot send fail!!!\n", ld->name);
+ mif_err("FAIL!!!\n");
+ mif_info("---\n");
return -EIO;
}
-static int cmc221_download_boot(struct dpram_link_device *dpld, void *arg)
-{
- if (dpld->dp_type == CP_IDPRAM)
- return _cmc221_idpram_send_boot(dpld, arg);
- else
- return -ENODEV;
-}
-
-static int _cmc221_idpram_download_bin(struct dpram_link_device *dpld,
+static int cmc221_idpram_download_bin(struct dpram_link_device *dpld,
struct sk_buff *skb)
{
int err = 0;
int ret = 0;
- struct link_device *ld = &dpld->ld;
struct dpram_boot_frame *bf = (struct dpram_boot_frame *)skb->data;
u8 __iomem *buff = (dpld->bt_map.buff + bf->offset);
- if ((bf->offset + bf->len) > dpld->bt_map.size) {
- mif_info("%s: ERR! Out of DPRAM boundary\n", ld->name);
+ if ((bf->offset + bf->len) > dpld->bt_map.space) {
+ mif_info("ERR! out of DPRAM boundary\n");
err = -EINVAL;
goto exit;
}
@@ -481,17 +544,16 @@ static int _cmc221_idpram_download_bin(struct dpram_link_device *dpld,
memcpy(buff, bf->data, bf->len);
if (bf->req)
- dpld->dpctl->send_msg((u16)bf->req);
+ cmc221_idpram_send_msg(dpld, (u16)bf->req);
if (bf->resp) {
- err = _cmc221_idpram_wait_resp(dpld, bf->resp);
+ err = cmc221_idpram_wait_resp(dpld, bf->resp);
if (err < 0)
- mif_info("%s: ERR! wait_response fail (err %d)\n",
- ld->name, err);
+ mif_info("ERR! wait_resp fail (err %d)\n", err);
}
if (bf->req == CMC22x_CAL_NV_DOWN_END)
- mif_info("%s: CMC22x_CAL_NV_DOWN_END\n", ld->name);
+ mif_info("request CMC22x_CAL_NV_DOWN_END\n");
exit:
if (err < 0)
@@ -504,89 +566,84 @@ exit:
return ret;
}
-static int cmc221_download_binary(struct dpram_link_device *dpld,
+static int cmc221_xmit_binary(struct dpram_link_device *dpld,
struct sk_buff *skb)
{
- if (dpld->dp_type == CP_IDPRAM)
- return _cmc221_idpram_download_bin(dpld, skb);
+ if (dpld->type == CP_IDPRAM)
+ return cmc221_idpram_download_bin(dpld, skb);
else
return -ENODEV;
}
static int cmc221_dump_start(struct dpram_link_device *dpld)
{
- struct link_device *ld = &dpld->ld;
- int ret;
-
- ld->mode = LINK_MODE_ULOAD;
+ dpld->ld.mode = LINK_MODE_ULOAD;
- ret = del_timer(&dpld->dump_timer);
+ del_timer(&dpld->crash_timer);
wake_lock(&dpld->wlock);
- dpld->dump_rcvd = 0;
+ dpld->crash_rcvd = 0;
iowrite32(CMC22x_CP_DUMP_MAGIC, dpld->ul_map.magic);
- init_completion(&dpld->dump_start_complete);
+ init_completion(&dpld->crash_cmpl);
return 0;
}
-static void _cmc221_idpram_wait_dump(unsigned long arg)
+static void cmc221_idpram_wait_dump(unsigned long arg)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)arg;
u16 msg;
- msg = dpld->dpctl->recv_msg();
+ msg = cmc221_idpram_recv_msg(dpld);
if (msg == CMC22x_CP_DUMP_END) {
- complete_all(&dpld->dump_recv_done);
+ complete_all(&dpld->crash_cmpl);
return;
}
- if (((dpld->dump_rcvd & 0x1) == 0) && (msg == CMC22x_1ST_BUFF_FULL)) {
- complete_all(&dpld->dump_recv_done);
+ if (((dpld->crash_rcvd & 0x1) == 0) && (msg == CMC22x_1ST_BUFF_FULL)) {
+ complete_all(&dpld->crash_cmpl);
return;
}
- if (((dpld->dump_rcvd & 0x1) == 1) && (msg == CMC22x_2ND_BUFF_FULL)) {
- complete_all(&dpld->dump_recv_done);
+ if (((dpld->crash_rcvd & 0x1) == 1) && (msg == CMC22x_2ND_BUFF_FULL)) {
+ complete_all(&dpld->crash_cmpl);
return;
}
- mif_add_timer(&dpld->dump_timer, DUMP_WAIT_TIMEOUT,
- _cmc221_idpram_wait_dump, (unsigned long)dpld);
+ mif_add_timer(&dpld->crash_timer, DUMP_WAIT_TIMEOUT,
+ cmc221_idpram_wait_dump, (unsigned long)dpld);
}
-static int _cmc221_idpram_upload(struct dpram_link_device *dpld,
- struct dpram_dump_arg *dumparg)
+static int cmc221_idpram_upload(struct dpram_link_device *dpld,
+ struct dpram_dump_arg *dumparg)
{
- struct link_device *ld = &dpld->ld;
int ret;
u8 __iomem *src;
int buff_size = CMC22x_DUMP_BUFF_SIZE;
- if ((dpld->dump_rcvd & 0x1) == 0)
- dpld->dpctl->send_msg(CMC22x_1ST_BUFF_READY);
+ if ((dpld->crash_rcvd & 0x1) == 0)
+ cmc221_idpram_send_msg(dpld, CMC22x_1ST_BUFF_READY);
else
- dpld->dpctl->send_msg(CMC22x_2ND_BUFF_READY);
+ cmc221_idpram_send_msg(dpld, CMC22x_2ND_BUFF_READY);
- init_completion(&dpld->dump_recv_done);
+ init_completion(&dpld->crash_cmpl);
- mif_add_timer(&dpld->dump_timer, DUMP_WAIT_TIMEOUT,
- _cmc221_idpram_wait_dump, (unsigned long)dpld);
+ mif_add_timer(&dpld->crash_timer, DUMP_WAIT_TIMEOUT,
+ cmc221_idpram_wait_dump, (unsigned long)dpld);
- ret = wait_for_completion_interruptible_timeout(
- &dpld->dump_recv_done, DUMP_TIMEOUT);
+ ret = wait_for_completion_timeout(&dpld->crash_cmpl, DUMP_TIMEOUT);
if (!ret) {
- mif_info("%s: ERR! CP didn't send dump data!!!\n", ld->name);
+ mif_info("ERR! no dump from CP!!!\n");
goto err_out;
}
- if (dpld->dpctl->recv_msg() == CMC22x_CP_DUMP_END) {
- mif_info("%s: CMC22x_CP_DUMP_END\n", ld->name);
+ if (cmc221_idpram_recv_msg(dpld) == CMC22x_CP_DUMP_END) {
+ mif_info("recv CMC22x_CP_DUMP_END\n");
return 0;
}
- if ((dpld->dump_rcvd & 0x1) == 0)
+ if ((dpld->crash_rcvd & 0x1) == 0)
src = dpld->ul_map.buff;
else
src = dpld->ul_map.buff + CMC22x_DUMP_BUFF_SIZE;
@@ -595,52 +652,64 @@ static int _cmc221_idpram_upload(struct dpram_link_device *dpld,
ret = copy_to_user(dumparg->buff, dpld->buff, buff_size);
if (ret < 0) {
- mif_info("%s: ERR! copy_to_user fail\n", ld->name);
+ mif_info("ERR! copy_to_user fail\n");
goto err_out;
}
- dpld->dump_rcvd++;
+ dpld->crash_rcvd++;
return buff_size;
err_out:
return -EIO;
}
-static int cmc221_dump_update(struct dpram_link_device *dpld, void *arg)
+static int cmc221_dump_update(struct dpram_link_device *dpld, unsigned long arg)
{
- struct link_device *ld = &dpld->ld;
struct dpram_dump_arg dump;
int ret;
ret = copy_from_user(&dump, (void __user *)arg, sizeof(dump));
if (ret < 0) {
- mif_info("%s: ERR! copy_from_user fail\n", ld->name);
+ mif_info("ERR! copy_from_user fail\n");
return ret;
}
- return _cmc221_idpram_upload(dpld, &dump);
+ return cmc221_idpram_upload(dpld, &dump);
}
-static int cmc221_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
- unsigned int cmd, unsigned long arg)
+static void cmc221_idpram_clr_int2ap(struct dpram_link_device *dpld)
{
- struct link_device *ld = &dpld->ld;
- int err = 0;
+ iowrite16(0xFFFF, cmc_sfr.clr_int2ap);
+}
- switch (cmd) {
- case IOCTL_DPRAM_SEND_BOOT:
- err = cmc221_download_boot(dpld, (void *)arg);
- if (err < 0)
- mif_info("%s: ERR! download_boot fail\n", ld->name);
- break;
+static int cmc221_idpram_wakeup(struct dpram_link_device *dpld)
+{
+ int cnt = 0;
- default:
- mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd);
- err = -EINVAL;
- break;
+ gpio_set_value(dpld->gpio_cp_wakeup, 1);
+
+ while (!gpio_get_value(dpld->gpio_cp_status)) {
+ if (cnt++ > 10) {
+ if (in_irq())
+ mif_err("ERR! gpio_cp_status == 0 in IRQ\n");
+ else
+ mif_err("ERR! gpio_cp_status == 0\n");
+ return -EACCES;
+ }
+
+ mif_info("gpio_cp_status == 0 (cnt %d)\n", cnt);
+ if (in_interrupt())
+ udelay(1000);
+ else
+ usleep_range(1000, 2000);
}
- return err;
+ return 0;
+}
+
+static void cmc221_idpram_sleep(struct dpram_link_device *dpld)
+{
+ gpio_set_value(dpld->gpio_cp_wakeup, 0);
}
#endif
@@ -652,17 +721,44 @@ enum qc_dload_tag {
QC_DLOAD_TAG_MAX
};
+struct qc_dpram_boot_map {
+ u8 __iomem *buff;
+ u16 __iomem *frame_size;
+ u16 __iomem *tag;
+ u16 __iomem *count;
+};
+
+struct qc_dpram_udl_param {
+ unsigned char *addr;
+ unsigned int size;
+ unsigned int count;
+ unsigned int tag;
+};
+
+struct qc_dpram_udl_check {
+ unsigned int total_size;
+ unsigned int rest_size;
+ unsigned int send_size;
+ unsigned int copy_start;
+ unsigned int copy_complete;
+ unsigned int boot_complete;
+};
+
+static struct qc_dpram_boot_map qc_bt_map;
+static struct qc_dpram_udl_param qc_udl_param;
+static struct qc_dpram_udl_check qc_udl_check;
+
static void qc_dload_task(unsigned long data);
static void qc_init_boot_map(struct dpram_link_device *dpld)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
- struct modemlink_dpram_control *dpctl = dpld->dpctl;
+ struct qc_dpram_boot_map *qbt_map = &qc_bt_map;
+ struct modemlink_dpram_data *dpram = dpld->dpram;
- bt_map->buff = dpld->dp_base;
- bt_map->frame_size = (u16 *)(dpld->dp_base + dpctl->boot_size_offset);
- bt_map->tag = (u16 *)(dpld->dp_base + dpctl->boot_tag_offset);
- bt_map->count = (u16 *)(dpld->dp_base + dpctl->boot_count_offset);
+ qbt_map->buff = dpld->base;
+ qbt_map->frame_size = (u16 *)(dpld->base + dpram->boot_size_offset);
+ qbt_map->tag = (u16 *)(dpld->base + dpram->boot_tag_offset);
+ qbt_map->count = (u16 *)(dpld->base + dpram->boot_count_offset);
tasklet_init(&dpld->dl_tsk, qc_dload_task, (unsigned long)dpld);
}
@@ -673,15 +769,15 @@ static int qc_prepare_download(struct dpram_link_device *dpld)
int count = 0;
while (1) {
- if (dpld->udl_check.copy_start) {
- dpld->udl_check.copy_start = 0;
+ if (qc_udl_check.copy_start) {
+ qc_udl_check.copy_start = 0;
break;
}
- msleep_interruptible(10);
+ usleep_range(10000, 11000);
count++;
- if (count > 200) {
+ if (count > 300) {
mif_err("ERR! count %d\n", count);
return -1;
}
@@ -690,32 +786,33 @@ static int qc_prepare_download(struct dpram_link_device *dpld)
return retval;
}
-static void _qc_do_download(struct dpram_link_device *dpld,
- struct dpram_udl_param *param)
+static void qc_do_download(struct dpram_link_device *dpld,
+ struct qc_dpram_udl_param *param)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
+ struct qc_dpram_boot_map *qbt_map = &qc_bt_map;
- if (param->size <= dpld->dpctl->max_boot_frame_size) {
- memcpy(bt_map->buff, param->addr, param->size);
- iowrite16(param->size, bt_map->frame_size);
- iowrite16(param->tag, bt_map->tag);
- iowrite16(param->count, bt_map->count);
+ if (param->size <= dpld->dpram->max_boot_frame_size) {
+ memcpy(qbt_map->buff, param->addr, param->size);
+ iowrite16(param->size, qbt_map->frame_size);
+ iowrite16(param->tag, qbt_map->tag);
+ iowrite16(param->count, qbt_map->count);
dpld->send_intr(dpld, 0xDB12);
} else {
mif_info("param->size %d\n", param->size);
}
}
-static int _qc_download(struct dpram_link_device *dpld, void *arg,
+static int qc_download(struct dpram_link_device *dpld, void *arg,
enum qc_dload_tag tag)
{
int retval = 0;
int count = 0;
int cnt_limit;
unsigned char *img;
- struct dpram_udl_param param;
+ struct qc_dpram_udl_param param;
- retval = copy_from_user((void *)&param, (void *)arg, sizeof(param));
+ retval = copy_from_user((void *)&param, (void __user *)arg,
+ sizeof(param));
if (retval < 0) {
mif_err("ERR! copy_from_user fail\n");
return -1;
@@ -729,24 +826,24 @@ static int _qc_download(struct dpram_link_device *dpld, void *arg,
memset(img, 0, param.size);
memcpy(img, param.addr, param.size);
- dpld->udl_check.total_size = param.size;
- dpld->udl_check.rest_size = param.size;
- dpld->udl_check.send_size = 0;
- dpld->udl_check.copy_complete = 0;
+ qc_udl_check.total_size = param.size;
+ qc_udl_check.rest_size = param.size;
+ qc_udl_check.send_size = 0;
+ qc_udl_check.copy_complete = 0;
- dpld->udl_param.addr = img;
- dpld->udl_param.size = dpld->dpctl->max_boot_frame_size;
+ qc_udl_param.addr = img;
+ qc_udl_param.size = dpld->dpram->max_boot_frame_size;
if (tag == QC_DLOAD_TAG_NV)
- dpld->udl_param.count = 1;
+ qc_udl_param.count = 1;
else
- dpld->udl_param.count = param.count;
- dpld->udl_param.tag = tag;
+ qc_udl_param.count = param.count;
+ qc_udl_param.tag = tag;
- if (dpld->udl_check.rest_size < dpld->dpctl->max_boot_frame_size)
- dpld->udl_param.size = dpld->udl_check.rest_size;
+ if (qc_udl_check.rest_size < dpld->dpram->max_boot_frame_size)
+ qc_udl_param.size = qc_udl_check.rest_size;
/* Download image (binary or NV) */
- _qc_do_download(dpld, &dpld->udl_param);
+ qc_do_download(dpld, &qc_udl_param);
/* Wait for completion
*/
@@ -756,18 +853,18 @@ static int _qc_download(struct dpram_link_device *dpld, void *arg,
cnt_limit = 1000;
while (1) {
- if (dpld->udl_check.copy_complete) {
- dpld->udl_check.copy_complete = 0;
+ if (qc_udl_check.copy_complete) {
+ qc_udl_check.copy_complete = 0;
retval = 0;
break;
}
- msleep(10);
+ usleep_range(10000, 11000);
count++;
if (count > cnt_limit) {
- dpld->udl_check.total_size = 0;
- dpld->udl_check.rest_size = 0;
+ qc_udl_check.total_size = 0;
+ qc_udl_check.rest_size = 0;
mif_err("ERR! count %d\n", count);
retval = -1;
break;
@@ -781,51 +878,51 @@ static int _qc_download(struct dpram_link_device *dpld, void *arg,
static int qc_download_binary(struct dpram_link_device *dpld, void *arg)
{
- return _qc_download(dpld, arg, QC_DLOAD_TAG_BIN);
+ return qc_download(dpld, arg, QC_DLOAD_TAG_BIN);
}
static int qc_download_nv(struct dpram_link_device *dpld, void *arg)
{
- return _qc_download(dpld, arg, QC_DLOAD_TAG_NV);
+ return qc_download(dpld, arg, QC_DLOAD_TAG_NV);
}
static void qc_dload_task(unsigned long data)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)data;
- dpld->udl_check.send_size += dpld->udl_param.size;
- dpld->udl_check.rest_size -= dpld->udl_param.size;
+ qc_udl_check.send_size += qc_udl_param.size;
+ qc_udl_check.rest_size -= qc_udl_param.size;
- dpld->udl_param.addr += dpld->udl_param.size;
+ qc_udl_param.addr += qc_udl_param.size;
- if (dpld->udl_check.send_size >= dpld->udl_check.total_size) {
- dpld->udl_check.copy_complete = 1;
- dpld->udl_param.tag = 0;
+ if (qc_udl_check.send_size >= qc_udl_check.total_size) {
+ qc_udl_check.copy_complete = 1;
+ qc_udl_param.tag = 0;
return;
}
- if (dpld->udl_check.rest_size < dpld->dpctl->max_boot_frame_size)
- dpld->udl_param.size = dpld->udl_check.rest_size;
+ if (qc_udl_check.rest_size < dpld->dpram->max_boot_frame_size)
+ qc_udl_param.size = qc_udl_check.rest_size;
- dpld->udl_param.count += 1;
+ qc_udl_param.count += 1;
- _qc_do_download(dpld, &dpld->udl_param);
+ qc_do_download(dpld, &qc_udl_param);
}
static void qc_dload_cmd_handler(struct dpram_link_device *dpld, u16 cmd)
{
switch (cmd) {
case 0x1234:
- dpld->udl_check.copy_start = 1;
+ qc_udl_check.copy_start = 1;
break;
case 0xDBAB:
- if (dpld->udl_check.total_size)
+ if (qc_udl_check.total_size)
tasklet_schedule(&dpld->dl_tsk);
break;
case 0xABCD:
- dpld->udl_check.boot_complete = 1;
+ qc_udl_check.boot_complete = 1;
break;
default:
@@ -843,12 +940,12 @@ static int qc_boot_start(struct dpram_link_device *dpld)
dpld->send_intr(dpld, mask);
while (1) {
- if (dpld->udl_check.boot_complete) {
- dpld->udl_check.boot_complete = 0;
+ if (qc_udl_check.boot_complete) {
+ qc_udl_check.boot_complete = 0;
break;
}
- msleep_interruptible(10);
+ usleep_range(10000, 11000);
count++;
if (count > 200) {
@@ -870,7 +967,7 @@ static int qc_boot_post_process(struct dpram_link_device *dpld)
break;
}
- msleep_interruptible(10);
+ usleep_range(10000, 11000);
count++;
if (count > 200) {
@@ -900,27 +997,26 @@ static void qc_start_handler(struct dpram_link_device *dpld)
static void qc_crash_log(struct dpram_link_device *dpld)
{
- struct link_device *ld = &dpld->ld;
static unsigned char buf[151];
u8 __iomem *data = NULL;
- data = dpld->get_rx_buff(dpld, IPC_FMT);
+ data = dpld->get_rxq_buff(dpld, IPC_FMT);
memcpy(buf, data, (sizeof(buf) - 1));
- mif_info("PHONE ERR MSG\t| %s Crash\n", ld->mdm_data->name);
+ mif_info("PHONE ERR MSG\t| %s Crash\n", dpld->ld.mc->name);
mif_info("PHONE ERR MSG\t| %s\n", buf);
}
-static int _qc_data_upload(struct dpram_link_device *dpld,
- struct dpram_udl_param *param)
+static int qc_data_upload(struct dpram_link_device *dpld,
+ struct qc_dpram_udl_param *param)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
+ struct qc_dpram_boot_map *qbt_map = &qc_bt_map;
int retval = 0;
u16 intval = 0;
int count = 0;
while (1) {
- if (!gpio_get_value(dpld->gpio_dpram_int)) {
+ if (!gpio_get_value(dpld->gpio_int2ap)) {
intval = dpld->recv_intr(dpld);
if (intval == 0xDBAB) {
break;
@@ -930,7 +1026,7 @@ static int _qc_data_upload(struct dpram_link_device *dpld,
}
}
- msleep_interruptible(1);
+ usleep_range(1000, 2000);
count++;
if (count > 200) {
@@ -939,10 +1035,10 @@ static int _qc_data_upload(struct dpram_link_device *dpld,
}
}
- param->size = ioread16(bt_map->frame_size);
- memcpy(param->addr, bt_map->buff, param->size);
- param->tag = ioread16(bt_map->tag);
- param->count = ioread16(bt_map->count);
+ param->size = ioread16(qbt_map->frame_size);
+ memcpy(param->addr, qbt_map->buff, param->size);
+ param->tag = ioread16(qbt_map->tag);
+ param->count = ioread16(qbt_map->count);
dpld->send_intr(dpld, 0xDB12);
@@ -961,7 +1057,7 @@ static int qc_uload_step1(struct dpram_link_device *dpld)
mif_info("+---------------------------------------------+\n");
while (1) {
- if (!gpio_get_value(dpld->gpio_dpram_int)) {
+ if (!gpio_get_value(dpld->gpio_int2ap)) {
intval = dpld->recv_intr(dpld);
mif_info("intr 0x%04x\n", intval);
if (intval == 0x1234) {
@@ -972,7 +1068,7 @@ static int qc_uload_step1(struct dpram_link_device *dpld)
}
}
- msleep_interruptible(1);
+ usleep_range(1000, 2000);
count++;
if (count > 200) {
@@ -993,17 +1089,18 @@ static int qc_uload_step1(struct dpram_link_device *dpld)
static int qc_uload_step2(struct dpram_link_device *dpld, void *arg)
{
int retval = 0;
- struct dpram_udl_param param;
+ struct qc_dpram_udl_param param;
- retval = copy_from_user((void *)&param, (void *)arg, sizeof(param));
+ retval = copy_from_user((void *)&param, (void __user *)arg,
+ sizeof(param));
if (retval < 0) {
mif_err("ERR! copy_from_user fail (err %d)\n", retval);
return -1;
}
- retval = _qc_data_upload(dpld, &param);
+ retval = qc_data_upload(dpld, &param);
if (retval < 0) {
- mif_err("ERR! _qc_data_upload fail (err %d)\n", retval);
+ mif_err("ERR! qc_data_upload fail (err %d)\n", retval);
return -1;
}
@@ -1025,40 +1122,39 @@ static int qc_uload_step2(struct dpram_link_device *dpld, void *arg)
}
static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- struct link_device *ld = &dpld->ld;
int err = 0;
switch (cmd) {
case IOCTL_DPRAM_PHONE_POWON:
err = qc_prepare_download(dpld);
if (err < 0)
- mif_info("%s: ERR! prepare_download fail\n", ld->name);
+ mif_info("ERR! prepare_download fail\n");
break;
case IOCTL_DPRAM_PHONEIMG_LOAD:
err = qc_download_binary(dpld, (void *)arg);
if (err < 0)
- mif_info("%s: ERR! download_binary fail\n", ld->name);
+ mif_info("ERR! download_binary fail\n");
break;
case IOCTL_DPRAM_NVDATA_LOAD:
err = qc_download_nv(dpld, (void *)arg);
if (err < 0)
- mif_info("%s: ERR! download_nv fail\n", ld->name);
+ mif_info("ERR! download_nv fail\n");
break;
case IOCTL_DPRAM_PHONE_BOOTSTART:
err = qc_boot_start(dpld);
if (err < 0) {
- mif_info("%s: ERR! boot_start fail\n", ld->name);
+ mif_info("ERR! boot_start fail\n");
break;
}
err = qc_boot_post_process(dpld);
if (err < 0)
- mif_info("%s: ERR! boot_post_process fail\n", ld->name);
+ mif_info("ERR! boot_post_process fail\n");
break;
@@ -1067,7 +1163,7 @@ static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
err = qc_uload_step1(dpld);
if (err < 0) {
enable_irq(dpld->irq);
- mif_info("%s: ERR! upload_step1 fail\n", ld->name);
+ mif_info("ERR! upload_step1 fail\n");
}
break;
@@ -1075,12 +1171,12 @@ static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
err = qc_uload_step2(dpld, (void *)arg);
if (err < 0) {
enable_irq(dpld->irq);
- mif_info("%s: ERR! upload_step2 fail\n", ld->name);
+ mif_info("ERR! upload_step2 fail\n");
}
break;
default:
- mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd);
+ mif_err("ERR! invalid cmd 0x%08X\n", cmd);
err = -EINVAL;
break;
}
@@ -1091,44 +1187,402 @@ static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
static irqreturn_t qc_dpram_irq_handler(int irq, void *data)
{
struct dpram_link_device *dpld = (struct dpram_link_device *)data;
- struct link_device *ld = (struct link_device *)&dpld->ld;
+ struct link_device *ld = &dpld->ld;
+ struct mem_status stat;
u16 int2ap = 0;
- if (unlikely(ld->mode == LINK_MODE_OFFLINE))
+ if (ld->mode == LINK_MODE_OFFLINE) {
+ int2ap = dpld->recv_intr(dpld);
return IRQ_HANDLED;
+ }
- int2ap = dpld->recv_intr(dpld);
+ dpld->get_dpram_status(dpld, RX, &stat);
+ int2ap = stat.int2ap;
if (int2ap == INT_POWERSAFE_FAIL) {
- mif_info("%s: int2ap == INT_POWERSAFE_FAIL\n", ld->name);
+ mif_info("int2ap == INT_POWERSAFE_FAIL\n");
goto exit;
}
if (int2ap == 0x1234 || int2ap == 0xDBAB || int2ap == 0xABCD) {
qc_dload_cmd_handler(dpld, int2ap);
goto exit;
+ } else if (int2ap == 0x4321 || int2ap == 0x5432) {
+ mif_err("ERR! CP error command (0x%04X)\n", int2ap);
+ goto exit;
}
if (likely(INT_VALID(int2ap)))
- dpld->ipc_rx_handler(dpld, int2ap);
+ dpld->ipc_rx_handler(dpld, &stat);
else
- mif_info("%s: ERR! invalid intr 0x%04X\n", ld->name, int2ap);
+ mif_info("ERR! invalid intr 0x%04X\n", int2ap);
exit:
return IRQ_HANDLED;
}
#endif
-static struct dpram_ext_op ext_op_set[] = {
+#if defined(CONFIG_CDMA_MODEM_QSC6085)
+#define CMD_CP_RAMDUMP_START_REQ 0x9200
+#define CMD_CP_RAMDUMP_SEND_REQ 0x9400
+#define CMD_CP_RAMDUMP_SEND_DONE_REQ 0x9600
+
+#define CMD_CP_RAMDUMP_START_RESP 0x0300
+#define CMD_CP_RAMDUMP_SEND_RESP 0x0500
+#define CMD_CP_RAMDUMP_SEND_DONE_RESP 0x0700
+
+#define QSC_UPLOAD_MODE (0x444D554C)
+#define QSC_UPLOAD_MODE_COMPLETE (0xABCDEF90)
+
+#define RAMDUMP_CMD_TIMEOUT (5 * HZ)
+#define QSC6085_RAM_SIZE (32 * 1024 * 1024) /* 32MB */
+
+struct qsc6085_dump_command {
+ u32 addr;
+ u32 size;
+ u32 copyto_offset;
+};
+
+struct qsc6085_dump_status {
+ u32 dump_size;
+ u32 addr;
+ u32 rcvd;
+ u32 rest;
+};
+
+static struct qsc6085_dump_status qsc_dump_stat;
+
+static void qsc6085_dump_work(struct work_struct *work);
+
+static void qsc6085_init_dl_map(struct dpram_link_device *dpld)
+{
+ dpld->dl_map.magic = (u32 *)dpld->base;
+ dpld->dl_map.buff = (u8 *)(dpld->base + DP_DLOAD_BUFF_OFFSET);
+}
+
+static void qsc6085_init_ul_map(struct dpram_link_device *dpld)
+{
+ int magic_size = DP_ULOAD_MAGIC_SIZE;
+ int cmd_size = sizeof(struct qsc6085_dump_command);
+ int mbx_size = DP_MBX_SET_SIZE;
+
+ dpld->ul_map.magic = (u32 *)dpld->base;
+ dpld->ul_map.cmd = dpld->base + magic_size;
+ dpld->ul_map.cmd_size = cmd_size;
+ dpld->ul_map.buff = dpld->base + magic_size + cmd_size;
+ dpld->ul_map.space = dpld->size - (magic_size + cmd_size + mbx_size);
+}
+
+static void qsc6085_req_active_handler(struct dpram_link_device *dpld)
+{
+ struct modem_ctl *mc = dpld->ld.mc;
+ mif_info("pda_active = %d\n", gpio_get_value(mc->gpio_pda_active));
+ dpld->send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE));
+}
+
+static void qsc6085_error_display_handler(struct dpram_link_device *dpld)
+{
+ struct link_device *ld = &dpld->ld;
+ struct io_device *iod;
+
+ mif_err("recv 0xC9 (CRASH_EXIT)\n");
+ mif_err("CP Crash: %s\n", dpld->get_rxq_buff(dpld, IPC_FMT));
+
+ iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_EXIT);
+}
+
+static void qsc6085_start_handler(struct dpram_link_device *dpld)
+{
+ struct link_device *ld = &dpld->ld;
+ struct io_device *iod;
+
+ mif_info("recv 0xC8 (CP_START)\n");
+
+ mif_info("send 0xC1 (INIT_START)\n");
+ dpld->send_intr(dpld, INT_CMD(INT_CMD_INIT_START));
+
+ dpld->reset_dpram_ipc(dpld);
+
+ iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (!iod) {
+ mif_err("ERR! no iod\n");
+ return;
+ }
+ iod->modem_state_changed(iod, STATE_ONLINE);
+
+ mif_info("send 0xC2 (INIT_END)\n");
+ dpld->send_intr(dpld, INT_CMD(INT_CMD_INIT_END));
+}
+
+static void qsc6085_command_handler(struct dpram_link_device *dpld, u16 cmd)
+{
+ switch (INT_CMD_MASK(cmd)) {
+ case INT_CMD_REQ_ACTIVE:
+ qsc6085_req_active_handler(dpld);
+ break;
+
+ case INT_CMD_ERR_DISPLAY:
+#ifdef CONFIG_LINK_DEVICE_S5P_IDPRAM
+ /* If modem crashes while PDA_SLEEP is in progres */
+ dpld->pm_op->halt_suspend(dpld);
+#endif
+ qsc6085_error_display_handler(dpld);
+ break;
+
+ case INT_CMD_PHONE_START:
+ qsc6085_start_handler(dpld);
+ complete_all(&ld->init_cmpl);
+ break;
+
+#ifdef CONFIG_LINK_DEVICE_S5P_IDPRAM
+ case INT_CMD_IDPRAM_SUSPEND_ACK:
+ dpld->pm_op->power_down(dpld);
+ break;
+
+ case INT_CMD_IDPRAM_WAKEUP_START:
+ dpld->pm_op->power_up(dpld);
+ break;
+#endif
+
+ case INT_CMD_NORMAL_POWER_OFF:
+ complete(&dpld->crash_cmpl);
+ qsc6085_error_display_handler(dpld);
+ break;
+
+ default:
+ mif_err("unknown command 0x%04X\n", cmd);
+ break;
+ }
+}
+
+static int qsc6085_download_firmware(struct dpram_link_device *dpld,
+ struct modem_firmware *fw)
+{
+ int ret = 0;
+ char __user *src = fw->binary;
+ int rest = fw->size;
+ char __iomem *dst = NULL;
+ unsigned long timeout;
+ u16 curr_frame = 0;
+ u16 len = 0;
+ struct dpram_udl_header header;
+
+ header.bop = START_FLAG;
+ header.num_frames = DIV_ROUND_UP(len, DP_DEFAULT_WRITE_LEN);
+ mif_err("FW %d bytes = %d frames\n", fw->size, header.num_frames);
+
+ while (rest > 0) {
+ curr_frame++;
+ len = min(rest, DP_DEFAULT_WRITE_LEN);
+
+ header.curr_frame = curr_frame;
+ header.len = len;
+ mif_info(">>> frame# %u, len %u\n", curr_frame, len);
+
+ dst = dpld->dl_map.buff;
+ memcpy(dst, &header, sizeof(header));
+
+ dst += sizeof(header);
+ ret = copy_from_user(dst, (void __user *)src, len);
+ if (ret < 0) {
+ mif_err("copy_from_user fail\n");
+ return -EIO;
+ }
+
+ dst += len;
+ src += len;
+ rest -= len;
+
+ iowrite8(END_FLAG, (dst+3));
+
+ if (curr_frame == 1) {
+ dpld->send_intr(dpld, 0);
+ timeout = UDL_TIMEOUT;
+ } else {
+ dpld->send_intr(dpld, CMD_DL_SEND_REQ);
+ timeout = UDL_SEND_TIMEOUT;
+ }
+
+ ret = wait_for_completion_timeout(&dpld->udl_cmpl, timeout);
+ if (!ret) {
+ mif_err("ERR! no response from CP\n");
+ return -EIO;
+ }
+ }
+
+ mif_err("send CMD_DL_DONE_REQ to CP\n");
+ dpld->send_intr(dpld, CMD_DL_DONE_REQ);
+
+ ret = wait_for_completion_timeout(&dpld->udl_cmpl, UDL_TIMEOUT);
+ if (!ret) {
+ mif_err("ERR! no response from CP\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int qsc6085_dload_firmware(struct dpram_link_device *dpld,
+ unsigned long arg)
+{
+ int ret;
+ struct modem_firmware fw;
+ mif_err("+++\n");
+
+ ret = copy_from_user(&fw, (void __user *)arg, sizeof(fw));
+ if (ret < 0) {
+ mif_err("ERR! copy_from_user fail!\n");
+ return ret;
+ }
+
+ ret = qsc6085_download_firmware(dpld, &fw);
+
+ mif_err("---\n");
+ return ret;
+}
+
+static int qsc6085_dump_start(struct dpram_link_device *dpld)
+{
+ int ret;
+ struct link_device *ld = &dpld->ld;
+ struct modem_ctl *mc = ld->mc;
+ struct qsc6085_dump_status *dump_stat = &qsc_dump_stat;
+ mif_err("+++\n");
+
+ init_completion(&dpld->crash_cmpl);
+ INIT_DELAYED_WORK(&dpld->crash_dwork, qsc6085_dump_work);
+
+ iowrite32(QSC_UPLOAD_MODE, &dpld->ul_map.magic);
+
+ /* reset modem so that it goes to upload mode */
+ /* ap does not need to reset cp during CRASH_EXIT case */
+ if (gpio_get_value(mc->gpio_phone_active))
+ mc->ops.modem_reset(mc);
+
+ dpld->send_intr(dpld, CMD_CP_RAMDUMP_START_REQ);
+ ret = wait_for_completion_timeout(&dpld->crash_cmpl,
+ RAMDUMP_CMD_TIMEOUT);
+ if (!ret) {
+ mif_err("ERR! no response to CP_RAMDUMP_START_REQ\n");
+ dump_stat->dump_size = 0;
+ } else {
+ dump_stat->dump_size = QSC6085_RAM_SIZE;
+ dump_stat->addr = 0;
+ dump_stat->rcvd = 0;
+ dump_stat->rest = dump_stat->dump_size;
+ }
+
+ queue_delayed_work(system_nrt_wq, &dpld->crash_dwork, 0);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int qsc6085_dump_update(struct dpram_link_device *dpld,
+ unsigned long arg)
+{
+ int ret;
+ struct link_device *ld = &dpld->ld;
+ struct io_device *iod = link_get_iod_with_format(ld, IPC_RAMDUMP);
+ struct memif_uload_map *ul_map = &dpld->ul_map;
+ struct qsc6085_dump_status *dump_stat = &qsc_dump_stat;
+ struct qsc6085_dump_command dump_cmd;
+
+ while (iod->sk_rx_q.qlen > 0)
+ usleep_range(1000, 1100);
+
+ memset(&dump_cmd, 0, sizeof(dump_cmd));
+ dump_cmd.addr = dump_stat->addr;
+ dump_cmd.size = min(dump_stat->rest, ul_map->space);
+ dump_cmd.copyto_offset = 0x38000010;
+
+ memcpy_toio(ul_map->cmd, &dump_cmd, ul_map->cmd_size);
+
+ dpld->send_intr(dpld, CMD_CP_RAMDUMP_SEND_REQ);
+ ret = wait_for_completion_timeout(&dpld->crash_cmpl,
+ RAMDUMP_CMD_TIMEOUT);
+ if (!ret) {
+ dump_stat->dump_size = 0;
+ mif_err("ERR! no response to CP_RAMDUMP_SEND_REQ\n");
+ ret = -EIO;
+ goto exit;
+ }
+
+ memcpy_fromio(dpld->buff, ul_map->buff, dump_cmd.size);
+
+ ret = iod->recv(iod, ld, dpld->buff, dump_cmd.size);
+ if (ret < 0)
+ goto exit;
+
+ dump_stat->addr += dump_cmd.size;
+ dump_stat->rcvd += dump_cmd.size;
+ dump_stat->rest -= dump_cmd.size;
+ mif_info("rest = %u bytes\n", dump_stat->rest);
+
+ ret = dump_cmd.size;
+
+exit:
+ return ret;
+}
+
+static void qsc6085_dump_work(struct work_struct *work)
+{
+ struct dpram_link_device *dpld;
+ struct link_device *ld;
+ struct qsc6085_dump_status *dump_stat = &qsc_dump_stat;
+ int ret;
+
+ dpld = container_of(work, struct dpram_link_device, crash_dwork.work);
+ ld = &dpld->ld;
+
+ ret = qsc6085_dump_update(dpld, 0);
+ if (ret > 0 && dump_stat->rest > 0)
+ queue_delayed_work(system_nrt_wq, &dpld->crash_dwork, 0);
+}
+
+static int qsc6085_dump_finish(struct dpram_link_device *dpld,
+ unsigned long arg)
+{
+ int ret;
+ struct completion *cmpl = &dpld->crash_cmpl;
+ mif_err("+++\n");
+
+ init_completion(cmpl);
+
+ dpld->send_intr(dpld, CMD_CP_RAMDUMP_SEND_DONE_REQ);
+
+ ret = wait_for_completion_timeout(cmpl, RAMDUMP_CMD_TIMEOUT);
+ if (!ret) {
+ mif_err("ERR! no response to CP_RAMDUMP_SEND_DONE_REQ\n");
+ ret = -EIO;
+ }
+
+ mif_err("---\n");
+ return ret;
+}
+#endif
+
+static struct dpram_ext_op ext_op_set[MAX_MODEM_TYPE] = {
#ifdef CONFIG_CDMA_MODEM_CBP72
[VIA_CBP72] = {
.exist = 1,
- .init_boot_map = cbp72_init_boot_map,
- .init_dl_map = cbp72_init_dl_map,
- .download_binary = cbp72_download_binary,
- .dump_start = cbp72_dump_start,
- .dump_update = cbp72_dump_update,
- .ioctl = cbp72_ioctl,
+ .init_boot_map = cbp_init_boot_map,
+ .init_dl_map = cbp_init_dl_map,
+ .xmit_binary = cbp_xmit_binary,
+ .dump_start = cbp_dump_start,
+ .dump_update = cbp_dump_update,
+ },
+#endif
+#ifdef CONFIG_CDMA_MODEM_CBP82
+ [VIA_CBP82] = {
+ .exist = 1,
+ .init_boot_map = cbp_init_boot_map,
+ .init_dl_map = cbp_init_dl_map,
+ .xmit_binary = cbp_xmit_binary,
+ .dump_start = cbp_dump_start,
+ .dump_update = cbp_dump_update,
},
#endif
#ifdef CONFIG_LTE_MODEM_CMC221
@@ -1137,10 +1591,14 @@ static struct dpram_ext_op ext_op_set[] = {
.init_boot_map = cmc221_init_boot_map,
.init_dl_map = cmc221_init_dl_map,
.init_ul_map = cmc221_init_ul_map,
- .download_binary = cmc221_download_binary,
+ .init_ipc_map = cmc221_init_ipc_map,
+ .xmit_boot = cmc221_xmit_boot,
+ .xmit_binary = cmc221_xmit_binary,
.dump_start = cmc221_dump_start,
.dump_update = cmc221_dump_update,
- .ioctl = cmc221_ioctl,
+ .clear_int2ap = cmc221_idpram_clr_int2ap,
+ .wakeup = cmc221_idpram_wakeup,
+ .sleep = cmc221_idpram_sleep,
},
#endif
#if defined(CONFIG_CDMA_MODEM_MDM6600)
@@ -1163,6 +1621,18 @@ static struct dpram_ext_op ext_op_set[] = {
.irq_handler = qc_dpram_irq_handler,
},
#endif
+#if defined(CONFIG_CDMA_MODEM_QSC6085)
+ [QC_QSC6085] = {
+ .exist = 1,
+ .init_dl_map = qsc6085_init_dl_map,
+ .init_ul_map = qsc6085_init_ul_map,
+ .cmd_handler = qsc6085_command_handler,
+ .firm_update = qsc6085_dload_firmware,
+ .dump_start = qsc6085_dump_start,
+ .dump_update = qsc6085_dump_update,
+ .dump_finish = qsc6085_dump_finish,
+ },
+#endif
};
struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem)
@@ -1173,3 +1643,422 @@ struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem)
return NULL;
}
+#ifdef CONFIG_LINK_DEVICE_S5P_IDPRAM
+#define GPIO_IDPRAM_SFN S3C_GPIO_SFN(2)
+
+#define MAX_CHECK_RETRY_CNT 5
+#define MAX_RESUME_TRY_CNT 5
+
+static bool s5p_idpram_is_pm_locked(struct dpram_link_device *dpld)
+{
+ struct modem_ctl *mc = dpld->ld.mc;
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+
+ /* If PM is in SUSPEND */
+ if (atomic_read(&pm_data->pm_lock) > 0) {
+ mif_info("in SUSPEND\n");
+ return true;
+ }
+
+ /* If AP is in or into LPA */
+ if (!gpio_get_value(mc->gpio_pda_active)) {
+ mif_info("in LPA\n");
+ return true;
+ }
+
+ return false;
+}
+
+static void s5p_idpram_set_pm_lock(struct dpram_link_device *dpld, int lock)
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+
+ /* 0 = unlock, 1 = lock */
+ switch (lock) {
+ case 0:
+ if (atomic_read(&pm_data->pm_lock))
+ atomic_set(&pm_data->pm_lock, lock);
+ break;
+
+ case 1:
+ if (!atomic_read(&pm_data->pm_lock))
+ atomic_set(&pm_data->pm_lock, lock);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void s5p_idpram_try_resume(struct work_struct *work)
+{
+ struct idpram_pm_data *pm_data;
+ struct dpram_link_device *dpld;
+ struct link_device *ld;
+ unsigned long delay;
+ u16 cmd;
+ mif_info("+++\n");
+
+ pm_data = container_of(work, struct idpram_pm_data, resume_dwork.work);
+ dpld = container_of(pm_data, struct dpram_link_device, pm_data);
+ ld = &dpld->ld;
+
+ if (pm_data->last_msg == INT_CMD(INT_CMD_IDPRAM_RESUME_REQ)) {
+ pm_data->last_msg = 0;
+
+ s5p_idpram_set_pm_lock(dpld, 0);
+ wake_unlock(&pm_data->hold_wlock);
+
+ delay = msecs_to_jiffies(10);
+ schedule_delayed_work(&pm_data->tx_dwork, delay);
+
+ mif_info("%s resumed\n", ld->name);
+ goto exit;
+ }
+
+ if (pm_data->resume_try_cnt++ < MAX_RESUME_TRY_CNT) {
+ mif_info("%s not resumed yet\n", ld->name);
+
+ cmd = INT_CMD(INT_CMD_IDPRAM_RESUME_REQ);
+ mif_info("send IDPRAM_RESUME_REQ (0x%X)\n", cmd);
+ dpld->send_intr(dpld, cmd);
+
+ delay = msecs_to_jiffies(200);
+ schedule_delayed_work(&pm_data->resume_dwork, delay);
+ } else {
+ struct io_device *iod;
+ mif_err("ERR! %s resume T-I-M-E-O-U-T\n", ld->name);
+
+ iod = link_get_iod_with_format(ld, IPC_FMT);
+ if (iod)
+ iod->modem_state_changed(iod, STATE_CRASH_EXIT);
+
+ wake_unlock(&pm_data->hold_wlock);
+
+ /* hold wakelock until uevnet sent to rild */
+ wake_lock_timeout(&pm_data->hold_wlock, HZ*7);
+ s5p_idpram_set_pm_lock(dpld, 0);
+ }
+
+exit:
+ mif_info("---\n");
+}
+
+static irqreturn_t s5p_cp_dump_irq_handler(int irq, void *data)
+{
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t s5p_ap_wakeup_irq_handler(int irq, void *data)
+{
+ struct idpram_pm_data *pm_data = data;
+ wake_lock_timeout(&pm_data->ap_wlock, HZ*5);
+ return IRQ_HANDLED;
+}
+
+static void s5p_idpram_power_down(struct dpram_link_device *dpld)
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ mif_info("+++\n");
+
+ pm_data->last_msg = INT_CMD(INT_CMD_IDPRAM_SUSPEND_ACK);
+ complete(&pm_data->down_cmpl);
+
+ mif_info("---\n");
+}
+
+static void s5p_idpram_power_up(struct dpram_link_device *dpld)
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ mif_info("+++\n");
+
+ pm_data->last_msg = INT_CMD(INT_CMD_IDPRAM_RESUME_REQ);
+ pm_data->pm_state = IDPRAM_PM_ACTIVE;
+
+ mif_info("---\n");
+}
+
+static void s5p_idpram_halt_suspend(struct dpram_link_device *dpld)
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ mif_info("+++\n");
+
+ complete(&pm_data->down_cmpl);
+
+ mif_info("---\n");
+}
+
+static int s5p_idpram_prepare_suspend(struct dpram_link_device *dpld)
+{
+ struct link_device *ld = &dpld->ld;
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ struct modem_ctl *mc = dpld->ld.mc;
+ struct completion *cmpl;
+ unsigned long timeout;
+ unsigned long rest;
+ int cnt = 0;
+ u16 cmd = INT_CMD(INT_CMD_IDPRAM_SUSPEND_REQ);
+ mif_info("+++\n");
+
+ pm_data->pm_state = IDPRAM_PM_SUSPEND_PREPARE;
+ pm_data->last_msg = 0;
+ s5p_idpram_set_pm_lock(dpld, 1);
+
+ /*
+ * Because, if dpram was powered down, cp dpram random intr was
+ * ocurred. so, fixed by muxing cp dpram intr pin to GPIO output
+ * high,..
+ */
+ gpio_set_value(dpld->gpio_int2cp, 1);
+ s3c_gpio_cfgpin(dpld->gpio_int2cp, S3C_GPIO_OUTPUT);
+
+ /* prevent PDA_ACTIVE status is low */
+ gpio_set_value(mc->gpio_pda_active, 1);
+
+ cmpl = &pm_data->down_cmpl;
+ timeout = IDPRAM_SUSPEND_REQ_TIMEOUT;
+ cnt = 0;
+ do {
+ init_completion(cmpl);
+
+ mif_info("send IDPRAM_SUSPEND_REQ (0x%X)\n", cmd);
+ dpld->send_intr(dpld, cmd);
+
+ rest = wait_for_completion_timeout(cmpl, timeout);
+ if (rest == 0) {
+ cnt++;
+ mif_err("timeout!!! (count = %d)\n", cnt);
+ if (cnt >= 3) {
+ mif_err("ERR! no response from CP\n");
+ break;
+ }
+ }
+ } while (rest == 0);
+
+ switch (pm_data->last_msg) {
+ case INT_CMD(INT_CMD_IDPRAM_SUSPEND_ACK):
+ mif_info("recv IDPRAM_SUSPEND_ACK (0x%X)\n", pm_data->last_msg);
+ pm_data->pm_state = IDPRAM_PM_DPRAM_POWER_DOWN;
+ break;
+
+ default:
+ mif_err("ERR! %s down or not ready!!! (intr 0x%04X)\n",
+ ld->name, dpld->recv_intr(dpld));
+ timeout = msecs_to_jiffies(500);
+ wake_lock_timeout(&pm_data->hold_wlock, timeout);
+ s5p_idpram_set_pm_lock(dpld, 0);
+ break;
+ }
+
+ mif_info("---\n");
+ return 0;
+}
+
+static int s5p_idpram_resume_init(struct dpram_link_device *dpld)
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ mif_info("+++\n");
+
+ pm_data->pm_state = IDPRAM_PM_RESUME_START;
+ pm_data->last_msg = 0;
+
+ dpld->reset_dpram_ipc(dpld);
+
+ /* re-initialize internal dpram gpios */
+ s3c_gpio_cfgpin(dpld->gpio_int2cp, GPIO_IDPRAM_SFN);
+
+ mif_info("---\n");
+ return 0;
+}
+
+static int s5p_idpram_start_resume(struct dpram_link_device *dpld)
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ struct modem_ctl *mc = dpld->ld.mc;
+ unsigned long delay;
+ mif_info("+++ (pm_state = %d)\n", pm_data->pm_state);
+
+ switch (pm_data->pm_state) {
+ /* schedule_work */
+ case IDPRAM_PM_DPRAM_POWER_DOWN:
+ gpio_set_value(mc->gpio_pda_active, 0);
+ msleep(50);
+
+ s5p_idpram_resume_init(dpld);
+ msleep(50);
+
+ gpio_set_value(mc->gpio_pda_active, 1);
+ msleep(20);
+
+ pm_data->resume_try_cnt = 0;
+ wake_lock(&pm_data->hold_wlock);
+
+ delay = msecs_to_jiffies(20);
+ schedule_delayed_work(&pm_data->resume_dwork, delay);
+ break;
+
+ case IDPRAM_PM_RESUME_START:
+ case IDPRAM_PM_SUSPEND_PREPARE:
+ default:
+ break;
+ }
+
+ mif_info("---\n");
+ return 0;
+}
+
+static int s5p_idpram_notify_pm_event(struct notifier_block *this,
+ unsigned long event, void *v)
+{
+ struct idpram_pm_data *pm_data;
+ struct dpram_link_device *dpld;
+ int err;
+ mif_info("+++ (event 0x%08X)\n", (int)event);
+
+ pm_data = container_of(this, struct idpram_pm_data, pm_noti);
+ dpld = container_of(pm_data, struct dpram_link_device, pm_data);
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ err = s5p_idpram_prepare_suspend(dpld);
+ break;
+
+ case PM_POST_SUSPEND:
+ err = s5p_idpram_start_resume(dpld);
+ break;
+
+ default:
+ break;
+ }
+
+ mif_info("---\n");
+ return NOTIFY_DONE;
+}
+
+static int s5p_idpram_pm_init(struct dpram_link_device *dpld,
+ struct modem_data *modem, void (*pm_tx_func)(struct work_struct *work))
+{
+ struct idpram_pm_data *pm_data = &dpld->pm_data;
+ int err;
+ unsigned gpio;
+ unsigned irq;
+ mif_info("+++\n");
+
+ atomic_set(&pm_data->pm_lock, 0);
+
+ init_completion(&pm_data->down_cmpl);
+
+ wake_lock_init(&pm_data->ap_wlock, WAKE_LOCK_SUSPEND, "ap_wakeup");
+ wake_lock_init(&pm_data->hold_wlock, WAKE_LOCK_SUSPEND, "dpram_hold");
+
+ INIT_DELAYED_WORK(&pm_data->tx_dwork, pm_tx_func);
+ INIT_DELAYED_WORK(&pm_data->resume_dwork, s5p_idpram_try_resume);
+
+ pm_data->resume_try_cnt = 0;
+
+ /* register PM notifier */
+ pm_data->pm_noti.notifier_call = s5p_idpram_notify_pm_event;
+ register_pm_notifier(&pm_data->pm_noti);
+
+ /*
+ ** Register gpio_ap_wakeup interrupt handler
+ */
+ gpio = modem->gpio_ap_wakeup;
+ irq = gpio_to_irq(gpio);
+ mif_info("gpio_ap_wakeup: GPIO# %d, IRQ# %d\n", gpio, irq);
+
+ err = request_irq(irq, s5p_ap_wakeup_irq_handler, IRQF_TRIGGER_RISING,
+ "idpram_ap_wakeup", (void *)pm_data);
+ if (err) {
+ mif_err("ERR! request_irq(#%d) fail (err %d)\n", irq, err);
+ goto exit;
+ }
+
+ err = enable_irq_wake(irq);
+ if (err) {
+ mif_err("ERR! enable_irq_wake(#%d) fail (err %d)\n", irq, err);
+ free_irq(irq, (void *)pm_data);
+ goto exit;
+ }
+
+ /*
+ ** Register gpio_cp_dump_int interrupt handler for LPA mode
+ */
+ gpio = modem->gpio_cp_dump_int;
+ irq = gpio_to_irq(gpio);
+ mif_info("gpio_cp_dump_int: GPIO# %d, IRQ# %d\n", gpio, irq);
+
+ err = request_irq(irq, s5p_cp_dump_irq_handler, IRQF_TRIGGER_RISING,
+ "idpram_cp_dump", (void *)pm_data);
+ if (err) {
+ mif_err("ERR! request_irq(#%d) fail (err %d)\n", irq, err);
+ free_irq(gpio_to_irq(modem->gpio_ap_wakeup), (void *)pm_data);
+ goto exit;
+ }
+
+ err = enable_irq_wake(irq);
+ if (err) {
+ mif_err("ERR! enable_irq_wake(#%d) fail (err %d)\n", irq, err);
+ free_irq(gpio_to_irq(modem->gpio_cp_dump_int), (void *)pm_data);
+ free_irq(gpio_to_irq(modem->gpio_ap_wakeup), (void *)pm_data);
+ goto exit;
+ }
+
+exit:
+ mif_err("---\n");
+ return err;
+}
+
+static bool s5p_idpram_int2cp_possible(struct dpram_link_device *dpld)
+{
+ struct modem_ctl *mc = dpld->ld.mc;
+ int i;
+ int level;
+
+ for (i = 1; i <= MAX_CHECK_RETRY_CNT; i++) {
+ level = gpio_get_value(dpld->gpio_int2cp);
+ if (level)
+ break;
+
+ /* CP has not yet received previous command. */
+ mif_info("gpio_ipc_int2cp == 0 (count %d)\n", i);
+
+ usleep_range(1000, 1100);
+ }
+
+ for (i = 1; i <= MAX_CHECK_RETRY_CNT; i++) {
+ level = gpio_get_value(mc->gpio_pda_active);
+ if (level)
+ break;
+
+ /* AP is in transition to LPA mode. */
+ mif_info("gpio_pda_active == 0 (count %d)\n", i);
+
+ usleep_range(1000, 1100);
+ }
+
+ return true;
+}
+#endif
+
+static struct idpram_pm_op idpram_pm_op_set[MAX_AP_TYPE] = {
+#ifdef CONFIG_LINK_DEVICE_S5P_IDPRAM
+ [S5P] = {
+ .pm_init = s5p_idpram_pm_init,
+ .power_down = s5p_idpram_power_down,
+ .power_up = s5p_idpram_power_up,
+ .halt_suspend = s5p_idpram_halt_suspend,
+ .locked = s5p_idpram_is_pm_locked,
+ .int2cp_possible = s5p_idpram_int2cp_possible,
+ },
+#endif
+};
+
+struct idpram_pm_op *idpram_get_pm_op(enum ap_type ap)
+{
+ if (idpram_pm_op_set[ap].exist)
+ return &idpram_pm_op_set[ap];
+ else
+ return NULL;
+}
+
diff --git a/drivers/misc/modem_if/modem_link_device_hsic.c b/drivers/misc/modem_if/modem_link_device_hsic.c
index eb5dfc6..e50e4a8 100644
--- a/drivers/misc/modem_if/modem_link_device_hsic.c
+++ b/drivers/misc/modem_if/modem_link_device_hsic.c
@@ -31,7 +31,7 @@
#include <linux/suspend.h>
#include <linux/version.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_hsic.h"
#include "modem_utils.h"
@@ -269,7 +269,7 @@ static void usb_rx_complete(struct urb *urb)
switch (pipe_data->format) {
case IF_USB_FMT_EP:
if (usb_ld->if_usb_is_main) {
-// pr_urb("IPC-RX", urb);
+ pr_urb("IPC-RX", urb);
iod_format = IPC_FMT;
} else {
iod_format = IPC_BOOT;
@@ -477,13 +477,13 @@ static int _usb_tx_work(struct sk_buff *skb)
if (!pipe_data)
return -ENOENT;
-/*
+
if (iod->format == IPC_FMT && usb_ld->if_usb_is_main)
pr_skb("IPC-TX", skb);
if (iod->format == IPC_RAW)
mif_debug("TX[RAW]\n");
-*/
+
return usb_tx_urb_with_skb(usb_ld->usbdev, skb, pipe_data);
}
@@ -741,11 +741,11 @@ static inline int link_pm_slave_wake(struct link_pm_data *pm_data)
!= HOSTWAKE_TRIGLEVEL) {
if (gpio_get_value(pm_data->gpio_link_slavewake)) {
gpio_set_value(pm_data->gpio_link_slavewake, 0);
- mif_debug("gpio [SWK] set [0]\n");
+ mif_info("gpio [SWK] set [0]\n");
mdelay(5);
}
gpio_set_value(pm_data->gpio_link_slavewake, 1);
- mif_debug("gpio [SWK] set [1]\n");
+ mif_info("gpio [SWK] set [1]\n");
mdelay(5);
/* wait host wake signal*/
@@ -860,7 +860,7 @@ static irqreturn_t link_pm_irq_handler(int irq, void *data)
runtime pm status changes to ACTIVE
*/
value = gpio_get_value(pm_data->gpio_link_hostwake);
- mif_debug("gpio [HWK] get [%d]\n", value);
+ mif_info("gpio [HWK] get [%d]\n", value);
/*
* igonore host wakeup interrupt at suspending kernel
@@ -975,9 +975,7 @@ static int link_pm_notifier_event(struct notifier_block *this,
{
struct link_pm_data *pm_data =
container_of(this, struct link_pm_data, pm_notifier);
-#ifdef CONFIG_UMTS_MODEM_XMM6262
struct modem_ctl *mc = if_usb_get_modemctl(pm_data);
-#endif
switch (event) {
case PM_SUSPEND_PREPARE:
@@ -986,13 +984,11 @@ static int link_pm_notifier_event(struct notifier_block *this,
case PM_RESTORE_PREPARE:
#endif
pm_data->dpm_suspending = true;
-#ifdef CONFIG_UMTS_MODEM_XMM6262
/* set PDA Active High if previous state was LPA */
if (!gpio_get_value(pm_data->gpio_link_active)) {
mif_info("PDA active High to LPA suspend spot\n");
gpio_set_value(mc->gpio_pda_active, 1);
}
-#endif
mif_debug("dpm suspending set to true\n");
return NOTIFY_OK;
case PM_POST_SUSPEND:
@@ -1006,15 +1002,14 @@ static int link_pm_notifier_event(struct notifier_block *this,
queue_delayed_work(pm_data->wq, &pm_data->link_pm_work,
0);
mif_info("post resume\n");
- }
-#ifdef CONFIG_UMTS_MODEM_XMM6262
+ } else {
/* LPA to Kernel suspend and User Freezing task fail resume,
restore to LPA GPIO states. */
- if (!gpio_get_value(pm_data->gpio_link_active)) {
- mif_info("PDA active low to LPA GPIO state\n");
- gpio_set_value(mc->gpio_pda_active, 0);
+ if (!gpio_get_value(pm_data->gpio_link_active)) {
+ mif_info("PDA active low to LPA GPIO state\n");
+ gpio_set_value(mc->gpio_pda_active, 0);
+ }
}
-#endif
mif_debug("dpm suspending set to false\n");
return NOTIFY_OK;
}
@@ -1458,8 +1453,7 @@ static int usb_link_pm_init(struct usb_link_device *usb_ld, void *data)
struct modem_data *pdata =
(struct modem_data *)pdev->dev.platform_data;
struct modemlink_pm_data *pm_pdata;
- struct link_pm_data *pm_data =
- kzalloc(sizeof(struct link_pm_data), GFP_KERNEL);
+ struct link_pm_data *pm_data;
if (!pdata || !pdata->link_pm_data) {
mif_err("platform data is NULL\n");
@@ -1467,6 +1461,7 @@ static int usb_link_pm_init(struct usb_link_device *usb_ld, void *data)
}
pm_pdata = pdata->link_pm_data;
+ pm_data = kzalloc(sizeof(struct link_pm_data), GFP_KERNEL);
if (!pm_data) {
mif_err("link_pm_data is NULL\n");
return -ENOMEM;
diff --git a/drivers/misc/modem_if/modem_link_device_memory.c b/drivers/misc/modem_if/modem_link_device_memory.c
new file mode 100644
index 0000000..9e49e50
--- /dev/null
+++ b/drivers/misc/modem_if/modem_link_device_memory.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/irq.h>
+#include <linux/gpio.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/wakelock.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/if_arp.h>
+#include <linux/platform_device.h>
+#include <linux/kallsyms.h>
+#include <linux/suspend.h>
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+
+#include "modem.h"
+#include "modem_prj.h"
+#include "modem_utils.h"
+#include "modem_link_device_memory.h"
+#ifdef CONFIG_LINK_DEVICE_DPRAM
+#include "modem_link_device_dpram.h"
+#endif
+
+/**
+ * msq_get_free_slot
+ * @trq : pointer to an instance of mem_status_queue structure
+ *
+ * Succeeds always by dropping the oldest slot if a "msq" is full.
+ */
+struct mem_status *msq_get_free_slot(struct mem_status_queue *msq)
+{
+ int qsize = MAX_MEM_LOG_CNT;
+ int in;
+ int out;
+ unsigned long flags;
+ struct mem_status *stat;
+
+ spin_lock_irqsave(&msq->lock, flags);
+
+ in = msq->in;
+ out = msq->out;
+
+ if (circ_get_space(qsize, in, out) < 1) {
+ /* Make the oldest slot empty */
+ out++;
+ msq->out = (out == qsize) ? 0 : out;
+ }
+
+ /* Get a free slot */
+ stat = &msq->stat[in];
+
+ /* Make it as "data" slot */
+ in++;
+ msq->in = (in == qsize) ? 0 : in;
+
+ spin_unlock_irqrestore(&msq->lock, flags);
+
+ memset(stat, 0, sizeof(struct mem_status));
+
+ return stat;
+}
+
+struct mem_status *msq_get_data_slot(struct mem_status_queue *msq)
+{
+ int qsize = MAX_MEM_LOG_CNT;
+ int in;
+ int out;
+ unsigned long flags;
+ struct mem_status *stat;
+
+ spin_lock_irqsave(&msq->lock, flags);
+
+ in = msq->in;
+ out = msq->out;
+
+ if (in == out) {
+ stat = NULL;
+ goto exit;
+ }
+
+ /* Get a data slot */
+ stat = &msq->stat[out];
+
+ /* Make it "free" slot */
+ out++;
+ msq->out = (out == qsize) ? 0 : out;
+
+exit:
+ spin_unlock_irqrestore(&msq->lock, flags);
+ return stat;
+}
+
+/**
+ * memcpy16_from_io
+ * @to: pointer to "real" memory
+ * @from: pointer to IO memory
+ * @count: data length in bytes to be copied
+ *
+ * Copies data from IO memory space to "real" memory space.
+ */
+void memcpy16_from_io(const void *to, const void __iomem *from, u32 count)
+{
+ u16 *d = (u16 *)to;
+ u16 *s = (u16 *)from;
+ u32 words = count >> 1;
+ while (words--)
+ *d++ = ioread16(s++);
+}
+
+/**
+ * memcpy16_to_io
+ * @to: pointer to IO memory
+ * @from: pointer to "real" memory
+ * @count: data length in bytes to be copied
+ *
+ * Copies data from "real" memory space to IO memory space.
+ */
+void memcpy16_to_io(const void __iomem *to, const void *from, u32 count)
+{
+ u16 *d = (u16 *)to;
+ u16 *s = (u16 *)from;
+ u32 words = count >> 1;
+ while (words--)
+ iowrite16(*s++, d++);
+}
+
+/**
+ * memcmp16_to_io
+ * @to: pointer to IO memory
+ * @from: pointer to "real" memory
+ * @count: data length in bytes to be compared
+ *
+ * Compares data from "real" memory space to IO memory space.
+ */
+int memcmp16_to_io(const void __iomem *to, const void *from, u32 count)
+{
+ u16 *d = (u16 *)to;
+ u16 *s = (u16 *)from;
+ int words = count >> 1;
+ int diff = 0;
+ int i;
+ u16 d1;
+ u16 s1;
+
+ for (i = 0; i < words; i++) {
+ d1 = ioread16(d);
+ s1 = *s;
+ if (d1 != s1) {
+ diff++;
+ mif_err("ERR! [%d] d:0x%04X != s:0x%04X\n", i, d1, s1);
+ }
+ d++;
+ s++;
+ }
+
+ return diff;
+}
+
+/**
+ * circ_read16_from_io
+ * @dst: start address of the destination buffer
+ * @src: start address of the buffer in a circular queue
+ * @qsize: size of the circular queue
+ * @out: offset to read
+ * @len: length of data to be read
+ *
+ * Should be invoked after checking data length
+ */
+void circ_read16_from_io(void *dst, void *src, u32 qsize, u32 out, u32 len)
+{
+ if ((out + len) <= qsize) {
+ /* ----- (out) (in) ----- */
+ /* ----- 7f 00 00 7e ----- */
+ memcpy16_from_io(dst, (src + out), len);
+ } else {
+ /* (in) ----------- (out) */
+ /* 00 7e ----------- 7f 00 */
+ unsigned len1 = qsize - out;
+
+ /* 1) data start (out) ~ buffer end */
+ memcpy16_from_io(dst, (src + out), len1);
+
+ /* 2) buffer start ~ data end (in - 1) */
+ memcpy16_from_io((dst + len1), src, (len - len1));
+ }
+}
+
+/**
+ * circ_write16_to_io
+ * @dst: pointer to the start of the circular queue
+ * @src: pointer to the source
+ * @qsize: size of the circular queue
+ * @in: offset to write
+ * @len: length of data to be written
+ *
+ * Should be invoked after checking free space
+ */
+void circ_write16_to_io(void *dst, void *src, u32 qsize, u32 in, u32 len)
+{
+ u32 space;
+
+ if ((in + len) < qsize) {
+ /* (in) ----------- (out) */
+ /* 00 7e ----------- 7f 00 */
+ memcpy16_to_io((dst + in), src, len);
+ } else {
+ /* ----- (out) (in) ----- */
+ /* ----- 7f 00 00 7e ----- */
+
+ /* 1) space start (in) ~ buffer end */
+ space = qsize - in;
+ memcpy16_to_io((dst + in), src, ((len > space) ? space : len));
+
+ /* 2) buffer start ~ data end */
+ if (len > space)
+ memcpy16_to_io(dst, (src + space), (len - space));
+ }
+}
+
+/**
+ * copy_circ_to_user
+ * @dst: start address of the destination buffer
+ * @src: start address of the buffer in a circular queue
+ * @qsize: size of the circular queue
+ * @out: offset to read
+ * @len: length of data to be read
+ *
+ * Should be invoked after checking data length
+ */
+int copy_circ_to_user(void __user *dst, void *src, u32 qsize, u32 out, u32 len)
+{
+ if ((out + len) <= qsize) {
+ /* ----- (out) (in) ----- */
+ /* ----- 7f 00 00 7e ----- */
+ if (copy_to_user(dst, (src + out), len)) {
+ mif_err("ERR! <called by %pf> copy_to_user fail\n",
+ CALLER);
+ return -EFAULT;
+ }
+ } else {
+ /* (in) ----------- (out) */
+ /* 00 7e ----------- 7f 00 */
+ unsigned len1 = qsize - out;
+
+ /* 1) data start (out) ~ buffer end */
+ if (copy_to_user(dst, (src + out), len1)) {
+ mif_err("ERR! <called by %pf> copy_to_user fail\n",
+ CALLER);
+ return -EFAULT;
+ }
+
+ /* 2) buffer start ~ data end (in?) */
+ if (copy_to_user((dst + len1), src, (len - len1))) {
+ mif_err("ERR! <called by %pf> copy_to_user fail\n",
+ CALLER);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * copy_user_to_circ
+ * @dst: pointer to the start of the circular queue
+ * @src: pointer to the source
+ * @qsize: size of the circular queue
+ * @in: offset to write
+ * @len: length of data to be written
+ *
+ * Should be invoked after checking free space
+ */
+int copy_user_to_circ(void *dst, void __user *src, u32 qsize, u32 in, u32 len)
+{
+ u32 space;
+ u32 len1;
+
+ if ((in + len) < qsize) {
+ /* (in) ----------- (out) */
+ /* 00 7e ----------- 7f 00 */
+ if (copy_from_user((dst + in), src, len)) {
+ mif_err("ERR! <called by %pf> copy_from_user fail\n",
+ CALLER);
+ return -EFAULT;
+ }
+ } else {
+ /* ----- (out) (in) ----- */
+ /* ----- 7f 00 00 7e ----- */
+
+ /* 1) space start (in) ~ buffer end */
+ space = qsize - in;
+ len1 = (len > space) ? space : len;
+ if (copy_from_user((dst + in), src, len1)) {
+ mif_err("ERR! <called by %pf> copy_from_user fail\n",
+ CALLER);
+ return -EFAULT;
+ }
+
+ /* 2) buffer start ~ data end */
+ if (len > len1) {
+ if (copy_from_user(dst, (src + space), (len - len1))) {
+ mif_err("ERR! <called by %pf> copy_from_user "
+ "fail\n", CALLER);
+ return -EFAULT;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * print_mem_status
+ * @ld: pointer to an instance of link_device structure
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Prints a snapshot of the status of a SHM.
+ */
+void print_mem_status(struct link_device *ld, struct mem_status *mst)
+{
+ struct utc_time utc;
+ int us = ns2us(mst->ts.tv_nsec);
+
+ ts2utc(&mst->ts, &utc);
+ pr_info("%s: %s: [%02d:%02d:%02d.%06d] "
+ "[%s] ACC{%X %d} "
+ "FMT{TI:%u TO:%u RI:%u RO:%u} "
+ "RAW{TI:%u TO:%u RI:%u RO:%u} "
+ "INTR{RX:0x%X TX:0x%X}\n",
+ MIF_TAG, ld->name, utc.hour, utc.min, utc.sec, us,
+ get_dir_str(mst->dir), mst->magic, mst->access,
+ mst->head[IPC_FMT][TX], mst->tail[IPC_FMT][TX],
+ mst->head[IPC_FMT][RX], mst->tail[IPC_FMT][RX],
+ mst->head[IPC_RAW][TX], mst->tail[IPC_RAW][TX],
+ mst->head[IPC_RAW][RX], mst->tail[IPC_RAW][RX],
+ mst->int2ap, mst->int2cp);
+}
+
+/**
+ * print_circ_status
+ * @ld: pointer to an instance of link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ *
+ * Prints a snapshot of the status of a memory
+ */
+void print_circ_status(struct link_device *ld, int dev, struct mem_status *mst)
+{
+ struct utc_time utc;
+ int us = ns2us(mst->ts.tv_nsec);
+
+ if (dev > IPC_RAW)
+ return;
+
+ ts2utc(&mst->ts, &utc);
+ pr_info("%s: %s: [%02d:%02d:%02d.%06d] "
+ "[%s] %s | TXQ{in:%u out:%u} RXQ{in:%u out:%u}\n",
+ MIF_TAG, ld->name, utc.hour, utc.min, utc.sec, us,
+ get_dir_str(mst->dir), get_dev_name(dev),
+ mst->head[dev][TX], mst->tail[dev][TX],
+ mst->head[dev][RX], mst->tail[dev][RX]);
+}
+
+/**
+ * print_ipc_trace
+ * @ld: pointer to an instance of link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @stat: pointer to an instance of circ_status structure
+ * @ts: pointer to an instance of timespec structure
+ * @buff: start address of a buffer into which RX IPC messages were copied
+ * @rcvd: size of data in the buffer
+ *
+ * Prints IPC messages in a local memory buffer to a kernel log.
+ */
+void print_ipc_trace(struct link_device *ld, int dev, struct circ_status *stat,
+ struct timespec *ts, u8 *buff, u32 rcvd)
+{
+ struct utc_time utc;
+
+ ts2utc(ts, &utc);
+
+ pr_info("%s: [%d-%02d-%02d %02d:%02d:%02d.%03d] "
+ "%s %s_RXQ {IN:%u OUT:%u LEN:%d}\n",
+ MIF_TAG, utc.year, utc.mon, utc.day, utc.hour, utc.min, utc.sec,
+ utc.msec, ld->name, get_dev_name(dev), stat->in, stat->out,
+ stat->size);
+
+ mif_print_dump(buff, rcvd, 4);
+}
+
+/**
+ * capture_mem_dump
+ * @ld: pointer to an instance of link_device structure
+ * @base: base virtual address to a memory interface medium
+ * @size: size of the memory interface medium
+ *
+ * Captures a dump for a memory interface medium.
+ *
+ * Returns the pointer to a memory dump buffer.
+ */
+u8 *capture_mem_dump(struct link_device *ld, u8 *base, u32 size)
+{
+ u8 *buff = kzalloc(size, GFP_ATOMIC);
+ if (!buff) {
+ mif_err("%s: ERR! kzalloc(%d) fail\n", ld->name, size);
+ return NULL;
+ } else {
+ memcpy16_from_io(buff, base, size);
+ return buff;
+ }
+}
+
+/**
+ * trq_get_free_slot
+ * @trq : pointer to an instance of trace_data_queue structure
+ *
+ * Succeeds always by dropping the oldest slot if a "trq" is full.
+ */
+struct trace_data *trq_get_free_slot(struct trace_data_queue *trq)
+{
+ int qsize = MAX_TRACE_SIZE;
+ int in;
+ int out;
+ unsigned long flags;
+ struct trace_data *trd;
+
+ spin_lock_irqsave(&trq->lock, flags);
+
+ in = trq->in;
+ out = trq->out;
+
+ /* The oldest slot can be dropped. */
+ if (circ_get_space(qsize, in, out) < 1) {
+ /* Free the data buffer in the oldest slot */
+ trd = &trq->trd[out];
+ kfree(trd->data);
+
+ /* Make the oldest slot empty */
+ out++;
+ trq->out = (out == qsize) ? 0 : out;
+ }
+
+ /* Get a free slot and make it occupied */
+ trd = &trq->trd[in++];
+ trq->in = (in == qsize) ? 0 : in;
+
+ spin_unlock_irqrestore(&trq->lock, flags);
+
+ memset(trd, 0, sizeof(struct trace_data));
+
+ return trd;
+}
+
+struct trace_data *trq_get_data_slot(struct trace_data_queue *trq)
+{
+ int qsize = MAX_TRACE_SIZE;
+ int in;
+ int out;
+ unsigned long flags;
+ struct trace_data *trd;
+
+ spin_lock_irqsave(&trq->lock, flags);
+
+ in = trq->in;
+ out = trq->out;
+
+ if (circ_get_usage(qsize, in, out) < 1) {
+ spin_unlock_irqrestore(&trq->lock, flags);
+ return NULL;
+ }
+
+ /* Get a data slot and make it empty */
+ trd = &trq->trd[out++];
+ trq->out = (out == qsize) ? 0 : out;
+
+ spin_unlock_irqrestore(&trq->lock, flags);
+
+ return trd;
+}
+
diff --git a/drivers/misc/modem_if/modem_link_device_memory.h b/drivers/misc/modem_if/modem_link_device_memory.h
new file mode 100644
index 0000000..29a84ac
--- /dev/null
+++ b/drivers/misc/modem_if/modem_link_device_memory.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MODEM_LINK_DEVICE_MEMORY_H__
+#define __MODEM_LINK_DEVICE_MEMORY_H__
+
+#include <linux/spinlock.h>
+#include <linux/wakelock.h>
+#include <linux/workqueue.h>
+#include <linux/timer.h>
+#include <linux/notifier.h>
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#elif defined(CONFIG_FB)
+#include <linux/fb.h>
+#endif
+
+#include "modem.h"
+#include "modem_prj.h"
+
+#define DPRAM_MAGIC_CODE 0xAA
+
+/* interrupt masks.*/
+#define INT_MASK_VALID 0x0080
+#define INT_MASK_CMD 0x0040
+#define INT_VALID(x) ((x) & INT_MASK_VALID)
+#define INT_CMD_VALID(x) ((x) & INT_MASK_CMD)
+#define INT_NON_CMD(x) (INT_MASK_VALID | (x))
+#define INT_CMD(x) (INT_MASK_VALID | INT_MASK_CMD | (x))
+
+#define EXT_UDL_MASK 0xF000
+#define EXT_UDL_CMD(x) ((x) & EXT_UDL_MASK)
+#define EXT_INT_VALID_MASK 0x8000
+#define EXT_CMD_VALID_MASK 0x4000
+#define UDL_CMD_VALID_MASK 0x2000
+#define EXT_INT_VALID(x) ((x) & EXT_INT_VALID_MASK)
+#define EXT_CMD_VALID(x) ((x) & EXT_CMD_VALID_MASK)
+#define UDL_CMD_VALID(x) ((x) & UDL_CMD_VALID_MASK)
+#define INT_EXT_CMD(x) (EXT_INT_VALID_MASK | EXT_CMD_VALID_MASK | (x))
+
+#define EXT_CMD_MASK(x) ((x) & 0x0FFF)
+#define EXT_CMD_SET_SPEED_LOW 0x0011
+#define EXT_CMD_SET_SPEED_MID 0x0012
+#define EXT_CMD_SET_SPEED_HIGH 0x0013
+
+#define UDL_RESULT_SUCCESS 0x1
+#define UDL_RESULT_FAIL 0x2
+
+#define UDL_CMD_MASK(x) (((x) >> 8) & 0xF)
+#define UDL_CMD_RECV_READY 0x1
+#define UDL_CMD_DL_START_REQ 0x2
+#define UDL_CMD_DL_START_RESP 0x3
+#define UDL_CMD_IMAGE_SEND_REQ 0x4
+#define UDL_CMD_SEND_DONE_RESP 0x5
+#define UDL_CMD_SEND_DONE_REQ 0x6
+#define UDL_CMD_UPDATE_DONE 0x7
+#define UDL_CMD_STATUS_UPDATE 0x8
+#define UDL_CMD_IMAGE_SEND_RESP 0x9
+#define UDL_CMD_EFS_CLEAR_RESP 0xB
+#define UDL_CMD_ALARM_BOOT_OK 0xC
+#define UDL_CMD_ALARM_BOOT_FAIL 0xD
+
+#define CMD_DL_READY 0xA100
+#define CMD_DL_START_REQ 0x9200
+#define CMD_DL_START_RESP 0xA301
+#define CMD_DL_SEND_REQ 0x9400
+#define CMD_DL_SEND_RESP 0xA501
+#define CMD_DL_DONE_REQ 0x9600
+#define CMD_DL_DONE_RESP 0xA701
+
+#define CMD_UL_RECV_RESP 0x9601
+#define CMD_UL_RECV_DONE_REQ 0xA700
+#define CMD_UL_RECV_DONE_RESP 0x9801
+
+/* special interrupt cmd indicating modem boot failure. */
+#define INT_POWERSAFE_FAIL 0xDEAD
+
+#define INT_MASK_REQ_ACK_F 0x0020
+#define INT_MASK_REQ_ACK_R 0x0010
+#define INT_MASK_RES_ACK_F 0x0008
+#define INT_MASK_RES_ACK_R 0x0004
+#define INT_MASK_SEND_F 0x0002
+#define INT_MASK_SEND_R 0x0001
+
+#define INT_MASK_REQ_ACK_RFS 0x0400 /* Request RES_ACK_RFS */
+#define INT_MASK_RES_ACK_RFS 0x0200 /* Response of REQ_ACK_RFS */
+#define INT_MASK_SEND_RFS 0x0100 /* Indicate sending RFS data */
+
+#define INT_MASK_REQ_ACK_SET \
+ (INT_MASK_REQ_ACK_F | INT_MASK_REQ_ACK_R | INT_MASK_REQ_ACK_RFS)
+
+#define INT_MASK_RES_ACK_SET \
+ (INT_MASK_RES_ACK_F | INT_MASK_RES_ACK_R | INT_MASK_RES_ACK_RFS)
+
+#define INT_CMD_MASK(x) ((x) & 0xF)
+#define INT_CMD_INIT_START 0x1
+#define INT_CMD_INIT_END 0x2
+#define INT_CMD_REQ_ACTIVE 0x3
+#define INT_CMD_RES_ACTIVE 0x4
+#define INT_CMD_REQ_TIME_SYNC 0x5
+#define INT_CMD_CRASH_RESET 0x7
+#define INT_CMD_PHONE_START 0x8
+#define INT_CMD_ERR_DISPLAY 0x9
+#define INT_CMD_CRASH_EXIT 0x9
+#define INT_CMD_CP_DEEP_SLEEP 0xA
+#define INT_CMD_NV_REBUILDING 0xB
+#define INT_CMD_EMER_DOWN 0xC
+#define INT_CMD_PIF_INIT_DONE 0xD
+#define INT_CMD_SILENT_NV_REBUILDING 0xE
+#define INT_CMD_NORMAL_POWER_OFF 0xF
+
+/* AP_IDPRAM PM control command with QSC6085 */
+#define INT_CMD_IDPRAM_SUSPEND_REQ 0xD
+#define INT_CMD_IDPRAM_SUSPEND_ACK 0xB
+#define INT_CMD_IDPRAM_WAKEUP_START 0xE
+#define INT_CMD_IDPRAM_RESUME_REQ 0xC
+
+#define START_FLAG 0x7F
+#define END_FLAG 0x7E
+
+#define DP_MAGIC_DMDL 0x4445444C
+#define DP_MAGIC_UMDL 0x4445444D
+#define DP_DPRAM_SIZE 0x4000
+#define DP_DEFAULT_WRITE_LEN 8168
+#define DP_DEFAULT_DUMP_LEN 16128
+#define DP_DUMP_HEADER_SIZE 7
+
+#define UDL_TIMEOUT (50 * HZ)
+#define UDL_SEND_TIMEOUT (200 * HZ)
+#define FORCE_CRASH_ACK_TIMEOUT (5 * HZ)
+#define DUMP_TIMEOUT (30 * HZ)
+#define DUMP_START_TIMEOUT (100 * HZ)
+#define DUMP_WAIT_TIMEOUT (HZ >> 10) /* 1/1024 second */
+
+#define IDPRAM_SUSPEND_REQ_TIMEOUT (50 * HZ)
+
+#define RES_ACK_WAIT_TIMEOUT 10 /* 10 ms */
+#define REQ_ACK_DELAY 10 /* 10 ms */
+
+#ifdef DEBUG_MODEM_IF
+#define MAX_RETRY_CNT 1
+#else
+#define MAX_RETRY_CNT 3
+#endif
+
+#define MAX_SKB_TXQ_DEPTH 1024
+
+struct memif_boot_map {
+ u32 __iomem *magic;
+ u8 __iomem *buff;
+ u32 __iomem *req;
+ u32 __iomem *resp;
+ u32 space;
+};
+
+struct memif_dload_map {
+ u32 __iomem *magic;
+ u8 __iomem *buff;
+ u32 space;
+};
+
+struct memif_uload_map {
+ u32 __iomem *magic;
+ u8 __iomem *cmd;
+ u32 cmd_size;
+ u8 __iomem *buff;
+ u32 space;
+};
+
+#define DP_BOOT_BUFF_OFFSET 4
+#define DP_DLOAD_MAGIC_SIZE 4
+#define DP_DLOAD_BUFF_OFFSET 4
+#define DP_ULOAD_MAGIC_SIZE 4
+#define DP_ULOAD_BUFF_OFFSET 4
+#define DP_BOOT_REQ_OFFSET 0
+#define DP_BOOT_RESP_OFFSET 8
+#define DP_MBX_SET_SIZE 4
+#define DP_MAX_PAYLOAD_SIZE 0x2000
+
+enum circ_dir_type {
+ TX,
+ RX,
+ MAX_DIR,
+};
+
+enum circ_ptr_type {
+ HEAD,
+ TAIL,
+};
+
+static inline bool circ_valid(u32 qsize, u32 in, u32 out)
+{
+ if (in >= qsize)
+ return false;
+
+ if (out >= qsize)
+ return false;
+
+ return true;
+}
+
+static inline u32 circ_get_space(u32 qsize, u32 in, u32 out)
+{
+ return (in < out) ? (out - in - 1) : (qsize + out - in - 1);
+}
+
+static inline u32 circ_get_usage(u32 qsize, u32 in, u32 out)
+{
+ return (in >= out) ? (in - out) : (qsize - out + in);
+}
+
+static inline u32 circ_new_pointer(u32 qsize, u32 p, u32 len)
+{
+ p += len;
+ return (p < qsize) ? p : (p - qsize);
+}
+
+/**
+ * circ_read
+ * @dst: start address of the destination buffer
+ * @src: start address of the buffer in a circular queue
+ * @qsize: size of the circular queue
+ * @out: offset to read
+ * @len: length of data to be read
+ *
+ * Should be invoked after checking data length
+ */
+static inline void circ_read(void *dst, void *src, u32 qsize, u32 out, u32 len)
+{
+ unsigned len1;
+
+ if ((out + len) <= qsize) {
+ /* ----- (out) (in) ----- */
+ /* ----- 7f 00 00 7e ----- */
+ memcpy(dst, (src + out), len);
+ } else {
+ /* (in) ----------- (out) */
+ /* 00 7e ----------- 7f 00 */
+
+ /* 1) data start (out) ~ buffer end */
+ len1 = qsize - out;
+ memcpy(dst, (src + out), len1);
+
+ /* 2) buffer start ~ data end (in?) */
+ memcpy((dst + len1), src, (len - len1));
+ }
+}
+
+/**
+ * circ_write
+ * @dst: pointer to the start of the circular queue
+ * @src: pointer to the source
+ * @qsize: size of the circular queue
+ * @in: offset to write
+ * @len: length of data to be written
+ *
+ * Should be invoked after checking free space
+ */
+static inline void circ_write(void *dst, void *src, u32 qsize, u32 in, u32 len)
+{
+ u32 space;
+
+ if ((in + len) < qsize) {
+ /* (in) ----------- (out) */
+ /* 00 7e ----------- 7f 00 */
+ memcpy((dst + in), src, len);
+ } else {
+ /* ----- (out) (in) ----- */
+ /* ----- 7f 00 00 7e ----- */
+
+ /* 1) space start (in) ~ buffer end */
+ space = qsize - in;
+ memcpy((dst + in), src, ((len > space) ? space : len));
+
+ /* 2) buffer start ~ data end */
+ if (len > space)
+ memcpy(dst, (src + space), (len - space));
+ }
+}
+
+/**
+ * circ_dir
+ * @dir: communication direction (enum circ_dir_type)
+ *
+ * Returns the direction of a circular queue
+ *
+ */
+static const inline char *circ_dir(enum circ_dir_type dir)
+{
+ if (dir == TX)
+ return "TXQ";
+ else
+ return "RXQ";
+}
+
+/**
+ * circ_ptr
+ * @ptr: circular queue pointer (enum circ_ptr_type)
+ *
+ * Returns the name of a circular queue pointer
+ *
+ */
+static const inline char *circ_ptr(enum circ_ptr_type ptr)
+{
+ if (ptr == HEAD)
+ return "head";
+ else
+ return "tail";
+}
+
+/**
+ * get_dir_str
+ * @dir: communication direction (enum circ_dir_type)
+ *
+ * Returns the direction of a circular queue
+ *
+ */
+static const inline char *get_dir_str(enum circ_dir_type dir)
+{
+ if (dir == TX)
+ return "AP->CP";
+ else
+ return "CP->AP";
+}
+
+void memcpy16_from_io(const void *to, const void __iomem *from, u32 count);
+void memcpy16_to_io(const void __iomem *to, const void *from, u32 count);
+int memcmp16_to_io(const void __iomem *to, const void *from, u32 count);
+void circ_read16_from_io(void *dst, void *src, u32 qsize, u32 out, u32 len);
+void circ_write16_to_io(void *dst, void *src, u32 qsize, u32 in, u32 len);
+int copy_circ_to_user(void __user *dst, void *src, u32 qsize, u32 out, u32 len);
+int copy_user_to_circ(void *dst, void __user *src, u32 qsize, u32 in, u32 len);
+
+#define MAX_MEM_LOG_CNT 8192
+#define MAX_TRACE_SIZE 1024
+
+struct mem_status {
+ /* Timestamp */
+ struct timespec ts;
+
+ /* Direction (TX or RX) */
+ enum circ_dir_type dir;
+
+ /* The status of memory interface at the time */
+ u32 magic;
+ u32 access;
+
+ u32 head[MAX_IPC_DEV][MAX_DIR];
+ u32 tail[MAX_IPC_DEV][MAX_DIR];
+
+ u16 int2ap;
+ u16 int2cp;
+};
+
+struct mem_status_queue {
+ spinlock_t lock;
+ u32 in;
+ u32 out;
+ struct mem_status stat[MAX_MEM_LOG_CNT];
+};
+
+struct circ_status {
+ u8 *buff;
+ u32 qsize; /* the size of a circular buffer */
+ u32 in;
+ u32 out;
+ u32 size; /* the size of free space or received data */
+};
+
+struct trace_data {
+ struct timespec ts;
+ enum dev_format dev;
+ struct circ_status circ_stat;
+ u8 *data;
+ u32 size;
+};
+
+struct trace_data_queue {
+ spinlock_t lock;
+ u32 in;
+ u32 out;
+ struct trace_data trd[MAX_TRACE_SIZE];
+};
+
+struct mem_status *msq_get_free_slot(struct mem_status_queue *msq);
+struct mem_status *msq_get_data_slot(struct mem_status_queue *msq);
+
+void print_mem_status(struct link_device *ld, struct mem_status *mst);
+void print_circ_status(struct link_device *ld, int dev, struct mem_status *mst);
+void print_ipc_trace(struct link_device *ld, int dev, struct circ_status *stat,
+ struct timespec *ts, u8 *buff, u32 rcvd);
+
+u8 *capture_mem_dump(struct link_device *ld, u8 *base, u32 size);
+struct trace_data *trq_get_free_slot(struct trace_data_queue *trq);
+struct trace_data *trq_get_data_slot(struct trace_data_queue *trq);
+
+#endif
+
diff --git a/drivers/misc/modem_if/modem_link_device_mipi.c b/drivers/misc/modem_if/modem_link_device_mipi.c
index f2804e9..948a61c 100644
--- a/drivers/misc/modem_if/modem_link_device_mipi.c
+++ b/drivers/misc/modem_if/modem_link_device_mipi.c
@@ -26,7 +26,7 @@
#include <linux/semaphore.h>
#include <linux/hsi_driver_if.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_mipi.h"
#include "modem_utils.h"
diff --git a/drivers/misc/modem_if/modem_link_device_pld.c b/drivers/misc/modem_if/modem_link_device_pld.c
index b68040e..c0769ff 100644
--- a/drivers/misc/modem_if/modem_link_device_pld.c
+++ b/drivers/misc/modem_if/modem_link_device_pld.c
@@ -25,190 +25,76 @@
#include <linux/if_arp.h>
#include <linux/platform_device.h>
#include <linux/kallsyms.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_pld.h"
#include "modem_utils.h"
-
/*
** Function prototypes for basic DPRAM operations
*/
-static inline void clear_intr(struct dpram_link_device *dpld);
-static inline u16 recv_intr(struct dpram_link_device *dpld);
-static inline void send_intr(struct dpram_link_device *dpld, u16 mask);
-
-static inline u16 get_magic(struct dpram_link_device *dpld);
-static inline void set_magic(struct dpram_link_device *dpld, u16 val);
-static inline u16 get_access(struct dpram_link_device *dpld);
-static inline void set_access(struct dpram_link_device *dpld, u16 val);
-
-static inline u32 get_tx_head(struct dpram_link_device *dpld, int id);
-static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id);
-static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in);
-static inline void set_tx_tail(struct dpram_link_device *dpld, int id, u32 out);
-static inline u8 *get_tx_buff(struct dpram_link_device *dpld, int id);
-static inline u32 get_tx_buff_size(struct dpram_link_device *dpld, int id);
-
-static inline u32 get_rx_head(struct dpram_link_device *dpld, int id);
-static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id);
-static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in);
-static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out);
-static inline u8 *get_rx_buff(struct dpram_link_device *dpld, int id);
-static inline u32 get_rx_buff_size(struct dpram_link_device *dpld, int id);
-
-static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id);
-static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id);
-static inline u16 get_mask_send(struct dpram_link_device *dpld, int id);
-
-static inline bool dpram_circ_valid(u32 size, u32 in, u32 out);
-
-static void handle_cp_crash(struct dpram_link_device *dpld);
-static int trigger_force_cp_crash(struct dpram_link_device *dpld);
+static inline void clear_intr(struct pld_link_device *pld);
+static inline u16 recv_intr(struct pld_link_device *pld);
+static inline void send_intr(struct pld_link_device *pld, u16 mask);
+
+static inline u16 get_magic(struct pld_link_device *pld);
+static inline void set_magic(struct pld_link_device *pld, u16 val);
+static inline u16 get_access(struct pld_link_device *pld);
+static inline void set_access(struct pld_link_device *pld, u16 val);
+
+static inline u32 get_tx_head(struct pld_link_device *pld, int id);
+static inline u32 get_tx_tail(struct pld_link_device *pld, int id);
+static inline void set_tx_head(struct pld_link_device *pld, int id, u32 in);
+static inline void set_tx_tail(struct pld_link_device *pld, int id, u32 out);
+static inline u8 *get_tx_buff(struct pld_link_device *pld, int id);
+static inline u32 get_tx_buff_size(struct pld_link_device *pld, int id);
+
+static inline u32 get_rx_head(struct pld_link_device *pld, int id);
+static inline u32 get_rx_tail(struct pld_link_device *pld, int id);
+static inline void set_rx_head(struct pld_link_device *pld, int id, u32 in);
+static inline void set_rx_tail(struct pld_link_device *pld, int id, u32 out);
+static inline u8 *get_rx_buff(struct pld_link_device *pld, int id);
+static inline u32 get_rx_buff_size(struct pld_link_device *pld, int id);
+
+static inline u16 get_mask_req_ack(struct pld_link_device *pld, int id);
+static inline u16 get_mask_res_ack(struct pld_link_device *pld, int id);
+static inline u16 get_mask_send(struct pld_link_device *pld, int id);
+
+static void handle_cp_crash(struct pld_link_device *pld);
+static int trigger_force_cp_crash(struct pld_link_device *pld);
/*
** Functions for debugging
*/
-static inline void log_dpram_status(struct dpram_link_device *dpld)
-{
- pr_info("mif: %s: {M:0x%X A:%d} {FMT TI:%u TO:%u RI:%u RO:%u} "
- "{RAW TI:%u TO:%u RI:%u RO:%u} {INT:0x%X}\n",
- dpld->ld.mc->name,
- get_magic(dpld), get_access(dpld),
- get_tx_head(dpld, IPC_FMT), get_tx_tail(dpld, IPC_FMT),
- get_rx_head(dpld, IPC_FMT), get_rx_tail(dpld, IPC_FMT),
- get_tx_head(dpld, IPC_RAW), get_tx_tail(dpld, IPC_RAW),
- get_rx_head(dpld, IPC_RAW), get_rx_tail(dpld, IPC_RAW),
- recv_intr(dpld));
-}
-
-static void set_dpram_map(struct dpram_link_device *dpld,
+static void set_dpram_map(struct pld_link_device *pld,
struct mif_irq_map *map)
{
- map->magic = get_magic(dpld);
- map->access = get_access(dpld);
-
- map->fmt_tx_in = get_tx_head(dpld, IPC_FMT);
- map->fmt_tx_out = get_tx_tail(dpld, IPC_FMT);
- map->fmt_rx_in = get_rx_head(dpld, IPC_FMT);
- map->fmt_rx_out = get_rx_tail(dpld, IPC_FMT);
- map->raw_tx_in = get_tx_head(dpld, IPC_RAW);
- map->raw_tx_out = get_tx_tail(dpld, IPC_RAW);
- map->raw_rx_in = get_rx_head(dpld, IPC_RAW);
- map->raw_rx_out = get_rx_tail(dpld, IPC_RAW);
-
- map->cp2ap = recv_intr(dpld);
-}
-
-/*
-** RXB (DPRAM RX buffer) functions
-*/
-static struct dpram_rxb *rxbq_create_pool(unsigned size, int count)
-{
- struct dpram_rxb *rxb;
- u8 *buff;
- int i;
-
- rxb = kzalloc(sizeof(struct dpram_rxb) * count, GFP_KERNEL);
- if (!rxb) {
- mif_info("ERR! kzalloc rxb fail\n");
- return NULL;
- }
-
- buff = kzalloc((size * count), GFP_KERNEL|GFP_DMA);
- if (!buff) {
- mif_info("ERR! kzalloc buff fail\n");
- kfree(rxb);
- return NULL;
- }
-
- for (i = 0; i < count; i++) {
- rxb[i].buff = buff;
- rxb[i].size = size;
- buff += size;
- }
-
- return rxb;
-}
-
-static inline unsigned rxbq_get_page_size(unsigned len)
-{
- return ((len + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT;
-}
+ map->magic = get_magic(pld);
+ map->access = get_access(pld);
-static inline bool rxbq_empty(struct dpram_rxb_queue *rxbq)
-{
- return (rxbq->in == rxbq->out) ? true : false;
-}
-
-static inline int rxbq_free_size(struct dpram_rxb_queue *rxbq)
-{
- int in = rxbq->in;
- int out = rxbq->out;
- int qsize = rxbq->size;
- return (in < out) ? (out - in - 1) : (qsize + out - in - 1);
-}
-
-static inline struct dpram_rxb *rxbq_get_free_rxb(struct dpram_rxb_queue *rxbq)
-{
- struct dpram_rxb *rxb = NULL;
-
- if (likely(rxbq_free_size(rxbq) > 0)) {
- rxb = &rxbq->rxb[rxbq->in];
- rxbq->in++;
- if (rxbq->in >= rxbq->size)
- rxbq->in -= rxbq->size;
- rxb->data = rxb->buff;
- }
-
- return rxb;
-}
-
-static inline int rxbq_size(struct dpram_rxb_queue *rxbq)
-{
- int in = rxbq->in;
- int out = rxbq->out;
- int qsize = rxbq->size;
- return (in >= out) ? (in - out) : (qsize - out + in);
-}
-
-static inline struct dpram_rxb *rxbq_get_data_rxb(struct dpram_rxb_queue *rxbq)
-{
- struct dpram_rxb *rxb = NULL;
-
- if (likely(!rxbq_empty(rxbq))) {
- rxb = &rxbq->rxb[rxbq->out];
- rxbq->out++;
- if (rxbq->out >= rxbq->size)
- rxbq->out -= rxbq->size;
- }
-
- return rxb;
-}
-
-static inline u8 *rxb_put(struct dpram_rxb *rxb, unsigned len)
-{
- rxb->len = len;
- return rxb->data;
-}
+ map->fmt_tx_in = get_tx_head(pld, IPC_FMT);
+ map->fmt_tx_out = get_tx_tail(pld, IPC_FMT);
+ map->fmt_rx_in = get_rx_head(pld, IPC_FMT);
+ map->fmt_rx_out = get_rx_tail(pld, IPC_FMT);
+ map->raw_tx_in = get_tx_head(pld, IPC_RAW);
+ map->raw_tx_out = get_tx_tail(pld, IPC_RAW);
+ map->raw_rx_in = get_rx_head(pld, IPC_RAW);
+ map->raw_rx_out = get_rx_tail(pld, IPC_RAW);
-static inline void rxb_clear(struct dpram_rxb *rxb)
-{
- rxb->data = NULL;
- rxb->len = 0;
+ map->cp2ap = recv_intr(pld);
}
/*
** DPRAM operations
*/
-static int dpram_register_isr(unsigned irq, irqreturn_t (*isr)(int, void*),
+static int pld_register_isr(unsigned irq, irqreturn_t (*isr)(int, void*),
unsigned long flag, const char *name,
- struct dpram_link_device *dpld)
+ struct pld_link_device *pld)
{
int ret = 0;
- ret = request_irq(irq, isr, flag, name, dpld);
+ ret = request_irq(irq, isr, flag, name, pld);
if (ret) {
mif_info("%s: ERR! request_irq fail (err %d)\n", name, ret);
return ret;
@@ -223,31 +109,31 @@ static int dpram_register_isr(unsigned irq, irqreturn_t (*isr)(int, void*),
return 0;
}
-static inline void clear_intr(struct dpram_link_device *dpld)
+static inline void clear_intr(struct pld_link_device *pld)
{
- if (dpld->dpctl->clear_intr)
- dpld->dpctl->clear_intr();
+ if (pld->ext_op && pld->ext_op->clear_intr)
+ pld->ext_op->clear_intr(pld);
}
-static inline u16 recv_intr(struct dpram_link_device *dpld)
+static inline u16 recv_intr(struct pld_link_device *pld)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&dpld->mbx2ap[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->mbx2ap[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&dpld->mbx2ap[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->mbx2ap[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -255,31 +141,31 @@ static inline u16 recv_intr(struct dpram_link_device *dpld)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline void send_intr(struct dpram_link_device *dpld, u16 mask)
+static inline void send_intr(struct pld_link_device *pld, u16 mask)
{
int cnt = 3;
u32 val = 0;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
- iowrite16(PLD_ADDR_MASK(&dpld->mbx2cp[0]),
- dpld->address_buffer);
- iowrite16((u16)mask, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->mbx2cp[0]),
+ pld->address_buffer);
+ iowrite16((u16)mask, pld->base);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&dpld->mbx2cp[0]),
- dpld->address_buffer);
- val = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->mbx2cp[0]),
+ pld->address_buffer);
+ val = ioread16(pld->base);
if (likely(val == mask)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
@@ -287,35 +173,35 @@ static inline void send_intr(struct dpram_link_device *dpld, u16 mask)
udelay(100);
/* Write head value again */
- iowrite16(PLD_ADDR_MASK(&dpld->mbx2cp[0]),
- dpld->address_buffer);
- iowrite16((u16)mask, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->mbx2cp[0]),
+ pld->address_buffer);
+ iowrite16((u16)mask, pld->base);
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
-static inline u16 get_magic(struct dpram_link_device *dpld)
+static inline u16 get_magic(struct pld_link_device *pld)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&dpld->magic_ap2cp[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&dpld->magic_ap2cp[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -324,31 +210,31 @@ static inline u16 get_magic(struct dpram_link_device *dpld)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline void set_magic(struct dpram_link_device *dpld, u16 in)
+static inline void set_magic(struct pld_link_device *pld, u16 in)
{
int cnt = 3;
u32 val = 0;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
- iowrite16(PLD_ADDR_MASK(&dpld->magic_ap2cp[0]),
- dpld->address_buffer);
- iowrite16((u16)in, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]),
+ pld->address_buffer);
+ iowrite16((u16)in, pld->base);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&dpld->magic_ap2cp[0]),
- dpld->address_buffer);
- val = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]),
+ pld->address_buffer);
+ val = ioread16(pld->base);
if (likely(val == in)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
@@ -356,34 +242,34 @@ static inline void set_magic(struct dpram_link_device *dpld, u16 in)
udelay(100);
/* Write head value again */
- iowrite16(PLD_ADDR_MASK(&dpld->magic_ap2cp[0]),
- dpld->address_buffer);
- iowrite16((u16)in, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]),
+ pld->address_buffer);
+ iowrite16((u16)in, pld->base);
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
-static inline u16 get_access(struct dpram_link_device *dpld)
+static inline u16 get_access(struct pld_link_device *pld)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&dpld->access_ap2cp[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&dpld->access_ap2cp[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -392,31 +278,31 @@ static inline u16 get_access(struct dpram_link_device *dpld)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline void set_access(struct dpram_link_device *dpld, u16 in)
+static inline void set_access(struct pld_link_device *pld, u16 in)
{
int cnt = 3;
u32 val = 0;
unsigned long int flags;
- iowrite16(PLD_ADDR_MASK(&dpld->access_ap2cp[0]),
- dpld->address_buffer);
- iowrite16((u16)in, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]),
+ pld->address_buffer);
+ iowrite16((u16)in, pld->base);
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&dpld->access_ap2cp[0]),
- dpld->address_buffer);
- val = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]),
+ pld->address_buffer);
+ val = ioread16(pld->base);
if (likely(val == in)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
@@ -424,34 +310,34 @@ static inline void set_access(struct dpram_link_device *dpld, u16 in)
udelay(100);
/* Write head value again */
- iowrite16(PLD_ADDR_MASK(&dpld->access_ap2cp[0]),
- dpld->address_buffer);
- iowrite16((u16)in, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]),
+ pld->address_buffer);
+ iowrite16((u16)in, pld->base);
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
-static inline u32 get_tx_head(struct dpram_link_device *dpld, int id)
+static inline u32 get_tx_head(struct pld_link_device *pld, int id)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.head)[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.head)[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -461,29 +347,29 @@ static inline u32 get_tx_head(struct dpram_link_device *dpld, int id)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id)
+static inline u32 get_tx_tail(struct pld_link_device *pld, int id)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.tail)[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.tail)[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.tail)[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.tail)[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -493,30 +379,30 @@ static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in)
+static inline void set_tx_head(struct pld_link_device *pld, int id, u32 in)
{
int cnt = 3;
u32 val = 0;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.head)[0]),
- dpld->address_buffer);
- iowrite16((u16)in, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]),
+ pld->address_buffer);
+ iowrite16((u16)in, pld->base);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.head)[0]),
- dpld->address_buffer);
- val = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]),
+ pld->address_buffer);
+ val = ioread16(pld->base);
if (likely(val == in)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
@@ -525,49 +411,49 @@ static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in)
udelay(100);
/* Write head value again */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->txq.head)[0]),
- dpld->address_buffer);
- iowrite16((u16)in, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]),
+ pld->address_buffer);
+ iowrite16((u16)in, pld->base);
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
-static inline void set_tx_tail(struct dpram_link_device *dpld, int id, u32 out)
+static inline void set_tx_tail(struct pld_link_device *pld, int id, u32 out)
{
return;
}
-static inline u8 *get_tx_buff(struct dpram_link_device *dpld, int id)
+static inline u8 *get_tx_buff(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->txq.buff;
+ return pld->dev[id]->txq.buff;
}
-static inline u32 get_tx_buff_size(struct dpram_link_device *dpld, int id)
+static inline u32 get_tx_buff_size(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->txq.size;
+ return pld->dev[id]->txq.size;
}
-static inline u32 get_rx_head(struct dpram_link_device *dpld, int id)
+static inline u32 get_rx_head(struct pld_link_device *pld, int id)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.head)[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.head)[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.head)[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.head)[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -577,29 +463,29 @@ static inline u32 get_rx_head(struct dpram_link_device *dpld, int id)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id)
+static inline u32 get_rx_tail(struct pld_link_device *pld, int id)
{
u16 val1 = 0, val2 = 0, cnt = 3;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
do {
/* Check head value written */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.tail)[0]),
- dpld->address_buffer);
- val1 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]),
+ pld->address_buffer);
+ val1 = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.tail)[0]),
- dpld->address_buffer);
- val2 = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]),
+ pld->address_buffer);
+ val2 = ioread16(pld->base);
if (likely(val1 == val2)) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
@@ -609,35 +495,35 @@ static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id)
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return val1;
}
-static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in)
+static inline void set_rx_head(struct pld_link_device *pld, int id, u32 in)
{
return;
}
-static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out)
+static inline void set_rx_tail(struct pld_link_device *pld, int id, u32 out)
{
int cnt = 3;
u32 val = 0;
unsigned long int flags;
- spin_lock_irqsave(&dpld->pld_lock, flags);
+ spin_lock_irqsave(&pld->pld_lock, flags);
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.tail)[0]),
- dpld->address_buffer);
- iowrite16((u16)out, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]),
+ pld->address_buffer);
+ iowrite16((u16)out, pld->base);
do {
/* Check tail value written */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.tail)[0]),
- dpld->address_buffer);
- val = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]),
+ pld->address_buffer);
+ val = ioread16(pld->base);
if (val == out) {
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
@@ -646,71 +532,60 @@ static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out)
udelay(100);
/* Write tail value again */
- iowrite16(PLD_ADDR_MASK(&(dpld->dev[id]->rxq.tail)[0]),
- dpld->address_buffer);
- iowrite16((u16)out, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]),
+ pld->address_buffer);
+ iowrite16((u16)out, pld->base);
} while (cnt--);
- spin_unlock_irqrestore(&dpld->pld_lock, flags);
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
return;
}
-static inline u8 *get_rx_buff(struct dpram_link_device *dpld, int id)
+static inline u8 *get_rx_buff(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->rxq.buff;
+ return pld->dev[id]->rxq.buff;
}
-static inline u32 get_rx_buff_size(struct dpram_link_device *dpld, int id)
+static inline u32 get_rx_buff_size(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->rxq.size;
+ return pld->dev[id]->rxq.size;
}
-static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id)
+static inline u16 get_mask_req_ack(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->mask_req_ack;
+ return pld->dev[id]->mask_req_ack;
}
-static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id)
+static inline u16 get_mask_res_ack(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->mask_res_ack;
+ return pld->dev[id]->mask_res_ack;
}
-static inline u16 get_mask_send(struct dpram_link_device *dpld, int id)
+static inline u16 get_mask_send(struct pld_link_device *pld, int id)
{
- return dpld->dev[id]->mask_send;
-}
-
-static inline bool dpram_circ_valid(u32 size, u32 in, u32 out)
-{
- if (in >= size)
- return false;
-
- if (out >= size)
- return false;
-
- return true;
+ return pld->dev[id]->mask_send;
}
/* Get free space in the TXQ as well as in & out pointers */
-static inline int dpram_get_txq_space(struct dpram_link_device *dpld, int dev,
- u32 qsize, u32 *in, u32 *out)
+static inline int get_txq_space(struct pld_link_device *pld, int dev, u32 qsize,
+ u32 *in, u32 *out)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
int cnt = 3;
u32 head;
u32 tail;
int space;
do {
- head = get_tx_head(dpld, dev);
- tail = get_tx_tail(dpld, dev);
+ head = get_tx_head(pld, dev);
+ tail = get_tx_tail(pld, dev);
space = (head < tail) ? (tail - head - 1) :
(qsize + tail - head - 1);
mif_debug("%s: %s_TXQ qsize[%u] in[%u] out[%u] space[%u]\n",
ld->name, get_dev_name(dev), qsize, head, tail, space);
- if (dpram_circ_valid(qsize, head, tail)) {
+ if (circ_valid(qsize, head, tail)) {
*in = head;
*out = tail;
return space;
@@ -729,27 +604,27 @@ static inline int dpram_get_txq_space(struct dpram_link_device *dpld, int dev,
return -EINVAL;
}
-static void dpram_reset_tx_circ(struct dpram_link_device *dpld, int dev)
+static void reset_tx_circ(struct pld_link_device *pld, int dev)
{
- set_tx_head(dpld, dev, 0);
- set_tx_tail(dpld, dev, 0);
+ set_tx_head(pld, dev, 0);
+ set_tx_tail(pld, dev, 0);
if (dev == IPC_FMT)
- trigger_force_cp_crash(dpld);
+ trigger_force_cp_crash(pld);
}
/* Get data size in the RXQ as well as in & out pointers */
-static inline int dpram_get_rxq_rcvd(struct dpram_link_device *dpld, int dev,
- u32 qsize, u32 *in, u32 *out)
+static inline int get_rxq_rcvd(struct pld_link_device *pld, int dev, u32 qsize,
+ u32 *in, u32 *out)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
int cnt = 3;
u32 head;
u32 tail;
u32 rcvd;
do {
- head = get_rx_head(dpld, dev);
- tail = get_rx_tail(dpld, dev);
+ head = get_rx_head(pld, dev);
+ tail = get_rx_tail(pld, dev);
if (head == tail) {
*in = head;
*out = tail;
@@ -760,7 +635,7 @@ static inline int dpram_get_rxq_rcvd(struct dpram_link_device *dpld, int dev,
mif_info("%s: %s_RXQ qsize[%u] in[%u] out[%u] rcvd[%u]\n",
ld->name, get_dev_name(dev), qsize, head, tail, rcvd);
- if (dpram_circ_valid(qsize, head, tail)) {
+ if (circ_valid(qsize, head, tail)) {
*in = head;
*out = tail;
return rcvd;
@@ -779,54 +654,20 @@ static inline int dpram_get_rxq_rcvd(struct dpram_link_device *dpld, int dev,
return -EINVAL;
}
-static void dpram_reset_rx_circ(struct dpram_link_device *dpld, int dev)
+static void reset_rx_circ(struct pld_link_device *pld, int dev)
{
- set_rx_head(dpld, dev, 0);
- set_rx_tail(dpld, dev, 0);
+ set_rx_head(pld, dev, 0);
+ set_rx_tail(pld, dev, 0);
if (dev == IPC_FMT)
- trigger_force_cp_crash(dpld);
+ trigger_force_cp_crash(pld);
}
-/*
-** CAUTION : dpram_allow_sleep() MUST be invoked after dpram_wake_up() success
-*/
-static int dpram_wake_up(struct dpram_link_device *dpld)
+static int check_access(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
-
- if (!dpld->dpctl->wakeup)
- return 0;
-
- if (dpld->dpctl->wakeup() < 0) {
- mif_err("%s: ERR! <%pf> DPRAM wakeup fail\n",
- ld->name, __builtin_return_address(0));
- return -EACCES;
- }
-
- atomic_inc(&dpld->accessing);
- return 0;
-}
-
-static void dpram_allow_sleep(struct dpram_link_device *dpld)
-{
- struct link_device *ld = &dpld->ld;
-
- if (!dpld->dpctl->sleep)
- return;
-
- if (atomic_dec_return(&dpld->accessing) <= 0) {
- dpld->dpctl->sleep();
- atomic_set(&dpld->accessing, 0);
- mif_debug("%s: DPRAM sleep possible\n", ld->name);
- }
-}
-
-static int dpram_check_access(struct dpram_link_device *dpld)
-{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
int i;
- u16 magic = get_magic(dpld);
- u16 access = get_access(dpld);
+ u16 magic = get_magic(pld);
+ u16 access = get_access(pld);
if (likely(magic == DPRAM_MAGIC_CODE && access == 1))
return 0;
@@ -836,8 +677,8 @@ static int dpram_check_access(struct dpram_link_device *dpld)
ld->name, magic, access, i);
udelay(100);
- magic = get_magic(dpld);
- access = get_access(dpld);
+ magic = get_magic(pld);
+ access = get_access(pld);
if (likely(magic == DPRAM_MAGIC_CODE && access == 1))
return 0;
}
@@ -846,9 +687,9 @@ static int dpram_check_access(struct dpram_link_device *dpld)
return -EACCES;
}
-static bool dpram_ipc_active(struct dpram_link_device *dpld)
+static bool ipc_active(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
/* Check DPRAM mode */
if (ld->mode != LINK_MODE_IPC) {
@@ -857,8 +698,8 @@ static bool dpram_ipc_active(struct dpram_link_device *dpld)
return false;
}
- if (dpram_check_access(dpld) < 0) {
- mif_info("%s: ERR! <%pf> dpram_check_access fail\n",
+ if (check_access(pld) < 0) {
+ mif_info("%s: ERR! <%pf> check_access fail\n",
ld->name, __builtin_return_address(0));
return false;
}
@@ -866,67 +707,72 @@ static bool dpram_ipc_active(struct dpram_link_device *dpld)
return true;
}
-static void dpram_ipc_write(struct dpram_link_device *dpld, int dev,
+static void pld_ipc_write(struct pld_link_device *pld, int dev,
u32 qsize, u32 in, u32 out, struct sk_buff *skb)
{
- struct link_device *ld = &dpld->ld;
- u8 __iomem *buff = get_tx_buff(dpld, dev);
+ struct link_device *ld = &pld->ld;
+ u8 __iomem *buff = get_tx_buff(pld, dev);
u8 *src = skb->data;
u32 len = skb->len;
u32 inp;
struct mif_irq_map map;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&pld->pld_lock, flags);
if (in < out) {
/* +++++++++ in ---------- out ++++++++++ */
- iowrite16(PLD_ADDR_MASK(&(buff+in)[0]), dpld->address_buffer);
- memcpy(dpld->dp_base, src, len);
+ iowrite16(PLD_ADDR_MASK(&(buff+in)[0]), pld->address_buffer);
+ memcpy(pld->base, src, len);
} else {
/* ------ out +++++++++++ in ------------ */
u32 space = qsize - in;
/* 1) in -> buffer end */
- iowrite16(PLD_ADDR_MASK(&(buff+in)[0]), dpld->address_buffer);
- memcpy(dpld->dp_base, src, ((len > space) ? space : len));
+ iowrite16(PLD_ADDR_MASK(&(buff+in)[0]), pld->address_buffer);
+ memcpy(pld->base, src, ((len > space) ? space : len));
if (len > space) {
iowrite16(PLD_ADDR_MASK(&buff[0]),
- dpld->address_buffer);
- memcpy(dpld->dp_base, (src+space), (len-space));
+ pld->address_buffer);
+ memcpy(pld->base, (src+space), (len-space));
}
}
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
+
/* update new in pointer */
inp = in + len;
if (inp >= qsize)
inp -= qsize;
- set_tx_head(dpld, dev, inp);
+ set_tx_head(pld, dev, inp);
if (dev == IPC_FMT) {
- set_dpram_map(dpld, &map);
+ set_dpram_map(pld, &map);
mif_irq_log(ld->mc->msd, map, "ipc_write", sizeof("ipc_write"));
mif_ipc_log(MIF_IPC_AP2CP, ld->mc->msd, skb->data, skb->len);
}
}
-static int dpram_try_ipc_tx(struct dpram_link_device *dpld, int dev)
+static int pld_try_ipc_tx(struct pld_link_device *pld, int dev)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
struct sk_buff_head *txq = ld->skb_txq[dev];
struct sk_buff *skb;
unsigned long int flags;
- u32 qsize = get_tx_buff_size(dpld, dev);
+ u32 qsize = get_tx_buff_size(pld, dev);
u32 in;
u32 out;
int space;
int copied = 0;
- spin_lock_irqsave(&dpld->tx_rx_lock, flags);
+ spin_lock_irqsave(&pld->tx_rx_lock, flags);
while (1) {
- space = dpram_get_txq_space(dpld, dev, qsize, &in, &out);
+ space = get_txq_space(pld, dev, qsize, &in, &out);
if (unlikely(space < 0)) {
- spin_unlock_irqrestore(&dpld->tx_rx_lock, flags);
- dpram_reset_tx_circ(dpld, dev);
+ spin_unlock_irqrestore(&pld->tx_rx_lock, flags);
+ reset_tx_circ(pld, dev);
return space;
}
@@ -935,9 +781,9 @@ static int dpram_try_ipc_tx(struct dpram_link_device *dpld, int dev)
break;
if (unlikely(space < skb->len)) {
- atomic_set(&dpld->res_required[dev], 1);
+ atomic_set(&pld->res_required[dev], 1);
skb_queue_head(txq, skb);
- spin_unlock_irqrestore(&dpld->tx_rx_lock, flags);
+ spin_unlock_irqrestore(&pld->tx_rx_lock, flags);
mif_info("%s: %s "
"qsize[%u] in[%u] out[%u] free[%u] < len[%u]\n",
ld->name, get_dev_name(dev),
@@ -946,30 +792,30 @@ static int dpram_try_ipc_tx(struct dpram_link_device *dpld, int dev)
}
/* TX if there is enough room in the queue */
- dpram_ipc_write(dpld, dev, qsize, in, out, skb);
+ pld_ipc_write(pld, dev, qsize, in, out, skb);
copied += skb->len;
dev_kfree_skb_any(skb);
}
- spin_unlock_irqrestore(&dpld->tx_rx_lock, flags);
+ spin_unlock_irqrestore(&pld->tx_rx_lock, flags);
return copied;
}
-static void dpram_ipc_rx_task(unsigned long data)
+static void pld_ipc_rx_task(unsigned long data)
{
- struct dpram_link_device *dpld = (struct dpram_link_device *)data;
- struct link_device *ld = &dpld->ld;
+ struct pld_link_device *pld = (struct pld_link_device *)data;
+ struct link_device *ld = &pld->ld;
struct io_device *iod;
- struct dpram_rxb *rxb;
+ struct mif_rxb *rxb;
unsigned qlen;
int i;
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- iod = dpld->iod[i];
- qlen = rxbq_size(&dpld->rxbq[i]);
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ iod = pld->iod[i];
+ qlen = rxbq_size(&pld->rxbq[i]);
while (qlen > 0) {
- rxb = rxbq_get_data_rxb(&dpld->rxbq[i]);
+ rxb = rxbq_get_data_rxb(&pld->rxbq[i]);
iod->recv(iod, ld, rxb->data, rxb->len);
rxb_clear(rxb);
qlen--;
@@ -977,36 +823,39 @@ static void dpram_ipc_rx_task(unsigned long data)
}
}
-static void dpram_ipc_read(struct dpram_link_device *dpld, int dev, u8 *dst,
+static void pld_ipc_read(struct pld_link_device *pld, int dev, u8 *dst,
u8 __iomem *src, u32 out, u32 len, u32 qsize)
{
u8 *ori_det = dst;
unsigned long flags;
+ spin_lock_irqsave(&pld->pld_lock, flags);
+
if ((out + len) <= qsize) {
/* ----- (out) (in) ----- */
/* ----- 7f 00 00 7e ----- */
- iowrite16(PLD_ADDR_MASK(&(src+out)[0]), dpld->address_buffer);
- memcpy(dst, dpld->dp_base, len);
+ iowrite16(PLD_ADDR_MASK(&(src+out)[0]), pld->address_buffer);
+ memcpy(dst, pld->base, len);
} else {
/* (in) ----------- (out) */
/* 00 7e ----------- 7f 00 */
unsigned len1 = qsize - out;
/* 1) out -> buffer end */
- iowrite16(PLD_ADDR_MASK(&(src+out)[0]), dpld->address_buffer);
- memcpy(dst, dpld->dp_base, len1);
+ iowrite16(PLD_ADDR_MASK(&(src+out)[0]), pld->address_buffer);
+ memcpy(dst, pld->base, len1);
/* 2) buffer start -> in */
dst += len1;
- iowrite16(PLD_ADDR_MASK(&src[0]), dpld->address_buffer);
- memcpy(dst, dpld->dp_base, (len - len1));
+ iowrite16(PLD_ADDR_MASK(&src[0]), pld->address_buffer);
+ memcpy(dst, pld->base, (len - len1));
}
- if (dpld->ld.mode == LINK_MODE_IPC && ori_det[0] != 0x7F) {
+ spin_unlock_irqrestore(&pld->pld_lock, flags);
+ if (pld->ld.mode == LINK_MODE_IPC && ori_det[0] != 0x7F) {
mif_info("ipc read error!! in[%d], out[%d]\n",
- get_rx_head(dpld, dev),
- get_rx_tail(dpld, dev));
+ get_rx_head(pld, dev),
+ get_rx_tail(pld, dev));
}
}
@@ -1016,190 +865,106 @@ static void dpram_ipc_read(struct dpram_link_device *dpld, int dev, u8 *dst,
ret == 0 : no data
ret > 0 : valid data
*/
-static int dpram_ipc_recv_data_with_rxb(struct dpram_link_device *dpld, int dev)
+static int pld_ipc_recv_data_with_rxb(struct pld_link_device *pld, int dev)
{
- struct link_device *ld = &dpld->ld;
- struct dpram_rxb *rxb;
- u8 __iomem *src = get_rx_buff(dpld, dev);
- u32 qsize = get_rx_buff_size(dpld, dev);
+ struct link_device *ld = &pld->ld;
+ struct mif_rxb *rxb;
+ u8 __iomem *src = get_rx_buff(pld, dev);
+ u32 qsize = get_rx_buff_size(pld, dev);
u32 in;
u32 out;
u32 rcvd;
struct mif_irq_map map;
unsigned long int flags;
- spin_lock_irqsave(&dpld->tx_rx_lock, flags);
+ spin_lock_irqsave(&pld->tx_rx_lock, flags);
- rcvd = dpram_get_rxq_rcvd(dpld, dev, qsize, &in, &out);
+ rcvd = get_rxq_rcvd(pld, dev, qsize, &in, &out);
if (rcvd <= 0) {
- spin_unlock_irqrestore(&dpld->tx_rx_lock, flags);
+ spin_unlock_irqrestore(&pld->tx_rx_lock, flags);
return rcvd;
}
if (dev == IPC_FMT) {
- set_dpram_map(dpld, &map);
+ set_dpram_map(pld, &map);
mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv"));
}
/* Allocate an rxb */
- rxb = rxbq_get_free_rxb(&dpld->rxbq[dev]);
+ rxb = rxbq_get_free_rxb(&pld->rxbq[dev]);
if (!rxb) {
mif_info("%s: ERR! %s rxbq_get_free_rxb fail\n",
ld->name, get_dev_name(dev));
- spin_unlock_irqrestore(&dpld->tx_rx_lock, flags);
+ spin_unlock_irqrestore(&pld->tx_rx_lock, flags);
return -ENOMEM;
}
/* Read data from each DPRAM buffer */
- dpram_ipc_read(dpld, dev, rxb_put(rxb, rcvd), src, out, rcvd, qsize);
+ pld_ipc_read(pld, dev, rxb_put(rxb, rcvd), src, out, rcvd, qsize);
/* Calculate and set new out */
out += rcvd;
if (out >= qsize)
out -= qsize;
- set_rx_tail(dpld, dev, out);
-
- spin_unlock_irqrestore(&dpld->tx_rx_lock, flags);
- return rcvd;
-}
-
-/*
- ret < 0 : error
- ret == 0 : no data
- ret > 0 : valid data
-*/
-static int dpram_ipc_recv_data_with_skb(struct dpram_link_device *dpld, int dev)
-{
- struct link_device *ld = &dpld->ld;
- struct io_device *iod = dpld->iod[dev];
- struct sk_buff *skb;
- u8 __iomem *src = get_rx_buff(dpld, dev);
- u32 qsize = get_rx_buff_size(dpld, dev);
- u32 in;
- u32 out;
- u32 rcvd;
- int rest;
- u8 *frm;
- u8 *dst;
- unsigned int len;
- unsigned int pad;
- unsigned int tot;
- struct mif_irq_map map;
-
- rcvd = dpram_get_rxq_rcvd(dpld, dev, qsize, &in, &out);
- if (rcvd <= 0)
- return rcvd;
-
- if (dev == IPC_FMT) {
- set_dpram_map(dpld, &map);
- mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv"));
- }
-
- rest = rcvd;
- while (rest > 0) {
- frm = src + out;
- if (unlikely(!sipc5_start_valid(frm[0]))) {
- mif_err("%s: ERR! %s invalid start 0x%02X\n",
- ld->name, get_dev_name(dev), frm[0]);
- skb_queue_purge(&dpld->skb_rxq[dev]);
- return -EBADMSG;
- }
-
- len = sipc5_get_frame_sz16(frm);
- if (unlikely(len > rest)) {
- mif_err("%s: ERR! %s len %d > rest %d\n",
- ld->name, get_dev_name(dev), len, rest);
- skb_queue_purge(&dpld->skb_rxq[dev]);
- return -EBADMSG;
- }
-
- pad = sipc5_calc_padding_size(len);
- tot = len + pad;
-
- /* Allocate an skb */
- skb = dev_alloc_skb(tot);
- if (!skb) {
- mif_err("%s: ERR! %s dev_alloc_skb fail\n",
- ld->name, get_dev_name(dev));
- return -ENOMEM;
- }
-
- /* Read data from each DPRAM buffer */
- dst = skb_put(skb, tot);
- dpram_ipc_read(dpld, dev, dst, src, out, tot, qsize);
- skb_trim(skb, len);
- iod->recv_skb(iod, ld, skb);
-
- /* Calculate and set new out */
- rest -= tot;
- out += tot;
- if (out >= qsize)
- out -= qsize;
- }
-
- set_rx_tail(dpld, dev, out);
+ set_rx_tail(pld, dev, out);
+ spin_unlock_irqrestore(&pld->tx_rx_lock, flags);
return rcvd;
}
-static void non_command_handler(struct dpram_link_device *dpld, u16 non_cmd)
+static void non_command_handler(struct pld_link_device *pld, u16 non_cmd)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
int i = 0;
int ret = 0;
- u16 tx_mask = 0;
+ u16 mask = 0;
- if (!dpram_ipc_active(dpld))
+ if (!ipc_active(pld))
return;
/* Read data from DPRAM */
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- if (dpld->use_skb)
- ret = dpram_ipc_recv_data_with_skb(dpld, i);
- else
- ret = dpram_ipc_recv_data_with_rxb(dpld, i);
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ ret = pld_ipc_recv_data_with_rxb(pld, i);
if (ret < 0)
- dpram_reset_rx_circ(dpld, i);
+ reset_rx_circ(pld, i);
/* Check and process REQ_ACK (at this time, in == out) */
- if (non_cmd & get_mask_req_ack(dpld, i)) {
+ if (non_cmd & get_mask_req_ack(pld, i)) {
mif_debug("%s: send %s_RES_ACK\n",
ld->name, get_dev_name(i));
- tx_mask |= get_mask_res_ack(dpld, i);
+ mask |= get_mask_res_ack(pld, i);
}
}
- if (!dpld->use_skb) {
- /* Schedule soft IRQ for RX */
- tasklet_hi_schedule(&dpld->rx_tsk);
- }
+ /* Schedule soft IRQ for RX */
+ tasklet_hi_schedule(&pld->rx_tsk);
/* Try TX via DPRAM */
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- if (atomic_read(&dpld->res_required[i]) > 0) {
- ret = dpram_try_ipc_tx(dpld, i);
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ if (atomic_read(&pld->res_required[i]) > 0) {
+ ret = pld_try_ipc_tx(pld, i);
if (ret > 0) {
- atomic_set(&dpld->res_required[i], 0);
- tx_mask |= get_mask_send(dpld, i);
+ atomic_set(&pld->res_required[i], 0);
+ mask |= get_mask_send(pld, i);
} else if (ret == -ENOSPC) {
- tx_mask |= get_mask_req_ack(dpld, i);
+ mask |= get_mask_req_ack(pld, i);
}
}
}
- if (tx_mask) {
- send_intr(dpld, INT_NON_CMD(tx_mask));
- mif_debug("%s: send intr 0x%04X\n", ld->name, tx_mask);
+ if (mask) {
+ send_intr(pld, INT_NON_CMD(mask));
+ mif_debug("%s: send intr 0x%04X\n", ld->name, mask);
}
}
-static void handle_cp_crash(struct dpram_link_device *dpld)
+static void handle_cp_crash(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
struct io_device *iod;
int i;
- for (i = 0; i < dpld->max_ipc_dev; i++) {
+ for (i = 0; i < ld->max_ipc_dev; i++) {
mif_info("%s: purging %s_skb_txq\b", ld->name, get_dev_name(i));
skb_queue_purge(ld->skb_txq[i]);
}
@@ -1210,27 +975,27 @@ static void handle_cp_crash(struct dpram_link_device *dpld)
iod = link_get_iod_with_format(ld, IPC_BOOT);
iod->modem_state_changed(iod, STATE_CRASH_EXIT);
- iod = link_get_iod_with_channel(ld, PS_DATA_CH_0);
+ iod = link_get_iod_with_channel(ld, RMNET0_CH_ID);
if (iod)
iodevs_for_each(iod->msd, iodev_netif_stop, 0);
}
static void handle_no_crash_ack(unsigned long arg)
{
- struct dpram_link_device *dpld = (struct dpram_link_device *)arg;
- struct link_device *ld = &dpld->ld;
+ struct pld_link_device *pld = (struct pld_link_device *)arg;
+ struct link_device *ld = &pld->ld;
mif_err("%s: ERR! No CRASH_EXIT ACK from CP\n", ld->mc->name);
- if (!wake_lock_active(&dpld->wlock))
- wake_lock(&dpld->wlock);
+ if (!wake_lock_active(&pld->wlock))
+ wake_lock(&pld->wlock);
- handle_cp_crash(dpld);
+ handle_cp_crash(pld);
}
-static int trigger_force_cp_crash(struct dpram_link_device *dpld)
+static int trigger_force_cp_crash(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
if (ld->mode == LINK_MODE_ULOAD) {
mif_err("%s: CP crash is already in progress\n", ld->mc->name);
@@ -1240,79 +1005,72 @@ static int trigger_force_cp_crash(struct dpram_link_device *dpld)
ld->mode = LINK_MODE_ULOAD;
mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0));
- dpram_wake_up(dpld);
-
- send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT));
+ send_intr(pld, INT_CMD(INT_CMD_CRASH_EXIT));
- mif_add_timer(&dpld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
- handle_no_crash_ack, (unsigned long)dpld);
+ mif_add_timer(&pld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
+ handle_no_crash_ack, (unsigned long)pld);
return 0;
}
-static int dpram_init_ipc(struct dpram_link_device *dpld)
+static int pld_init_ipc(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
int i;
if (ld->mode == LINK_MODE_IPC &&
- get_magic(dpld) == DPRAM_MAGIC_CODE &&
- get_access(dpld) == 1)
+ get_magic(pld) == DPRAM_MAGIC_CODE &&
+ get_access(pld) == 1)
mif_info("%s: IPC already initialized\n", ld->name);
/* Clear pointers in every circular queue */
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- set_tx_head(dpld, i, 0);
- set_tx_tail(dpld, i, 0);
- set_rx_head(dpld, i, 0);
- set_rx_tail(dpld, i, 0);
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ set_tx_head(pld, i, 0);
+ set_tx_tail(pld, i, 0);
+ set_rx_head(pld, i, 0);
+ set_rx_tail(pld, i, 0);
}
/* Initialize variables for efficient TX/RX processing */
- for (i = 0; i < dpld->max_ipc_dev; i++)
- dpld->iod[i] = link_get_iod_with_format(ld, i);
- dpld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW);
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ pld->iod[i] = link_get_iod_with_format(ld, i);
+ pld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW);
- if (dpld->iod[IPC_RAW]->recv_skb)
- dpld->use_skb = true;
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ atomic_set(&pld->res_required[i], 0);
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- atomic_set(&dpld->res_required[i], 0);
- skb_queue_purge(&dpld->skb_rxq[i]);
- }
-
- spin_lock_init(&dpld->tx_rx_lock);
+ spin_lock_init(&pld->tx_rx_lock);
/* Enable IPC */
- atomic_set(&dpld->accessing, 0);
+ atomic_set(&pld->accessing, 0);
- set_magic(dpld, DPRAM_MAGIC_CODE);
- set_access(dpld, 1);
- if (get_magic(dpld) != DPRAM_MAGIC_CODE || get_access(dpld) != 1)
+ set_magic(pld, DPRAM_MAGIC_CODE);
+ set_access(pld, 1);
+ if (get_magic(pld) != DPRAM_MAGIC_CODE || get_access(pld) != 1)
return -EACCES;
ld->mode = LINK_MODE_IPC;
- if (wake_lock_active(&dpld->wlock))
- wake_unlock(&dpld->wlock);
+ if (wake_lock_active(&pld->wlock))
+ wake_unlock(&pld->wlock);
return 0;
}
-static void cmd_req_active_handler(struct dpram_link_device *dpld)
+static void cmd_req_active_handler(struct pld_link_device *pld)
{
- send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE));
+ send_intr(pld, INT_CMD(INT_CMD_RES_ACTIVE));
}
-static void cmd_crash_reset_handler(struct dpram_link_device *dpld)
+static void cmd_crash_reset_handler(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
struct io_device *iod = NULL;
ld->mode = LINK_MODE_ULOAD;
- if (!wake_lock_active(&dpld->wlock))
- wake_lock(&dpld->wlock);
+ if (!wake_lock_active(&pld->wlock))
+ wake_lock(&pld->wlock);
mif_err("%s: Recv 0xC7 (CRASH_RESET)\n", ld->name);
@@ -1323,35 +1081,33 @@ static void cmd_crash_reset_handler(struct dpram_link_device *dpld)
iod->modem_state_changed(iod, STATE_CRASH_RESET);
}
-static void cmd_crash_exit_handler(struct dpram_link_device *dpld)
+static void cmd_crash_exit_handler(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
ld->mode = LINK_MODE_ULOAD;
- if (!wake_lock_active(&dpld->wlock))
- wake_lock(&dpld->wlock);
+ if (!wake_lock_active(&pld->wlock))
+ wake_lock(&pld->wlock);
mif_err("%s: Recv 0xC9 (CRASH_EXIT)\n", ld->name);
- dpram_wake_up(dpld);
-
- del_timer(&dpld->crash_ack_timer);
+ del_timer(&pld->crash_ack_timer);
- if (dpld->ext_op && dpld->ext_op->crash_log)
- dpld->ext_op->crash_log(dpld);
+ if (pld->ext_op && pld->ext_op->crash_log)
+ pld->ext_op->crash_log(pld);
- handle_cp_crash(dpld);
+ handle_cp_crash(pld);
}
-static void cmd_phone_start_handler(struct dpram_link_device *dpld)
+static void cmd_phone_start_handler(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
struct io_device *iod = NULL;
mif_info("%s: Recv 0xC8 (CP_START)\n", ld->name);
- dpram_init_ipc(dpld);
+ pld_init_ipc(pld);
iod = link_get_iod_with_format(ld, IPC_FMT);
if (!iod) {
@@ -1359,8 +1115,8 @@ static void cmd_phone_start_handler(struct dpram_link_device *dpld)
return;
}
- if (dpld->ext_op && dpld->ext_op->cp_start_handler)
- dpld->ext_op->cp_start_handler(dpld);
+ if (pld->ext_op && pld->ext_op->cp_start_handler)
+ pld->ext_op->cp_start_handler(pld);
if (ld->mc->phone_state != STATE_ONLINE) {
mif_info("%s: phone_state: %d -> ONLINE\n",
@@ -1369,32 +1125,32 @@ static void cmd_phone_start_handler(struct dpram_link_device *dpld)
}
mif_info("%s: Send 0xC2 (INIT_END)\n", ld->name);
- send_intr(dpld, INT_CMD(INT_CMD_INIT_END));
+ send_intr(pld, INT_CMD(INT_CMD_INIT_END));
}
-static void command_handler(struct dpram_link_device *dpld, u16 cmd)
+static void command_handler(struct pld_link_device *pld, u16 cmd)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
switch (INT_CMD_MASK(cmd)) {
case INT_CMD_REQ_ACTIVE:
- cmd_req_active_handler(dpld);
+ cmd_req_active_handler(pld);
break;
case INT_CMD_CRASH_RESET:
- dpld->dpram_init_status = DPRAM_INIT_STATE_NONE;
- cmd_crash_reset_handler(dpld);
+ pld->init_status = PLD_INIT_STATE_NONE;
+ cmd_crash_reset_handler(pld);
break;
case INT_CMD_CRASH_EXIT:
- dpld->dpram_init_status = DPRAM_INIT_STATE_NONE;
- cmd_crash_exit_handler(dpld);
+ pld->init_status = PLD_INIT_STATE_NONE;
+ cmd_crash_exit_handler(pld);
break;
case INT_CMD_PHONE_START:
- dpld->dpram_init_status = DPRAM_INIT_STATE_READY;
- cmd_phone_start_handler(dpld);
- complete_all(&dpld->dpram_init_cmd);
+ pld->init_status = PLD_INIT_STATE_READY;
+ cmd_phone_start_handler(pld);
+ complete_all(&pld->dpram_init_cmd);
break;
case INT_CMD_NV_REBUILDING:
@@ -1402,14 +1158,14 @@ static void command_handler(struct dpram_link_device *dpld, u16 cmd)
break;
case INT_CMD_PIF_INIT_DONE:
- complete_all(&dpld->modem_pif_init_done);
+ complete_all(&pld->modem_pif_init_done);
break;
case INT_CMD_SILENT_NV_REBUILDING:
mif_info("%s: SILENT_NV_REBUILDING\n", ld->name);
break;
- case INT_CMD_NORMAL_PWR_OFF:
+ case INT_CMD_NORMAL_POWER_OFF:
/*ToDo:*/
/*kernel_sec_set_cp_ack()*/;
break;
@@ -1424,123 +1180,46 @@ static void command_handler(struct dpram_link_device *dpld, u16 cmd)
}
}
-static void ext_command_handler(struct dpram_link_device *dpld, u16 cmd)
-{
- struct link_device *ld = &dpld->ld;
- u16 resp;
-
- switch (EXT_CMD_MASK(cmd)) {
- case EXT_CMD_SET_SPEED_LOW:
- if (dpld->dpctl->setup_speed) {
- dpld->dpctl->setup_speed(DPRAM_SPEED_LOW);
- resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_LOW);
- send_intr(dpld, resp);
- }
- break;
-
- case EXT_CMD_SET_SPEED_MID:
- if (dpld->dpctl->setup_speed) {
- dpld->dpctl->setup_speed(DPRAM_SPEED_MID);
- resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_MID);
- send_intr(dpld, resp);
- }
- break;
-
- case EXT_CMD_SET_SPEED_HIGH:
- if (dpld->dpctl->setup_speed) {
- dpld->dpctl->setup_speed(DPRAM_SPEED_HIGH);
- resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_HIGH);
- send_intr(dpld, resp);
- }
- break;
-
- default:
- mif_info("%s: unknown command 0x%04X\n", ld->name, cmd);
- break;
- }
-}
-
-static void udl_command_handler(struct dpram_link_device *dpld, u16 cmd)
-{
- struct link_device *ld = &dpld->ld;
-
- if (cmd & UDL_RESULT_FAIL) {
- mif_info("%s: ERR! Command failed: %04x\n", ld->name, cmd);
- return;
- }
-
- switch (UDL_CMD_MASK(cmd)) {
- case UDL_CMD_RECV_READY:
- mif_debug("%s: Send CP-->AP RECEIVE_READY\n", ld->name);
- send_intr(dpld, CMD_IMG_START_REQ);
- break;
- default:
- complete_all(&dpld->udl_cmd_complete);
- }
-}
-
-static irqreturn_t dpram_irq_handler(int irq, void *data)
+static irqreturn_t pld_irq_handler(int irq, void *data)
{
- struct dpram_link_device *dpld = (struct dpram_link_device *)data;
- struct link_device *ld = (struct link_device *)&dpld->ld;
+ struct pld_link_device *pld = (struct pld_link_device *)data;
+ struct link_device *ld = (struct link_device *)&pld->ld;
u16 int2ap = 0;
if (unlikely(ld->mode == LINK_MODE_OFFLINE))
return IRQ_HANDLED;
- if (dpram_wake_up(dpld) < 0) {
- log_dpram_status(dpld);
- trigger_force_cp_crash(dpld);
- return IRQ_HANDLED;
- }
-
- int2ap = recv_intr(dpld);
+ int2ap = recv_intr(pld);
if (unlikely(int2ap == INT_POWERSAFE_FAIL)) {
mif_info("%s: int2ap == INT_POWERSAFE_FAIL\n", ld->name);
goto exit;
} else if (int2ap == 0x1234 || int2ap == 0xDBAB || int2ap == 0xABCD) {
- if (dpld->ext_op && dpld->ext_op->dload_cmd_handler) {
- dpld->ext_op->dload_cmd_handler(dpld, int2ap);
+ if (pld->ext_op && pld->ext_op->dload_cmd_handler) {
+ pld->ext_op->dload_cmd_handler(pld, int2ap);
goto exit;
}
}
- if (unlikely(EXT_UDL_CMD(int2ap))) {
- if (likely(EXT_INT_VALID(int2ap))) {
- if (UDL_CMD_VALID(int2ap))
- udl_command_handler(dpld, int2ap);
- else if (EXT_CMD_VALID(int2ap))
- ext_command_handler(dpld, int2ap);
- else
- mif_info("%s: ERR! invalid intr 0x%04X\n",
- ld->name, int2ap);
- } else {
- mif_info("%s: ERR! invalid intr 0x%04X\n",
- ld->name, int2ap);
- }
+ if (likely(INT_VALID(int2ap))) {
+ if (unlikely(INT_CMD_VALID(int2ap)))
+ command_handler(pld, int2ap);
+ else
+ non_command_handler(pld, int2ap);
} else {
- if (likely(INT_VALID(int2ap))) {
- if (unlikely(INT_CMD_VALID(int2ap)))
- command_handler(dpld, int2ap);
- else
- non_command_handler(dpld, int2ap);
- } else {
- mif_info("%s: ERR! invalid intr 0x%04X\n",
- ld->name, int2ap);
- }
+ mif_info("%s: ERR! invalid intr 0x%04X\n",
+ ld->name, int2ap);
}
exit:
- clear_intr(dpld);
- dpram_allow_sleep(dpld);
+ clear_intr(pld);
return IRQ_HANDLED;
}
-static void dpram_send_ipc(struct link_device *ld, int dev,
+static void pld_send_ipc(struct link_device *ld, int dev,
struct io_device *iod, struct sk_buff *skb)
{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ struct pld_link_device *pld = to_pld_link_device(ld);
struct sk_buff_head *txq = ld->skb_txq[dev];
int ret;
u16 mask;
@@ -1551,46 +1230,31 @@ static void dpram_send_ipc(struct link_device *ld, int dev,
ld->name, get_dev_name(dev), txq->qlen);
}
- if (dpram_wake_up(dpld) < 0) {
- trigger_force_cp_crash(dpld);
- return;
- }
-
- if (!dpram_ipc_active(dpld))
+ if (!ipc_active(pld))
goto exit;
- if (atomic_read(&dpld->res_required[dev]) > 0) {
+ if (atomic_read(&pld->res_required[dev]) > 0) {
mif_debug("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev));
goto exit;
}
- ret = dpram_try_ipc_tx(dpld, dev);
+ ret = pld_try_ipc_tx(pld, dev);
if (ret > 0) {
- mask = get_mask_send(dpld, dev);
- send_intr(dpld, INT_NON_CMD(mask));
+ mask = get_mask_send(pld, dev);
+ send_intr(pld, INT_NON_CMD(mask));
} else if (ret == -ENOSPC) {
- mask = get_mask_req_ack(dpld, dev);
- send_intr(dpld, INT_NON_CMD(mask));
+ mask = get_mask_req_ack(pld, dev);
+ send_intr(pld, INT_NON_CMD(mask));
mif_info("%s: Send REQ_ACK 0x%04X\n", ld->name, mask);
} else {
- mif_info("%s: dpram_try_ipc_tx fail (err %d)\n", ld->name, ret);
+ mif_info("%s: pld_try_ipc_tx fail (err %d)\n", ld->name, ret);
}
exit:
- dpram_allow_sleep(dpld);
-}
-
-static int dpram_download_bin(struct link_device *ld, struct sk_buff *skb)
-{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
-
- if (dpld->ext_op && dpld->ext_op->dload_bin)
- return dpld->ext_op->dload_bin(dpld, skb);
- else
- return -ENODEV;
+ return;
}
-static int dpram_send(struct link_device *ld, struct io_device *iod,
+static int pld_send(struct link_device *ld, struct io_device *iod,
struct sk_buff *skb)
{
enum dev_format dev = iod->format;
@@ -1601,16 +1265,13 @@ static int dpram_send(struct link_device *ld, struct io_device *iod,
case IPC_RAW:
case IPC_RFS:
if (likely(ld->mode == LINK_MODE_IPC)) {
- dpram_send_ipc(ld, dev, iod, skb);
+ pld_send_ipc(ld, dev, iod, skb);
} else {
mif_info("%s: ld->mode != LINK_MODE_IPC\n", ld->name);
dev_kfree_skb_any(skb);
}
return len;
- case IPC_BOOT:
- return dpram_download_bin(ld, skb);
-
default:
mif_info("%s: ERR! no TXQ for %s\n", ld->name, iod->name);
dev_kfree_skb_any(skb);
@@ -1618,48 +1279,38 @@ static int dpram_send(struct link_device *ld, struct io_device *iod,
}
}
-static int dpram_force_dump(struct link_device *ld, struct io_device *iod)
+static int pld_force_dump(struct link_device *ld, struct io_device *iod)
{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
- trigger_force_cp_crash(dpld);
+ struct pld_link_device *pld = to_pld_link_device(ld);
+ trigger_force_cp_crash(pld);
return 0;
}
-static void dpram_dump_memory(struct link_device *ld, char *buff)
+static int pld_dump_start(struct link_device *ld, struct io_device *iod)
{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
- u8 __iomem *base = dpld->dpctl->dp_base;
- u32 size = dpld->dpctl->dp_size;
+ struct pld_link_device *pld = to_pld_link_device(ld);
- dpram_wake_up(dpld);
- memcpy(buff, base, size);
-}
-
-static int dpram_dump_start(struct link_device *ld, struct io_device *iod)
-{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
-
- if (dpld->ext_op && dpld->ext_op->dump_start)
- return dpld->ext_op->dump_start(dpld);
+ if (pld->ext_op && pld->ext_op->dump_start)
+ return pld->ext_op->dump_start(pld);
else
return -ENODEV;
}
-static int dpram_dump_update(struct link_device *ld, struct io_device *iod,
+static int pld_dump_update(struct link_device *ld, struct io_device *iod,
unsigned long arg)
{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ struct pld_link_device *pld = to_pld_link_device(ld);
- if (dpld->ext_op && dpld->ext_op->dump_update)
- return dpld->ext_op->dump_update(dpld, (void *)arg);
+ if (pld->ext_op && pld->ext_op->dump_update)
+ return pld->ext_op->dump_update(pld, (void *)arg);
else
return -ENODEV;
}
-static int dpram_ioctl(struct link_device *ld, struct io_device *iod,
+static int pld_ioctl(struct link_device *ld, struct io_device *iod,
unsigned int cmd, unsigned long arg)
{
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ struct pld_link_device *pld = to_pld_link_device(ld);
int err = 0;
/*
@@ -1669,11 +1320,11 @@ static int dpram_ioctl(struct link_device *ld, struct io_device *iod,
switch (cmd) {
case IOCTL_DPRAM_INIT_STATUS:
mif_debug("%s: get dpram init status\n", ld->name);
- return dpld->dpram_init_status;
+ return pld->init_status;
default:
- if (dpld->ext_ioctl) {
- err = dpld->ext_ioctl(dpld, iod, cmd, arg);
+ if (pld->ext_ioctl) {
+ err = pld->ext_ioctl(pld, iod, cmd, arg);
} else {
mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd);
err = -EINVAL;
@@ -1685,97 +1336,97 @@ static int dpram_ioctl(struct link_device *ld, struct io_device *iod,
return err;
}
-static int dpram_table_init(struct dpram_link_device *dpld)
+static int pld_table_init(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
u8 __iomem *dp_base;
int i;
- if (!dpld->dp_base) {
- mif_info("%s: ERR! dpld->dp_base == NULL\n", ld->name);
+ if (!pld->base) {
+ mif_info("%s: ERR! pld->base == NULL\n", ld->name);
return -EINVAL;
}
- dp_base = dpld->dp_base;
+ dp_base = pld->base;
/* Map for IPC */
- if (dpld->dpctl->ipc_map) {
- memcpy(&dpld->ipc_map, dpld->dpctl->ipc_map,
- sizeof(struct dpram_ipc_map));
+ if (pld->dpram->ipc_map) {
+ memcpy(&pld->ipc_map, pld->dpram->ipc_map,
+ sizeof(struct pld_ipc_map));
}
- dpld->magic_ap2cp = dpld->ipc_map.magic_ap2cp;
- dpld->access_ap2cp = dpld->ipc_map.access_ap2cp;
+ pld->magic_ap2cp = pld->ipc_map.magic_ap2cp;
+ pld->access_ap2cp = pld->ipc_map.access_ap2cp;
- dpld->magic_cp2ap = dpld->ipc_map.magic_cp2ap;
- dpld->access_cp2ap = dpld->ipc_map.access_cp2ap;
+ pld->magic_cp2ap = pld->ipc_map.magic_cp2ap;
+ pld->access_cp2ap = pld->ipc_map.access_cp2ap;
- dpld->address_buffer = dpld->ipc_map.address_buffer;
+ pld->address_buffer = pld->ipc_map.address_buffer;
- for (i = 0; i < dpld->max_ipc_dev; i++)
- dpld->dev[i] = &dpld->ipc_map.dev[i];
- dpld->mbx2ap = dpld->ipc_map.mbx_cp2ap;
- dpld->mbx2cp = dpld->ipc_map.mbx_ap2cp;
+ for (i = 0; i < ld->max_ipc_dev; i++)
+ pld->dev[i] = &pld->ipc_map.dev[i];
+ pld->mbx2ap = pld->ipc_map.mbx_cp2ap;
+ pld->mbx2cp = pld->ipc_map.mbx_ap2cp;
/* Map for booting */
- if (dpld->ext_op && dpld->ext_op->init_boot_map) {
- dpld->ext_op->init_boot_map(dpld);
+ if (pld->ext_op && pld->ext_op->init_boot_map) {
+ pld->ext_op->init_boot_map(pld);
} else {
- dpld->bt_map.magic = (u32 *)(dp_base);
- dpld->bt_map.buff = (u8 *)(dp_base + DP_BOOT_BUFF_OFFSET);
- dpld->bt_map.size = dpld->dp_size - 8;
+ pld->bt_map.magic = (u32 *)(dp_base);
+ pld->bt_map.buff = (u8 *)(dp_base + DP_BOOT_BUFF_OFFSET);
+ pld->bt_map.space = pld->size - 8;
}
/* Map for download (FOTA, UDL, etc.) */
- if (dpld->ext_op && dpld->ext_op->init_dl_map) {
- dpld->ext_op->init_dl_map(dpld);
+ if (pld->ext_op && pld->ext_op->init_dl_map) {
+ pld->ext_op->init_dl_map(pld);
} else {
- dpld->dl_map.magic = (u32 *)(dp_base);
- dpld->dl_map.buff = (u8 *)(dp_base + DP_DLOAD_BUFF_OFFSET);
+ pld->dl_map.magic = (u32 *)(dp_base);
+ pld->dl_map.buff = (u8 *)(dp_base + DP_DLOAD_BUFF_OFFSET);
}
/* Map for upload mode */
- if (dpld->ext_op && dpld->ext_op->init_ul_map) {
- dpld->ext_op->init_ul_map(dpld);
+ if (pld->ext_op && pld->ext_op->init_ul_map) {
+ pld->ext_op->init_ul_map(pld);
} else {
- dpld->ul_map.magic = (u32 *)(dp_base);
- dpld->ul_map.buff = (u8 *)(dp_base + DP_ULOAD_BUFF_OFFSET);
+ pld->ul_map.magic = (u32 *)(dp_base);
+ pld->ul_map.buff = (u8 *)(dp_base + DP_ULOAD_BUFF_OFFSET);
}
return 0;
}
-static void dpram_setup_common_op(struct dpram_link_device *dpld)
-{
- dpld->clear_intr = clear_intr;
- dpld->recv_intr = recv_intr;
- dpld->send_intr = send_intr;
- dpld->get_magic = get_magic;
- dpld->set_magic = set_magic;
- dpld->get_access = get_access;
- dpld->set_access = set_access;
- dpld->get_tx_head = get_tx_head;
- dpld->get_tx_tail = get_tx_tail;
- dpld->set_tx_head = set_tx_head;
- dpld->set_tx_tail = set_tx_tail;
- dpld->get_tx_buff = get_tx_buff;
- dpld->get_tx_buff_size = get_tx_buff_size;
- dpld->get_rx_head = get_rx_head;
- dpld->get_rx_tail = get_rx_tail;
- dpld->set_rx_head = set_rx_head;
- dpld->set_rx_tail = set_rx_tail;
- dpld->get_rx_buff = get_rx_buff;
- dpld->get_rx_buff_size = get_rx_buff_size;
- dpld->get_mask_req_ack = get_mask_req_ack;
- dpld->get_mask_res_ack = get_mask_res_ack;
- dpld->get_mask_send = get_mask_send;
-}
-
-static int dpram_link_init(struct link_device *ld, struct io_device *iod)
+static void pld_setup_common_op(struct pld_link_device *pld)
+{
+ pld->clear_intr = clear_intr;
+ pld->recv_intr = recv_intr;
+ pld->send_intr = send_intr;
+ pld->get_magic = get_magic;
+ pld->set_magic = set_magic;
+ pld->get_access = get_access;
+ pld->set_access = set_access;
+ pld->get_tx_head = get_tx_head;
+ pld->get_tx_tail = get_tx_tail;
+ pld->set_tx_head = set_tx_head;
+ pld->set_tx_tail = set_tx_tail;
+ pld->get_tx_buff = get_tx_buff;
+ pld->get_tx_buff_size = get_tx_buff_size;
+ pld->get_rx_head = get_rx_head;
+ pld->get_rx_tail = get_rx_tail;
+ pld->set_rx_head = set_rx_head;
+ pld->set_rx_tail = set_rx_tail;
+ pld->get_rx_buff = get_rx_buff;
+ pld->get_rx_buff_size = get_rx_buff_size;
+ pld->get_mask_req_ack = get_mask_req_ack;
+ pld->get_mask_res_ack = get_mask_res_ack;
+ pld->get_mask_send = get_mask_send;
+}
+
+static int pld_link_init(struct link_device *ld, struct io_device *iod)
{
return 0;
}
-static void dpram_link_terminate(struct link_device *ld, struct io_device *iod)
+static void pld_link_terminate(struct link_device *ld, struct io_device *iod)
{
return;
}
@@ -1783,11 +1434,11 @@ static void dpram_link_terminate(struct link_device *ld, struct io_device *iod)
struct link_device *pld_create_link_device(struct platform_device *pdev)
{
struct modem_data *mdm_data = NULL;
- struct dpram_link_device *dpld = NULL;
+ struct pld_link_device *pld = NULL;
struct link_device *ld = NULL;
struct resource *res = NULL;
resource_size_t res_size;
- struct modemlink_dpram_control *dpctl = NULL;
+ struct modemlink_dpram_data *dpram = NULL;
unsigned long task_data;
int ret = 0;
int i = 0;
@@ -1803,19 +1454,19 @@ struct link_device *pld_create_link_device(struct platform_device *pdev)
mif_info("modem = %s\n", mdm_data->name);
mif_info("link device = %s\n", mdm_data->link_name);
- if (!mdm_data->dpram_ctl) {
- mif_info("ERR! mdm_data->dpram_ctl == NULL\n");
+ if (!mdm_data->dpram) {
+ mif_info("ERR! no mdm_data->dpram\n");
goto err;
}
- dpctl = mdm_data->dpram_ctl;
+ dpram = mdm_data->dpram;
/* Alloc DPRAM link device structure */
- dpld = kzalloc(sizeof(struct dpram_link_device), GFP_KERNEL);
- if (!dpld) {
- mif_info("ERR! kzalloc dpld fail\n");
+ pld = kzalloc(sizeof(struct pld_link_device), GFP_KERNEL);
+ if (!pld) {
+ mif_info("ERR! kzalloc pld fail\n");
goto err;
}
- ld = &dpld->ld;
+ ld = &pld->ld;
/* Retrieve modem data and DPRAM control data from the modem data */
ld->mdm_data = mdm_data;
@@ -1823,30 +1474,30 @@ struct link_device *pld_create_link_device(struct platform_device *pdev)
ld->ipc_version = mdm_data->ipc_version;
/* Retrieve the most basic data for IPC from the modem data */
- dpld->dpctl = dpctl;
- dpld->dp_type = dpctl->dp_type;
+ pld->dpram = dpram;
+ pld->type = dpram->type;
if (mdm_data->ipc_version < SIPC_VER_50) {
- if (!dpctl->max_ipc_dev) {
+ if (!mdm_data->max_ipc_dev) {
mif_info("ERR! no max_ipc_dev\n");
goto err;
}
- ld->aligned = dpctl->aligned;
- dpld->max_ipc_dev = dpctl->max_ipc_dev;
+ ld->aligned = dpram->aligned;
+ ld->max_ipc_dev = mdm_data->max_ipc_dev;
} else {
ld->aligned = 1;
- dpld->max_ipc_dev = MAX_SIPC5_DEV;
+ ld->max_ipc_dev = MAX_SIPC5_DEV;
}
/* Set attributes as a link device */
- ld->init_comm = dpram_link_init;
- ld->terminate_comm = dpram_link_terminate;
- ld->send = dpram_send;
- ld->force_dump = dpram_force_dump;
- ld->dump_start = dpram_dump_start;
- ld->dump_update = dpram_dump_update;
- ld->ioctl = dpram_ioctl;
+ ld->init_comm = pld_link_init;
+ ld->terminate_comm = pld_link_terminate;
+ ld->send = pld_send;
+ ld->force_dump = pld_force_dump;
+ ld->dump_start = pld_dump_start;
+ ld->dump_update = pld_dump_update;
+ ld->ioctl = pld_ioctl;
INIT_LIST_HEAD(&ld->list);
@@ -1858,14 +1509,13 @@ struct link_device *pld_create_link_device(struct platform_device *pdev)
ld->skb_txq[IPC_RFS] = &ld->sk_rfs_tx_q;
/* Set up function pointers */
- dpram_setup_common_op(dpld);
- dpld->dpram_dump = dpram_dump_memory;
- dpld->ext_op = dpram_get_ext_op(mdm_data->modem_type);
- if (dpld->ext_op && dpld->ext_op->ioctl)
- dpld->ext_ioctl = dpld->ext_op->ioctl;
+ pld_setup_common_op(pld);
+ pld->ext_op = pld_get_ext_op(mdm_data->modem_type);
+ if (pld->ext_op && pld->ext_op->ioctl)
+ pld->ext_ioctl = pld->ext_op->ioctl;
/* Retrieve DPRAM resource */
- if (!dpctl->dp_base) {
+ if (!dpram->base) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
mif_info("%s: ERR! platform_get_resource fail\n",
@@ -1874,59 +1524,54 @@ struct link_device *pld_create_link_device(struct platform_device *pdev)
}
res_size = resource_size(res);
- dpctl->dp_base = ioremap_nocache(res->start, res_size);
- dpctl->dp_size = res_size;
+ dpram->base = ioremap_nocache(res->start, res_size);
+ dpram->size = res_size;
}
- dpld->dp_base = dpctl->dp_base;
- dpld->dp_size = dpctl->dp_size;
+ pld->base = dpram->base;
+ pld->size = dpram->size;
- mif_info("%s: dp_type %d, aligned %d, dp_base 0x%08X, dp_size %d\n",
- ld->name, dpld->dp_type, ld->aligned, (int)dpld->dp_base,
- dpld->dp_size);
+ mif_info("%s: type %d, aligned %d, base 0x%08X, size %d\n",
+ ld->name, pld->type, ld->aligned, (int)pld->base, pld->size);
/* Initialize DPRAM map (physical map -> logical map) */
- ret = dpram_table_init(dpld);
+ ret = pld_table_init(pld);
if (ret < 0) {
- mif_info("%s: ERR! dpram_table_init fail (err %d)\n",
+ mif_info("%s: ERR! pld_table_init fail (err %d)\n",
ld->name, ret);
goto err;
}
- spin_lock_init(&dpld->pld_lock);
+ spin_lock_init(&pld->pld_lock);
/* Disable IPC */
- set_magic(dpld, 0);
- set_access(dpld, 0);
+ set_magic(pld, 0);
+ set_access(pld, 0);
- dpld->dpram_init_status = DPRAM_INIT_STATE_NONE;
+ pld->init_status = PLD_INIT_STATE_NONE;
/* Initialize locks, completions, and bottom halves */
- snprintf(dpld->wlock_name, DP_MAX_NAME_LEN, "%s_wlock", ld->name);
- wake_lock_init(&dpld->wlock, WAKE_LOCK_SUSPEND, dpld->wlock_name);
-
- init_completion(&dpld->dpram_init_cmd);
- init_completion(&dpld->modem_pif_init_done);
- init_completion(&dpld->udl_start_complete);
- init_completion(&dpld->udl_cmd_complete);
- init_completion(&dpld->dump_start_complete);
- init_completion(&dpld->dump_recv_done);
+ snprintf(pld->wlock_name, MIF_MAX_NAME_LEN, "%s_wlock", ld->name);
+ wake_lock_init(&pld->wlock, WAKE_LOCK_SUSPEND, pld->wlock_name);
- task_data = (unsigned long)dpld;
- tasklet_init(&dpld->rx_tsk, dpram_ipc_rx_task, task_data);
+ init_completion(&pld->dpram_init_cmd);
+ init_completion(&pld->modem_pif_init_done);
+ init_completion(&pld->udl_start_complete);
+ init_completion(&pld->udl_cmd_complete);
+ init_completion(&pld->crash_start_complete);
+ init_completion(&pld->crash_recv_done);
- /* Prepare SKB queue head for RX processing */
- for (i = 0; i < dpld->max_ipc_dev; i++)
- skb_queue_head_init(&dpld->skb_rxq[i]);
+ task_data = (unsigned long)pld;
+ tasklet_init(&pld->rx_tsk, pld_ipc_rx_task, task_data);
/* Prepare RXB queue */
- qsize = DPRAM_MAX_RXBQ_SIZE;
- for (i = 0; i < dpld->max_ipc_dev; i++) {
- bsize = rxbq_get_page_size(get_rx_buff_size(dpld, i));
- dpld->rxbq[i].size = qsize;
- dpld->rxbq[i].in = 0;
- dpld->rxbq[i].out = 0;
- dpld->rxbq[i].rxb = rxbq_create_pool(bsize, qsize);
- if (!dpld->rxbq[i].rxb) {
+ qsize = MAX_RXBQ_SIZE;
+ for (i = 0; i < ld->max_ipc_dev; i++) {
+ bsize = rxbq_get_page_size(get_rx_buff_size(pld, i));
+ pld->rxbq[i].size = qsize;
+ pld->rxbq[i].in = 0;
+ pld->rxbq[i].out = 0;
+ pld->rxbq[i].rxb = rxbq_create_pool(bsize, qsize);
+ if (!pld->rxbq[i].rxb) {
mif_info("%s: ERR! %s rxbq_create_pool fail\n",
ld->name, get_dev_name(i));
goto err;
@@ -1936,44 +1581,37 @@ struct link_device *pld_create_link_device(struct platform_device *pdev)
}
/* Prepare a multi-purpose miscellaneous buffer */
- dpld->buff = kzalloc(dpld->dp_size, GFP_KERNEL);
- if (!dpld->buff) {
- mif_info("%s: ERR! kzalloc dpld->buff fail\n", ld->name);
+ pld->buff = kzalloc(pld->size, GFP_KERNEL);
+ if (!pld->buff) {
+ mif_info("%s: ERR! kzalloc pld->buff fail\n", ld->name);
goto err;
}
/* Retrieve DPRAM IRQ GPIO# */
- dpld->gpio_dpram_int = mdm_data->gpio_dpram_int;
+ pld->gpio_ipc_int2ap = mdm_data->gpio_ipc_int2ap;
/* Retrieve DPRAM IRQ# */
- if (!dpctl->dpram_irq) {
- dpctl->dpram_irq = platform_get_irq_byname(pdev, "dpram_irq");
- if (dpctl->dpram_irq < 0) {
- mif_info("%s: ERR! platform_get_irq_byname fail\n",
- ld->name);
- goto err;
- }
- }
- dpld->irq = dpctl->dpram_irq;
+ pld->irq = mdm_data->irq_ipc_int2ap;
/* Retrieve DPRAM IRQ flags */
- if (!dpctl->dpram_irq_flags)
- dpctl->dpram_irq_flags = (IRQF_NO_SUSPEND | IRQF_TRIGGER_LOW);
- dpld->irq_flags = dpctl->dpram_irq_flags;
+ if (mdm_data->irqf_ipc_int2ap)
+ pld->irq_flags = mdm_data->irqf_ipc_int2ap;
+ else
+ pld->irq_flags = (IRQF_NO_SUSPEND | IRQF_TRIGGER_LOW);
/* Register DPRAM interrupt handler */
- snprintf(dpld->irq_name, DP_MAX_NAME_LEN, "%s_irq", ld->name);
- ret = dpram_register_isr(dpld->irq, dpram_irq_handler, dpld->irq_flags,
- dpld->irq_name, dpld);
+ snprintf(pld->irq_name, MIF_MAX_NAME_LEN, "%s_irq", ld->name);
+ ret = pld_register_isr(pld->irq, pld_irq_handler, pld->irq_flags,
+ pld->irq_name, pld);
if (ret)
goto err;
return ld;
err:
- if (dpld) {
- kfree(dpld->buff);
- kfree(dpld);
+ if (pld) {
+ kfree(pld->buff);
+ kfree(pld);
}
return NULL;
diff --git a/drivers/misc/modem_if/modem_link_device_pld.h b/drivers/misc/modem_if/modem_link_device_pld.h
index 2656110..2690faa 100644
--- a/drivers/misc/modem_if/modem_link_device_pld.h
+++ b/drivers/misc/modem_if/modem_link_device_pld.h
@@ -1,5 +1,4 @@
/*
- * Copyright (C) 2011 Google, Inc.
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -12,181 +11,134 @@
* GNU General Public License for more details.
*
*/
-#ifndef __MODEM_LINK_DEVICE_DPRAM_H__
-#define __MODEM_LINK_DEVICE_DPRAM_H__
-
-#include <linux/spinlock.h>
-#include <linux/wakelock.h>
-#include <linux/workqueue.h>
-#include <linux/timer.h>
-#include <linux/platform_data/modem.h>
-
-#include "modem_prj.h"
-
-#define DPRAM_MAGIC_CODE 0xAA
-
-/* interrupt masks.*/
-#define INT_MASK_VALID 0x0080
-#define INT_MASK_CMD 0x0040
-#define INT_VALID(x) ((x) & INT_MASK_VALID)
-#define INT_CMD_VALID(x) ((x) & INT_MASK_CMD)
-#define INT_NON_CMD(x) (INT_MASK_VALID | (x))
-#define INT_CMD(x) (INT_MASK_VALID | INT_MASK_CMD | (x))
-
-#define EXT_UDL_MASK 0xF000
-#define EXT_UDL_CMD(x) ((x) & EXT_UDL_MASK)
-#define EXT_INT_VALID_MASK 0x8000
-#define EXT_CMD_VALID_MASK 0x4000
-#define UDL_CMD_VALID_MASK 0x2000
-#define EXT_INT_VALID(x) ((x) & EXT_INT_VALID_MASK)
-#define EXT_CMD_VALID(x) ((x) & EXT_CMD_VALID_MASK)
-#define UDL_CMD_VALID(x) ((x) & UDL_CMD_VALID_MASK)
-#define INT_EXT_CMD(x) (EXT_INT_VALID_MASK | EXT_CMD_VALID_MASK | (x))
-
-#define EXT_CMD_MASK(x) ((x) & 0x0FFF)
-#define EXT_CMD_SET_SPEED_LOW 0x0011
-#define EXT_CMD_SET_SPEED_MID 0x0012
-#define EXT_CMD_SET_SPEED_HIGH 0x0013
-
-#define UDL_RESULT_SUCCESS 0x1
-#define UDL_RESULT_FAIL 0x2
-
-#define UDL_CMD_MASK(x) (((x) >> 8) & 0xF)
-#define UDL_CMD_RECV_READY 0x1
-#define UDL_CMD_DL_START_REQ 0x2
-#define UDL_CMD_DL_START_RESP 0x3
-#define UDL_CMD_IMAGE_SEND_REQ 0x4
-#define UDL_CMD_SEND_DONE_RESP 0x5
-#define UDL_CMD_SEND_DONE_REQ 0x6
-#define UDL_CMD_UPDATE_DONE 0x7
-#define UDL_CMD_STATUS_UPDATE 0x8
-#define UDL_CMD_IMAGE_SEND_RESP 0x9
-#define UDL_CMD_EFS_CLEAR_RESP 0xB
-#define UDL_CMD_ALARM_BOOT_OK 0xC
-#define UDL_CMD_ALARM_BOOT_FAIL 0xD
-
-#define CMD_IMG_START_REQ 0x9200
-#define CMD_IMG_SEND_REQ 0x9400
-#define CMD_DL_SEND_DONE_REQ 0x9600
-#define CMD_UL_RECV_RESP 0x9601
-#define CMD_UL_RECV_DONE_RESP 0x9801
-
-/* special interrupt cmd indicating modem boot failure. */
-#define INT_POWERSAFE_FAIL 0xDEAD
-
-#define INT_MASK_REQ_ACK_RFS 0x0400 /* Request RES_ACK_RFS */
-#define INT_MASK_RES_ACK_RFS 0x0200 /* Response of REQ_ACK_RFS */
-#define INT_MASK_SEND_RFS 0x0100 /* Indicate sending RFS data */
-
-#define INT_MASK_REQ_ACK_F 0x0020
-#define INT_MASK_REQ_ACK_R 0x0010
-#define INT_MASK_RES_ACK_F 0x0008
-#define INT_MASK_RES_ACK_R 0x0004
-#define INT_MASK_SEND_F 0x0002
-#define INT_MASK_SEND_R 0x0001
-
-#define INT_MASK_REQ_ACK_RFS 0x0400 /* Request RES_ACK_RFS */
-#define INT_MASK_RES_ACK_RFS 0x0200 /* Response of REQ_ACK_RFS */
-#define INT_MASK_SEND_RFS 0x0100 /* Indicate sending RFS data */
-
-#define INT_MASK_RES_ACK_SET \
- (INT_MASK_RES_ACK_F | INT_MASK_RES_ACK_R | INT_MASK_RES_ACK_RFS)
-
-#define INT_MASK_SEND_SET \
- (INT_MASK_SEND_F | INT_MASK_SEND_R | INT_MASK_SEND_RFS)
-
-#define INT_CMD_MASK(x) ((x) & 0xF)
-#define INT_CMD_INIT_START 0x1
-#define INT_CMD_INIT_END 0x2
-#define INT_CMD_REQ_ACTIVE 0x3
-#define INT_CMD_RES_ACTIVE 0x4
-#define INT_CMD_REQ_TIME_SYNC 0x5
-#define INT_CMD_CRASH_RESET 0x7
-#define INT_CMD_PHONE_START 0x8
-#define INT_CMD_ERR_DISPLAY 0x9
-#define INT_CMD_CRASH_EXIT 0x9
-#define INT_CMD_CP_DEEP_SLEEP 0xA
-#define INT_CMD_NV_REBUILDING 0xB
-#define INT_CMD_EMER_DOWN 0xC
-#define INT_CMD_PIF_INIT_DONE 0xD
-#define INT_CMD_SILENT_NV_REBUILDING 0xE
-#define INT_CMD_NORMAL_PWR_OFF 0xF
-
-#define START_FLAG 0x7F
-#define END_FLAG 0x7E
-
-#define DP_MAGIC_DMDL 0x4445444C
-#define DP_MAGIC_UMDL 0x4445444D
-#define DP_DPRAM_SIZE 0x4000
-#define DP_DEFAULT_WRITE_LEN 8168
-#define DP_DEFAULT_DUMP_LEN 16128
-#define DP_DUMP_HEADER_SIZE 7
-
-#define UDL_TIMEOUT (50 * HZ)
-#define UDL_SEND_TIMEOUT (200 * HZ)
-#define FORCE_CRASH_ACK_TIMEOUT (5 * HZ)
-#define DUMP_TIMEOUT (30 * HZ)
-#define DUMP_START_TIMEOUT (100 * HZ)
-#define DUMP_WAIT_TIMEOUT (HZ >> 10) /* 1/1024 second */
+#ifndef __MODEM_LINK_DEVICE_PLD_H__
+#define __MODEM_LINK_DEVICE_PLD_H__
-#define PLD_ADDR_MASK(x) (0x00003FFF & (unsigned long)(x))
+#include "modem_link_device_memory.h"
-enum host_boot_mode {
- HOST_BOOT_MODE_NORMAL,
- HOST_BOOT_MODE_DUMP,
-};
+#define PLD_ADDR_MASK(x) (0x00003FFF & (unsigned long)(x))
-enum dpram_init_status {
- DPRAM_INIT_STATE_NONE,
- DPRAM_INIT_STATE_READY,
+enum pld_init_status {
+ PLD_INIT_STATE_NONE,
+ PLD_INIT_STATE_READY,
};
-struct dpram_boot_img {
- char *addr;
- int size;
- enum host_boot_mode mode;
- unsigned req;
- unsigned resp;
-};
+#if 1
+#define MAX_RXBQ_SIZE 256
-#define MAX_PAYLOAD_SIZE 0x2000
-struct dpram_boot_frame {
- unsigned req; /* AP->CP request */
- unsigned resp; /* response expected by AP */
- ssize_t len; /* data size in the buffer */
- unsigned offset; /* offset to write into DPRAM */
- char data[MAX_PAYLOAD_SIZE];
-};
+struct mif_rxb {
+ u8 *buff;
+ unsigned size;
-/* buffer type for modem image */
-struct dpram_dump_arg {
- char *buff; /* pointer to the buffer */
- int buff_size; /* buffer size */
- unsigned req; /* AP->CP request */
- unsigned resp; /* CP->AP response */
- bool cmd; /* AP->CP command */
+ u8 *data;
+ unsigned len;
};
-struct dpram_firmware {
- char *firmware;
+struct mif_rxb_queue {
int size;
- int is_delta;
-};
-enum dpram_link_mode {
- DPRAM_LINK_MODE_INVALID = 0,
- DPRAM_LINK_MODE_IPC,
- DPRAM_LINK_MODE_BOOT,
- DPRAM_LINK_MODE_DLOAD,
- DPRAM_LINK_MODE_ULOAD,
+ int in;
+ int out;
+ struct mif_rxb *rxb;
};
-struct dpram_boot_map {
- u32 __iomem *magic;
- u8 __iomem *buff;
- u32 __iomem *req;
- u32 __iomem *resp;
- u32 size;
-};
+/*
+** RXB (DPRAM RX buffer) functions
+*/
+static inline struct mif_rxb *rxbq_create_pool(unsigned size, int count)
+{
+ struct mif_rxb *rxb;
+ u8 *buff;
+ int i;
+
+ rxb = kzalloc(sizeof(struct mif_rxb) * count, GFP_KERNEL);
+ if (!rxb) {
+ mif_info("ERR! kzalloc rxb fail\n");
+ return NULL;
+ }
+
+ buff = kzalloc((size * count), GFP_KERNEL|GFP_DMA);
+ if (!buff) {
+ mif_info("ERR! kzalloc buff fail\n");
+ kfree(rxb);
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ rxb[i].buff = buff;
+ rxb[i].size = size;
+ buff += size;
+ }
+
+ return rxb;
+}
+
+static inline unsigned rxbq_get_page_size(unsigned len)
+{
+ return ((len + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT;
+}
+
+static inline bool rxbq_empty(struct mif_rxb_queue *rxbq)
+{
+ return (rxbq->in == rxbq->out) ? true : false;
+}
+
+static inline int rxbq_free_size(struct mif_rxb_queue *rxbq)
+{
+ int in = rxbq->in;
+ int out = rxbq->out;
+ int qsize = rxbq->size;
+ return (in < out) ? (out - in - 1) : (qsize + out - in - 1);
+}
+
+static inline struct mif_rxb *rxbq_get_free_rxb(struct mif_rxb_queue *rxbq)
+{
+ struct mif_rxb *rxb = NULL;
+
+ if (likely(rxbq_free_size(rxbq) > 0)) {
+ rxb = &rxbq->rxb[rxbq->in];
+ rxbq->in++;
+ if (rxbq->in >= rxbq->size)
+ rxbq->in -= rxbq->size;
+ rxb->data = rxb->buff;
+ }
+
+ return rxb;
+}
+
+static inline int rxbq_size(struct mif_rxb_queue *rxbq)
+{
+ int in = rxbq->in;
+ int out = rxbq->out;
+ int qsize = rxbq->size;
+ return (in >= out) ? (in - out) : (qsize - out + in);
+}
+
+static inline struct mif_rxb *rxbq_get_data_rxb(struct mif_rxb_queue *rxbq)
+{
+ struct mif_rxb *rxb = NULL;
+
+ if (likely(!rxbq_empty(rxbq))) {
+ rxb = &rxbq->rxb[rxbq->out];
+ rxbq->out++;
+ if (rxbq->out >= rxbq->size)
+ rxbq->out -= rxbq->size;
+ }
+
+ return rxb;
+}
+
+static inline u8 *rxb_put(struct mif_rxb *rxb, unsigned len)
+{
+ rxb->len = len;
+ return rxb->data;
+}
+
+static inline void rxb_clear(struct mif_rxb *rxb)
+{
+ rxb->data = NULL;
+ rxb->len = 0;
+}
+#endif
struct qc_dpram_boot_map {
u8 __iomem *buff;
@@ -195,39 +147,14 @@ struct qc_dpram_boot_map {
u16 __iomem *count;
};
-struct dpram_dload_map {
- u32 __iomem *magic;
- u8 __iomem *buff;
-};
-
-struct dpram_uload_map {
- u32 __iomem *magic;
- u8 __iomem *buff;
-};
-
-struct dpram_ota_header {
- u8 start_index;
- u16 nframes;
- u16 curframe;
- u16 len;
-
-} __packed;
-
-struct ul_header {
- u8 bop;
- u16 total_frame;
- u16 curr_frame;
- u16 len;
-} __packed;
-
-struct dpram_udl_param {
+struct qc_dpram_udl_param {
unsigned char *addr;
unsigned int size;
unsigned int count;
unsigned int tag;
};
-struct dpram_udl_check {
+struct qc_dpram_udl_check {
unsigned int total_size;
unsigned int rest_size;
unsigned int send_size;
@@ -236,180 +163,38 @@ struct dpram_udl_check {
unsigned int boot_complete;
};
-#define DP_BOOT_BUFF_OFFSET 4
-#define DP_DLOAD_BUFF_OFFSET 4
-#define DP_ULOAD_BUFF_OFFSET 4
-#define DP_BOOT_REQ_OFFSET 0
-#define DP_BOOT_RESP_OFFSET 8
-
-#define MAX_WQ_NAME_LENGTH 64
-
-#define DPRAM_MAX_RXBQ_SIZE 256
-
-struct dpram_rxb {
- u8 *buff;
- unsigned size;
+struct pld_ext_op;
- u8 *data;
- unsigned len;
-};
-
-struct dpram_rxb_queue {
- int size;
- int in;
- int out;
- struct dpram_rxb *rxb;
-};
-
-/*
- mbx_ap2cp + 0x0
- magic_code +
- access_enable +
- padding +
- mbx_cp2ap + 0x1000
- magic_code +
- access_enable +
- padding +
- fmt_tx_head + fmt_tx_tail + fmt_tx_buff + 0x2000
- raw_tx_head + raw_tx_tail + raw_tx_buff +
- fmt_rx_head + fmt_rx_tail + fmt_rx_buff + 0x3000
- raw_rx_head + raw_rx_tail + raw_rx_buff +
- = 2 +
- 4094 +
- 2 +
- 4094 +
- 2 +
- 2 +
- 2 + 2 + 1020 +
- 2 + 2 + 3064 +
- 2 + 2 + 1020 +
- 2 + 2 + 3064
- */
-
-#define DP_PLD_FMT_TX_BUFF_SZ 1024
-#define DP_PLD_RAW_TX_BUFF_SZ 3072
-#define DP_PLD_FMT_RX_BUFF_SZ 1024
-#define DP_PLD_RAW_RX_BUFF_SZ 3072
-
-#define MAX_MSM_EDPRAM_IPC_DEV 2 /* FMT, RAW */
-
-struct dpram_ipc_pld_map {
- u16 mbx_ap2cp;
- u16 magic_ap2cp;
- u16 access_ap2cp;
- u16 fmt_tx_head;
- u16 raw_tx_head;
- u16 fmt_rx_tail;
- u16 raw_rx_tail;
- u16 temp1;
- u8 padding1[4080];
-
- u16 mbx_cp2ap;
- u16 magic_cp2ap;
- u16 access_cp2ap;
- u16 fmt_tx_tail;
- u16 raw_tx_tail;
- u16 fmt_rx_head;
- u16 raw_rx_head;
- u16 temp2;
- u8 padding2[4080];
-
- u8 fmt_tx_buff[DP_PLD_FMT_TX_BUFF_SZ];
- u8 raw_tx_buff[DP_PLD_RAW_TX_BUFF_SZ];
- u8 fmt_rx_buff[DP_PLD_RAW_TX_BUFF_SZ];
- u8 raw_rx_buff[DP_PLD_RAW_RX_BUFF_SZ];
-
- u8 padding3[16384];
-
- u16 address_buffer;
-};
-
-/*
- magic_code +
- access_enable +
- fmt_tx_head + fmt_tx_tail + fmt_tx_buff +
- raw_tx_head + raw_tx_tail + raw_tx_buff +
- fmt_rx_head + fmt_rx_tail + fmt_rx_buff +
- raw_rx_head + raw_rx_tail + raw_rx_buff +
- mbx_cp2ap +
- mbx_ap2cp
- = 2 +
- 2 +
- 2 + 2 + 1336 +
- 2 + 2 + 4564 +
- 2 + 2 + 1336 +
- 2 + 2 + 9124 +
- 2 +
- 2
- = 16384
-*/
-#define DP_16K_FMT_TX_BUFF_SZ 1336
-#define DP_16K_RAW_TX_BUFF_SZ 4564
-#define DP_16K_FMT_RX_BUFF_SZ 1336
-#define DP_16K_RAW_RX_BUFF_SZ 9124
-
-struct dpram_ipc_16k_map {
- u16 magic;
- u16 access;
-
- u16 fmt_tx_head;
- u16 fmt_tx_tail;
- u8 fmt_tx_buff[DP_16K_FMT_TX_BUFF_SZ];
-
- u16 raw_tx_head;
- u16 raw_tx_tail;
- u8 raw_tx_buff[DP_16K_RAW_TX_BUFF_SZ];
-
- u16 fmt_rx_head;
- u16 fmt_rx_tail;
- u8 fmt_rx_buff[DP_16K_FMT_RX_BUFF_SZ];
-
- u16 raw_rx_head;
- u16 raw_rx_tail;
- u8 raw_rx_buff[DP_16K_RAW_RX_BUFF_SZ];
-
- u16 mbx_cp2ap;
- u16 mbx_ap2cp;
-};
-
-#define DP_MAX_NAME_LEN 32
-
-struct dpram_ext_op;
-
-struct dpram_link_device {
+struct pld_link_device {
struct link_device ld;
- /* The mode of this DPRAM link device */
- enum dpram_link_mode mode;
-
/* DPRAM address and size */
- u8 __iomem *dp_base; /* DPRAM base virtual address */
- u32 dp_size; /* DPRAM size */
- enum dpram_type dp_type; /* DPRAM type */
+ enum dpram_type type; /* DPRAM type */
+ u8 __iomem *base; /* DPRAM base virtual address */
+ u32 size; /* DPRAM size */
/* DPRAM IRQ GPIO# */
- unsigned gpio_dpram_int;
+ unsigned gpio_ipc_int2ap;
/* DPRAM IRQ from CP */
int irq;
unsigned long irq_flags;
- char irq_name[DP_MAX_NAME_LEN];
+ char irq_name[MIF_MAX_NAME_LEN];
/* Link to DPRAM control functions dependent on each platform */
- int max_ipc_dev;
- struct modemlink_dpram_control *dpctl;
+ struct modemlink_dpram_data *dpram;
/* Physical configuration -> logical configuration */
union {
- struct dpram_boot_map bt_map;
+ struct memif_boot_map bt_map;
struct qc_dpram_boot_map qc_bt_map;
};
- struct dpram_dload_map dl_map;
- struct dpram_uload_map ul_map;
+ struct memif_dload_map dl_map;
+ struct memif_uload_map ul_map;
/* IPC device map */
- struct dpram_ipc_map ipc_map;
+ struct pld_ipc_map ipc_map;
/* Pointers (aliases) to IPC device map */
u16 __iomem *magic_ap2cp;
@@ -424,7 +209,7 @@ struct dpram_link_device {
/* Wakelock for DPRAM device */
struct wake_lock wlock;
- char wlock_name[DP_MAX_NAME_LEN];
+ char wlock_name[MIF_MAX_NAME_LEN];
/* For booting */
unsigned boot_start_complete;
@@ -432,19 +217,16 @@ struct dpram_link_device {
struct completion modem_pif_init_done;
/* For UDL */
- struct tasklet_struct ul_tsk;
struct tasklet_struct dl_tsk;
struct completion udl_start_complete;
struct completion udl_cmd_complete;
- struct dpram_udl_check udl_check;
- struct dpram_udl_param udl_param;
+ struct qc_dpram_udl_check qc_udl_check;
+ struct qc_dpram_udl_param qc_udl_param;
- /* For CP RAM dump */
+ /* For CP crash dump */
struct timer_list crash_ack_timer;
- struct completion dump_start_complete;
- struct completion dump_recv_done;
- struct timer_list dump_timer;
- int dump_rcvd; /* Count of dump packets received */
+ struct completion crash_start_complete;
+ struct completion crash_recv_done;
/* For locking TX process */
spinlock_t tx_rx_lock;
@@ -452,10 +234,8 @@ struct dpram_link_device {
/* For efficient RX process */
struct tasklet_struct rx_tsk;
- struct dpram_rxb_queue rxbq[MAX_IPC_DEV];
+ struct mif_rxb_queue rxbq[MAX_IPC_DEV];
struct io_device *iod[MAX_IPC_DEV];
- bool use_skb;
- struct sk_buff_head skb_rxq[MAX_IPC_DEV];
/* For retransmission after buffer full state */
atomic_t res_required[MAX_IPC_DEV];
@@ -466,67 +246,65 @@ struct dpram_link_device {
/* Multi-purpose miscellaneous buffer */
u8 *buff;
- /* DPRAM IPC initialization status */
- int dpram_init_status;
+ /* PLD IPC initialization status */
+ int init_status;
/* Alias to device-specific IOCTL function */
- int (*ext_ioctl)(struct dpram_link_device *dpld, struct io_device *iod,
+ int (*ext_ioctl)(struct pld_link_device *pld, struct io_device *iod,
unsigned int cmd, unsigned long arg);
- /* For DPRAM dump */
- void (*dpram_dump)(struct link_device *ld, char *buff);
-
/* Common operations for each DPRAM */
- void (*clear_intr)(struct dpram_link_device *dpld);
- u16 (*recv_intr)(struct dpram_link_device *dpld);
- void (*send_intr)(struct dpram_link_device *dpld, u16 mask);
- u16 (*get_magic)(struct dpram_link_device *dpld);
- void (*set_magic)(struct dpram_link_device *dpld, u16 value);
- u16 (*get_access)(struct dpram_link_device *dpld);
- void (*set_access)(struct dpram_link_device *dpld, u16 value);
- u32 (*get_tx_head)(struct dpram_link_device *dpld, int id);
- u32 (*get_tx_tail)(struct dpram_link_device *dpld, int id);
- void (*set_tx_head)(struct dpram_link_device *dpld, int id, u32 head);
- void (*set_tx_tail)(struct dpram_link_device *dpld, int id, u32 tail);
- u8 *(*get_tx_buff)(struct dpram_link_device *dpld, int id);
- u32 (*get_tx_buff_size)(struct dpram_link_device *dpld, int id);
- u32 (*get_rx_head)(struct dpram_link_device *dpld, int id);
- u32 (*get_rx_tail)(struct dpram_link_device *dpld, int id);
- void (*set_rx_head)(struct dpram_link_device *dpld, int id, u32 head);
- void (*set_rx_tail)(struct dpram_link_device *dpld, int id, u32 tail);
- u8 *(*get_rx_buff)(struct dpram_link_device *dpld, int id);
- u32 (*get_rx_buff_size)(struct dpram_link_device *dpld, int id);
- u16 (*get_mask_req_ack)(struct dpram_link_device *dpld, int id);
- u16 (*get_mask_res_ack)(struct dpram_link_device *dpld, int id);
- u16 (*get_mask_send)(struct dpram_link_device *dpld, int id);
+ void (*clear_intr)(struct pld_link_device *pld);
+ u16 (*recv_intr)(struct pld_link_device *pld);
+ void (*send_intr)(struct pld_link_device *pld, u16 mask);
+ u16 (*get_magic)(struct pld_link_device *pld);
+ void (*set_magic)(struct pld_link_device *pld, u16 value);
+ u16 (*get_access)(struct pld_link_device *pld);
+ void (*set_access)(struct pld_link_device *pld, u16 value);
+ u32 (*get_tx_head)(struct pld_link_device *pld, int id);
+ u32 (*get_tx_tail)(struct pld_link_device *pld, int id);
+ void (*set_tx_head)(struct pld_link_device *pld, int id, u32 head);
+ void (*set_tx_tail)(struct pld_link_device *pld, int id, u32 tail);
+ u8 *(*get_tx_buff)(struct pld_link_device *pld, int id);
+ u32 (*get_tx_buff_size)(struct pld_link_device *pld, int id);
+ u32 (*get_rx_head)(struct pld_link_device *pld, int id);
+ u32 (*get_rx_tail)(struct pld_link_device *pld, int id);
+ void (*set_rx_head)(struct pld_link_device *pld, int id, u32 head);
+ void (*set_rx_tail)(struct pld_link_device *pld, int id, u32 tail);
+ u8 *(*get_rx_buff)(struct pld_link_device *pld, int id);
+ u32 (*get_rx_buff_size)(struct pld_link_device *pld, int id);
+ u16 (*get_mask_req_ack)(struct pld_link_device *pld, int id);
+ u16 (*get_mask_res_ack)(struct pld_link_device *pld, int id);
+ u16 (*get_mask_send)(struct pld_link_device *pld, int id);
/* Extended operations for various modems */
- struct dpram_ext_op *ext_op;
+ struct pld_ext_op *ext_op;
};
/* converts from struct link_device* to struct xxx_link_device* */
-#define to_dpram_link_device(linkdev) \
- container_of(linkdev, struct dpram_link_device, ld)
+#define to_pld_link_device(linkdev) \
+ container_of(linkdev, struct pld_link_device, ld)
-struct dpram_ext_op {
+struct pld_ext_op {
int exist;
- void (*init_boot_map)(struct dpram_link_device *dpld);
- void (*init_dl_map)(struct dpram_link_device *dpld);
- void (*init_ul_map)(struct dpram_link_device *dpld);
+ void (*init_boot_map)(struct pld_link_device *pld);
+ void (*init_dl_map)(struct pld_link_device *pld);
+ void (*init_ul_map)(struct pld_link_device *pld);
- int (*dload_bin)(struct dpram_link_device *dpld, struct sk_buff *skb);
- void (*dload_cmd_handler)(struct dpram_link_device *dpld, u16 cmd);
+ void (*dload_cmd_handler)(struct pld_link_device *pld, u16 cmd);
- void (*cp_start_handler)(struct dpram_link_device *dpld);
+ void (*cp_start_handler)(struct pld_link_device *pld);
- void (*crash_log)(struct dpram_link_device *dpld);
- int (*dump_start)(struct dpram_link_device *dpld);
- int (*dump_update)(struct dpram_link_device *dpld, void *arg);
+ void (*crash_log)(struct pld_link_device *pld);
+ int (*dump_start)(struct pld_link_device *pld);
+ int (*dump_update)(struct pld_link_device *pld, void *arg);
- int (*ioctl)(struct dpram_link_device *dpld, struct io_device *iod,
+ int (*ioctl)(struct pld_link_device *pld, struct io_device *iod,
unsigned int cmd, unsigned long arg);
+
+ void (*clear_intr)(struct pld_link_device *pld);
};
-struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem);
+struct pld_ext_op *pld_get_ext_op(enum modem_t modem);
#endif
diff --git a/drivers/misc/modem_if/modem_link_device_pld_ext_op.c b/drivers/misc/modem_if/modem_link_device_pld_ext_op.c
index ae6578c..26b0e28 100644
--- a/drivers/misc/modem_if/modem_link_device_pld_ext_op.c
+++ b/drivers/misc/modem_if/modem_link_device_pld_ext_op.c
@@ -25,8 +25,8 @@
#include <linux/if_arp.h>
#include <linux/platform_device.h>
#include <linux/kallsyms.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_pld.h"
#include "modem_utils.h"
@@ -41,56 +41,55 @@ enum qc_dload_tag {
static void qc_dload_task(unsigned long data);
-static void qc_init_boot_map(struct dpram_link_device *dpld)
+static void qc_init_boot_map(struct pld_link_device *pld)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
- struct modemlink_dpram_control *dpctl = dpld->dpctl;
+ struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map;
+ struct modemlink_dpram_data *dpram = pld->dpram;
- bt_map->buff = dpld->dev[0]->txq.buff;
- bt_map->frame_size = (u16 *)(dpld->dp_base + dpctl->boot_size_offset);
- bt_map->tag = (u16 *)(dpld->dp_base + dpctl->boot_tag_offset);
- bt_map->count = (u16 *)(dpld->dp_base + dpctl->boot_count_offset);
+ qbt_map->buff = pld->dev[0]->txq.buff;
+ qbt_map->frame_size = (u16 *)(pld->base + dpram->boot_size_offset);
+ qbt_map->tag = (u16 *)(pld->base + dpram->boot_tag_offset);
+ qbt_map->count = (u16 *)(pld->base + dpram->boot_count_offset);
- tasklet_init(&dpld->dl_tsk, qc_dload_task, (unsigned long)dpld);
+ tasklet_init(&pld->dl_tsk, qc_dload_task, (unsigned long)pld);
}
-static void qc_dload_map(struct dpram_link_device *dpld, u8 is_upload)
+static void qc_dload_map(struct pld_link_device *pld, u8 is_upload)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
- struct modemlink_dpram_control *dpctl = dpld->dpctl;
+ struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map;
+ struct modemlink_dpram_data *dpram = pld->dpram;
unsigned int upload_offset = 0;
if (is_upload == 1) {
upload_offset = 0x1000;
- bt_map->buff = dpld->dev[0]->rxq.buff;
+ qbt_map->buff = pld->dev[0]->rxq.buff;
} else {
upload_offset = 0;
- bt_map->buff = dpld->dev[0]->txq.buff;
+ qbt_map->buff = pld->dev[0]->txq.buff;
}
- bt_map->frame_size = (u16 *)(dpld->dp_base +
- dpctl->boot_size_offset + upload_offset);
- bt_map->tag = (u16 *)(dpld->dp_base +
- dpctl->boot_tag_offset + upload_offset);
- bt_map->count = (u16 *)(dpld->dp_base +
- dpctl->boot_count_offset + upload_offset);
-
+ qbt_map->frame_size = (u16 *)(pld->base +
+ dpram->boot_size_offset + upload_offset);
+ qbt_map->tag = (u16 *)(pld->base +
+ dpram->boot_tag_offset + upload_offset);
+ qbt_map->count = (u16 *)(pld->base +
+ dpram->boot_count_offset + upload_offset);
}
-static int qc_prepare_download(struct dpram_link_device *dpld)
+static int qc_prepare_download(struct pld_link_device *pld)
{
int retval = 0;
int count = 0;
- qc_dload_map(dpld, 0);
+ qc_dload_map(pld, 0);
while (1) {
- if (dpld->udl_check.copy_start) {
- dpld->udl_check.copy_start = 0;
+ if (pld->qc_udl_check.copy_start) {
+ pld->qc_udl_check.copy_start = 0;
break;
}
- msleep(20);
+ usleep_range(10000, 11000);
count++;
if (count > 1000) {
@@ -102,42 +101,42 @@ static int qc_prepare_download(struct dpram_link_device *dpld)
return retval;
}
-static void _qc_do_download(struct dpram_link_device *dpld,
- struct dpram_udl_param *param)
+static void _qc_do_download(struct pld_link_device *pld,
+ struct qc_dpram_udl_param *param)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
+ struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map;
- if (param->size <= dpld->dpctl->max_boot_frame_size) {
- iowrite16(PLD_ADDR_MASK(&bt_map->buff[0]),
- dpld->address_buffer);
- memcpy(dpld->dp_base, param->addr, param->size);
+ if (param->size <= pld->dpram->max_boot_frame_size) {
+ iowrite16(PLD_ADDR_MASK(&qbt_map->buff[0]),
+ pld->address_buffer);
+ memcpy(pld->base, param->addr, param->size);
- iowrite16(PLD_ADDR_MASK(&bt_map->frame_size[0]),
- dpld->address_buffer);
- iowrite16(param->size, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->frame_size[0]),
+ pld->address_buffer);
+ iowrite16(param->size, pld->base);
- iowrite16(PLD_ADDR_MASK(&bt_map->tag[0]),
- dpld->address_buffer);
- iowrite16(param->tag, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->tag[0]),
+ pld->address_buffer);
+ iowrite16(param->tag, pld->base);
- iowrite16(PLD_ADDR_MASK(&bt_map->count[0]),
- dpld->address_buffer);
- iowrite16(param->count, dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->count[0]),
+ pld->address_buffer);
+ iowrite16(param->count, pld->base);
- dpld->send_intr(dpld, 0xDB12);
+ pld->send_intr(pld, 0xDB12);
} else {
mif_info("param->size %d\n", param->size);
}
}
-static int _qc_download(struct dpram_link_device *dpld, void *arg,
+static int _qc_download(struct pld_link_device *pld, void *arg,
enum qc_dload_tag tag)
{
int retval = 0;
int count = 0;
int cnt_limit;
unsigned char *img;
- struct dpram_udl_param param;
+ struct qc_dpram_udl_param param;
retval = copy_from_user((void *)&param, (void *)arg, sizeof(param));
if (retval < 0) {
@@ -153,24 +152,24 @@ static int _qc_download(struct dpram_link_device *dpld, void *arg,
memset(img, 0, param.size);
memcpy(img, param.addr, param.size);
- dpld->udl_check.total_size = param.size;
- dpld->udl_check.rest_size = param.size;
- dpld->udl_check.send_size = 0;
- dpld->udl_check.copy_complete = 0;
+ pld->qc_udl_check.total_size = param.size;
+ pld->qc_udl_check.rest_size = param.size;
+ pld->qc_udl_check.send_size = 0;
+ pld->qc_udl_check.copy_complete = 0;
- dpld->udl_param.addr = img;
- dpld->udl_param.size = dpld->dpctl->max_boot_frame_size;
+ pld->qc_udl_param.addr = img;
+ pld->qc_udl_param.size = pld->dpram->max_boot_frame_size;
if (tag == QC_DLOAD_TAG_NV)
- dpld->udl_param.count = 1;
+ pld->qc_udl_param.count = 1;
else
- dpld->udl_param.count = param.count;
- dpld->udl_param.tag = tag;
+ pld->qc_udl_param.count = param.count;
+ pld->qc_udl_param.tag = tag;
- if (dpld->udl_check.rest_size < dpld->dpctl->max_boot_frame_size)
- dpld->udl_param.size = dpld->udl_check.rest_size;
+ if (pld->qc_udl_check.rest_size < pld->dpram->max_boot_frame_size)
+ pld->qc_udl_param.size = pld->qc_udl_check.rest_size;
/* Download image (binary or NV) */
- _qc_do_download(dpld, &dpld->udl_param);
+ _qc_do_download(pld, &pld->qc_udl_param);
/* Wait for completion
*/
@@ -180,13 +179,13 @@ static int _qc_download(struct dpram_link_device *dpld, void *arg,
cnt_limit = 1000;
while (1) {
- if (dpld->udl_check.copy_complete) {
- dpld->udl_check.copy_complete = 0;
+ if (pld->qc_udl_check.copy_complete) {
+ pld->qc_udl_check.copy_complete = 0;
retval = 0;
break;
}
- msleep(20);
+ usleep_range(10000, 11000);
count++;
if (count > cnt_limit) {
@@ -201,53 +200,53 @@ static int _qc_download(struct dpram_link_device *dpld, void *arg,
return retval;
}
-static int qc_download_bin(struct dpram_link_device *dpld, void *arg)
+static int qc_download_bin(struct pld_link_device *pld, void *arg)
{
- return _qc_download(dpld, arg, QC_DLOAD_TAG_BIN);
+ return _qc_download(pld, arg, QC_DLOAD_TAG_BIN);
}
-static int qc_download_nv(struct dpram_link_device *dpld, void *arg)
+static int qc_download_nv(struct pld_link_device *pld, void *arg)
{
- return _qc_download(dpld, arg, QC_DLOAD_TAG_NV);
+ return _qc_download(pld, arg, QC_DLOAD_TAG_NV);
}
static void qc_dload_task(unsigned long data)
{
- struct dpram_link_device *dpld = (struct dpram_link_device *)data;
+ struct pld_link_device *pld = (struct pld_link_device *)data;
- dpld->udl_check.send_size += dpld->udl_param.size;
- dpld->udl_check.rest_size -= dpld->udl_param.size;
+ pld->qc_udl_check.send_size += pld->qc_udl_param.size;
+ pld->qc_udl_check.rest_size -= pld->qc_udl_param.size;
- dpld->udl_param.addr += dpld->udl_param.size;
+ pld->qc_udl_param.addr += pld->qc_udl_param.size;
- if (dpld->udl_check.send_size >= dpld->udl_check.total_size) {
- dpld->udl_check.copy_complete = 1;
- dpld->udl_param.tag = 0;
+ if (pld->qc_udl_check.send_size >= pld->qc_udl_check.total_size) {
+ pld->qc_udl_check.copy_complete = 1;
+ pld->qc_udl_param.tag = 0;
return;
}
- if (dpld->udl_check.rest_size < dpld->dpctl->max_boot_frame_size)
- dpld->udl_param.size = dpld->udl_check.rest_size;
+ if (pld->qc_udl_check.rest_size < pld->dpram->max_boot_frame_size)
+ pld->qc_udl_param.size = pld->qc_udl_check.rest_size;
- dpld->udl_param.count += 1;
+ pld->qc_udl_param.count += 1;
- _qc_do_download(dpld, &dpld->udl_param);
+ _qc_do_download(pld, &pld->qc_udl_param);
}
-static void qc_dload_cmd_handler(struct dpram_link_device *dpld, u16 cmd)
+static void qc_dload_cmd_handler(struct pld_link_device *pld, u16 cmd)
{
switch (cmd) {
case 0x1234:
- dpld->udl_check.copy_start = 1;
+ pld->qc_udl_check.copy_start = 1;
break;
case 0xDBAB:
- tasklet_schedule(&dpld->dl_tsk);
+ tasklet_schedule(&pld->dl_tsk);
break;
case 0xABCD:
- mif_info("[%s] booting Start\n", dpld->ld.name);
- dpld->udl_check.boot_complete = 1;
+ mif_info("[%s] booting Start\n", pld->ld.name);
+ pld->qc_udl_check.boot_complete = 1;
break;
default:
@@ -255,22 +254,22 @@ static void qc_dload_cmd_handler(struct dpram_link_device *dpld, u16 cmd)
}
}
-static int qc_boot_start(struct dpram_link_device *dpld)
+static int qc_boot_start(struct pld_link_device *pld)
{
u16 mask = 0;
int count = 0;
/* Send interrupt -> '0x4567' */
mask = 0x4567;
- dpld->send_intr(dpld, mask);
+ pld->send_intr(pld, mask);
while (1) {
- if (dpld->udl_check.boot_complete) {
- dpld->udl_check.boot_complete = 0;
+ if (pld->qc_udl_check.boot_complete) {
+ pld->qc_udl_check.boot_complete = 0;
break;
}
- msleep(20);
+ usleep_range(10000, 11000);
count++;
if (count > 200) {
@@ -282,17 +281,17 @@ static int qc_boot_start(struct dpram_link_device *dpld)
return 0;
}
-static int qc_boot_post_process(struct dpram_link_device *dpld)
+static int qc_boot_post_process(struct pld_link_device *pld)
{
int count = 0;
while (1) {
- if (dpld->boot_start_complete) {
- dpld->boot_start_complete = 0;
+ if (pld->boot_start_complete) {
+ pld->boot_start_complete = 0;
break;
}
- msleep(20);
+ usleep_range(10000, 11000);
count++;
if (count > 200) {
@@ -304,7 +303,7 @@ static int qc_boot_post_process(struct dpram_link_device *dpld)
return 0;
}
-static void qc_start_handler(struct dpram_link_device *dpld)
+static void qc_start_handler(struct pld_link_device *pld)
{
/*
* INT_MASK_VALID | INT_MASK_CMD | INT_MASK_CP_AIRPLANE_BOOT |
@@ -312,38 +311,38 @@ static void qc_start_handler(struct dpram_link_device *dpld)
*/
u16 mask = (0x0080 | 0x0040 | 0x1000 | 0x0100 | 0x0002);
- dpld->boot_start_complete = 1;
+ pld->boot_start_complete = 1;
/* Send INIT_END code to CP */
mif_info("send 0x%04X (INIT_END)\n", mask);
- dpld->send_intr(dpld, mask);
+ pld->send_intr(pld, mask);
}
-static void qc_crash_log(struct dpram_link_device *dpld)
+static void qc_crash_log(struct pld_link_device *pld)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
static unsigned char buf[151];
u8 __iomem *data = NULL;
- data = dpld->get_rx_buff(dpld, IPC_FMT);
+ data = pld->get_rx_buff(pld, IPC_FMT);
memcpy(buf, data, (sizeof(buf) - 1));
mif_info("PHONE ERR MSG\t| %s Crash\n", ld->mdm_data->name);
mif_info("PHONE ERR MSG\t| %s\n", buf);
}
-static int _qc_data_upload(struct dpram_link_device *dpld,
- struct dpram_udl_param *param)
+static int _qc_data_upload(struct pld_link_device *pld,
+ struct qc_dpram_udl_param *param)
{
- struct qc_dpram_boot_map *bt_map = &dpld->qc_bt_map;
+ struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map;
int retval = 0;
u16 intval = 0;
int count = 0;
while (1) {
- if (!gpio_get_value(dpld->gpio_dpram_int)) {
- intval = dpld->recv_intr(dpld);
+ if (!gpio_get_value(pld->gpio_ipc_int2ap)) {
+ intval = pld->recv_intr(pld);
if (intval == 0xDBAB) {
break;
} else {
@@ -352,7 +351,7 @@ static int _qc_data_upload(struct dpram_link_device *dpld,
}
}
- msleep(20);
+ usleep_range(1000, 2000);
count++;
if (count > 200) {
@@ -361,43 +360,43 @@ static int _qc_data_upload(struct dpram_link_device *dpld,
}
}
- iowrite16(PLD_ADDR_MASK(&bt_map->frame_size[0]),
- dpld->address_buffer);
- param->size = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->frame_size[0]),
+ pld->address_buffer);
+ param->size = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&bt_map->tag[0]),
- dpld->address_buffer);
- param->tag = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->tag[0]),
+ pld->address_buffer);
+ param->tag = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&bt_map->count[0]),
- dpld->address_buffer);
- param->count = ioread16(dpld->dp_base);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->count[0]),
+ pld->address_buffer);
+ param->count = ioread16(pld->base);
- iowrite16(PLD_ADDR_MASK(&bt_map->buff[0]),
- dpld->address_buffer);
- memcpy(param->addr, dpld->dp_base, param->size);
+ iowrite16(PLD_ADDR_MASK(&qbt_map->buff[0]),
+ pld->address_buffer);
+ memcpy(param->addr, pld->base, param->size);
- dpld->send_intr(dpld, 0xDB12);
+ pld->send_intr(pld, 0xDB12);
return retval;
}
-static int qc_uload_step1(struct dpram_link_device *dpld)
+static int qc_uload_step1(struct pld_link_device *pld)
{
int retval = 0;
int count = 0;
u16 intval = 0;
u16 mask = 0;
- qc_dload_map(dpld, 1);
+ qc_dload_map(pld, 1);
mif_info("+---------------------------------------------+\n");
mif_info("| UPLOAD PHONE SDRAM |\n");
mif_info("+---------------------------------------------+\n");
while (1) {
- if (!gpio_get_value(dpld->gpio_dpram_int)) {
- intval = dpld->recv_intr(dpld);
+ if (!gpio_get_value(pld->gpio_ipc_int2ap)) {
+ intval = pld->recv_intr(pld);
mif_info("intr 0x%04x\n", intval);
if (intval == 0x1234) {
break;
@@ -407,11 +406,11 @@ static int qc_uload_step1(struct dpram_link_device *dpld)
}
}
- msleep(20);
+ usleep_range(1000, 2000);
count++;
if (count > 200) {
- intval = dpld->recv_intr(dpld);
+ intval = pld->recv_intr(pld);
mif_info("count %d, intr 0x%04x\n", count, intval);
if (intval == 0x1234)
break;
@@ -420,15 +419,15 @@ static int qc_uload_step1(struct dpram_link_device *dpld)
}
mask = 0xDEAD;
- dpld->send_intr(dpld, mask);
+ pld->send_intr(pld, mask);
return retval;
}
-static int qc_uload_step2(struct dpram_link_device *dpld, void *arg)
+static int qc_uload_step2(struct pld_link_device *pld, void *arg)
{
int retval = 0;
- struct dpram_udl_param param;
+ struct qc_dpram_udl_param param;
retval = copy_from_user((void *)&param, (void *)arg, sizeof(param));
if (retval < 0) {
@@ -436,7 +435,7 @@ static int qc_uload_step2(struct dpram_link_device *dpld, void *arg)
return -1;
}
- retval = _qc_data_upload(dpld, &param);
+ retval = _qc_data_upload(pld, &param);
if (retval < 0) {
mif_err("ERR! _qc_data_upload fail (err %d)\n", retval);
return -1;
@@ -446,7 +445,7 @@ static int qc_uload_step2(struct dpram_link_device *dpld, void *arg)
mif_info("param->count = %d\n", param.count);
if (param.tag == 4) {
- enable_irq(dpld->irq);
+ enable_irq(pld->irq);
mif_info("param->tag = %d\n", param.tag);
}
@@ -459,57 +458,57 @@ static int qc_uload_step2(struct dpram_link_device *dpld, void *arg)
return retval;
}
-static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
+static int qc_ioctl(struct pld_link_device *pld, struct io_device *iod,
unsigned int cmd, unsigned long arg)
{
- struct link_device *ld = &dpld->ld;
+ struct link_device *ld = &pld->ld;
int err = 0;
switch (cmd) {
case IOCTL_DPRAM_PHONE_POWON:
- err = qc_prepare_download(dpld);
+ err = qc_prepare_download(pld);
if (err < 0)
mif_info("%s: ERR! prepare_download fail\n", ld->name);
break;
case IOCTL_DPRAM_PHONEIMG_LOAD:
- err = qc_download_bin(dpld, (void *)arg);
+ err = qc_download_bin(pld, (void *)arg);
if (err < 0)
mif_info("%s: ERR! download_bin fail\n", ld->name);
break;
case IOCTL_DPRAM_NVDATA_LOAD:
- err = qc_download_nv(dpld, (void *)arg);
+ err = qc_download_nv(pld, (void *)arg);
if (err < 0)
mif_info("%s: ERR! download_nv fail\n", ld->name);
break;
case IOCTL_DPRAM_PHONE_BOOTSTART:
- err = qc_boot_start(dpld);
+ err = qc_boot_start(pld);
if (err < 0) {
mif_info("%s: ERR! boot_start fail\n", ld->name);
break;
}
- err = qc_boot_post_process(dpld);
+ err = qc_boot_post_process(pld);
if (err < 0)
mif_info("%s: ERR! boot_post_process fail\n", ld->name);
break;
case IOCTL_DPRAM_PHONE_UPLOAD_STEP1:
- disable_irq_nosync(dpld->irq);
- err = qc_uload_step1(dpld);
+ disable_irq_nosync(pld->irq);
+ err = qc_uload_step1(pld);
if (err < 0) {
- enable_irq(dpld->irq);
+ enable_irq(pld->irq);
mif_info("%s: ERR! upload_step1 fail\n", ld->name);
}
break;
case IOCTL_DPRAM_PHONE_UPLOAD_STEP2:
- err = qc_uload_step2(dpld, (void *)arg);
+ err = qc_uload_step2(pld, (void *)arg);
if (err < 0) {
- enable_irq(dpld->irq);
+ enable_irq(pld->irq);
mif_info("%s: ERR! upload_step2 fail\n", ld->name);
}
break;
@@ -524,7 +523,7 @@ static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod,
}
#endif
-static struct dpram_ext_op ext_op_set[] = {
+static struct pld_ext_op ext_op_set[] = {
#if defined(CONFIG_CDMA_MODEM_MDM6600)
[QC_MDM6600] = {
.exist = 1,
@@ -547,7 +546,7 @@ static struct dpram_ext_op ext_op_set[] = {
#endif
};
-struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem)
+struct pld_ext_op *pld_get_ext_op(enum modem_t modem)
{
if (ext_op_set[modem].exist)
return &ext_op_set[modem];
diff --git a/drivers/misc/modem_if/modem_link_device_shmem.h b/drivers/misc/modem_if/modem_link_device_shmem.h
new file mode 100644
index 0000000..1f33c2a
--- /dev/null
+++ b/drivers/misc/modem_if/modem_link_device_shmem.h
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MODEM_LINK_DEVICE_SHMEM_H__
+#define __MODEM_LINK_DEVICE_SHMEM_H__
+
+#include "modem_utils.h"
+#include "modem_link_device_memory.h"
+
+#define SHM_BOOT_MAGIC 0x424F4F54
+#define SHM_DUMP_MAGIC 0x44554D50
+#define SHM_IPC_MAGIC 0xAA
+#define SHM_PM_MAGIC 0x5F
+
+#define SHM_4M_RESERVED_SZ 4056
+#define SHM_4M_FMT_TX_BUFF_SZ 4096
+#define SHM_4M_FMT_RX_BUFF_SZ 4096
+#define SHM_4M_RAW_TX_BUFF_SZ 2084864
+#define SHM_4M_RAW_RX_BUFF_SZ 2097152
+
+struct shmem_4mb_phys_map {
+ u32 magic;
+ u32 access;
+
+ u32 fmt_tx_head;
+ u32 fmt_tx_tail;
+
+ u32 fmt_rx_head;
+ u32 fmt_rx_tail;
+
+ u32 raw_tx_head;
+ u32 raw_tx_tail;
+
+ u32 raw_rx_head;
+ u32 raw_rx_tail;
+
+ u8 reserved[SHM_4M_RESERVED_SZ];
+
+ u8 fmt_tx_buff[SHM_4M_FMT_TX_BUFF_SZ];
+ u8 fmt_rx_buff[SHM_4M_FMT_RX_BUFF_SZ];
+
+ u8 raw_tx_buff[SHM_4M_RAW_TX_BUFF_SZ];
+ u8 raw_rx_buff[SHM_4M_RAW_RX_BUFF_SZ];
+} __packed;
+
+struct shmem_circ {
+ u32 __iomem *head;
+ u32 __iomem *tail;
+ u8 __iomem *buff;
+ u32 size;
+};
+
+struct shmem_ipc_device {
+ char name[16];
+ int id;
+
+ struct shmem_circ txq;
+ struct shmem_circ rxq;
+
+ u16 mask_req_ack;
+ u16 mask_res_ack;
+ u16 mask_send;
+
+ int req_ack_rcvd;
+};
+
+struct shmem_ipc_map {
+ u32 __iomem *magic;
+ u32 __iomem *access;
+
+ struct shmem_ipc_device dev[MAX_SIPC5_DEV];
+
+ u32 __iomem *mbx2ap;
+ u32 __iomem *mbx2cp;
+};
+
+struct shmem_link_device {
+ struct link_device ld;
+
+ enum shmem_type type;
+
+ /* SHMEM (SHARED MEMORY) address and size */
+ u32 start; /* physical "start" address of SHMEM */
+ u32 size; /* size of SHMEM */
+ u8 __iomem *base; /* virtual address of the "start" */
+
+ /* SHMEM GPIO & IRQ */
+ unsigned gpio_pda_active;
+
+ unsigned gpio_ap_wakeup;
+ int irq_ap_wakeup;
+ unsigned gpio_ap_status;
+
+ unsigned gpio_cp_wakeup;
+ unsigned gpio_cp_status;
+ int irq_cp_status;
+
+ /* IPC device map */
+ struct shmem_ipc_map ipc_map;
+
+ /* Pointers (aliases) to IPC device map */
+ u32 __iomem *magic;
+ u32 __iomem *access;
+ struct shmem_ipc_device *dev[MAX_SIPC5_DEV];
+ u32 __iomem *mbx2ap;
+ u32 __iomem *mbx2cp;
+
+ /* Wakelock for SHMEM device */
+ struct wake_lock wlock;
+ char wlock_name[MIF_MAX_NAME_LEN];
+ struct wake_lock ap_wlock;
+ char ap_wlock_name[MIF_MAX_NAME_LEN];
+ struct wake_lock cp_wlock;
+ char cp_wlock_name[MIF_MAX_NAME_LEN];
+
+ /* for UDL */
+ struct completion udl_cmpl;
+ struct std_dload_info dl_info;
+
+ /* for CP crash dump */
+ bool forced_cp_crash;
+ struct timer_list crash_ack_timer;
+
+ /* for locking TX process */
+ spinlock_t tx_lock[MAX_SIPC5_DEV];
+
+ /* for retransmission under SHMEM flow control after TXQ full state */
+ atomic_t res_required[MAX_SIPC5_DEV];
+ struct completion req_ack_cmpl[MAX_SIPC5_DEV];
+
+ /* for efficient RX process */
+ struct tasklet_struct rx_tsk;
+ struct delayed_work ipc_rx_dwork;
+ struct delayed_work udl_rx_dwork;
+ struct io_device *iod[MAX_SIPC5_DEV];
+
+ /* for logging SHMEM status */
+ struct mem_status_queue stat_list;
+
+ /* for logging SHMEM dump */
+ struct trace_data_queue trace_list;
+#ifdef DEBUG_MODEM_IF
+ struct delayed_work dump_dwork;
+ char dump_path[MIF_MAX_PATH_LEN];
+#endif
+
+ /* to hold/release "cp_wakeup" for PM (power-management) */
+ struct delayed_work cp_sleep_dwork;
+ struct delayed_work link_off_dwork;
+ atomic_t ref_cnt;
+ spinlock_t pm_lock;
+};
+
+/* converts from struct link_device* to struct xxx_link_device* */
+#define to_shmem_link_device(linkdev) \
+ container_of(linkdev, struct shmem_link_device, ld)
+
+#if 1
+#endif
+
+/**
+ * get_magic
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Returns the value of the "magic code" field.
+ */
+static inline u32 get_magic(struct shmem_link_device *shmd)
+{
+ return ioread32(shmd->magic);
+}
+
+/**
+ * get_access
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Returns the value of the "access enable" field.
+ */
+static inline u32 get_access(struct shmem_link_device *shmd)
+{
+ return ioread32(shmd->access);
+}
+
+/**
+ * set_magic
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @val: value to be written to the "magic code" field
+ */
+static inline void set_magic(struct shmem_link_device *shmd, u32 val)
+{
+ iowrite32(val, shmd->magic);
+}
+
+/**
+ * set_access
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @val: value to be written to the "access enable" field
+ */
+static inline void set_access(struct shmem_link_device *shmd, u32 val)
+{
+ iowrite32(val, shmd->access);
+}
+
+/**
+ * get_txq_head
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a head (in) pointer in a TX queue.
+ */
+static inline u32 get_txq_head(struct shmem_link_device *shmd, int id)
+{
+ return ioread32(shmd->dev[id]->txq.head);
+}
+
+/**
+ * get_txq_tail
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a tail (out) pointer in a TX queue.
+ *
+ * It is useless for an AP to read a tail pointer in a TX queue twice to verify
+ * whether or not the value in the pointer is valid, because it can already have
+ * been updated by a CP after the first access from the AP.
+ */
+static inline u32 get_txq_tail(struct shmem_link_device *shmd, int id)
+{
+ return ioread32(shmd->dev[id]->txq.tail);
+}
+
+/**
+ * get_txq_buff
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the start address of the buffer in a TXQ.
+ */
+static inline u8 *get_txq_buff(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->txq.buff;
+}
+
+/**
+ * get_txq_buff_size
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the size of the buffer in a TXQ.
+ */
+static inline u32 get_txq_buff_size(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->txq.size;
+}
+
+/**
+ * get_rxq_head
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a head (in) pointer in an RX queue.
+ *
+ * It is useless for an AP to read a head pointer in an RX queue twice to verify
+ * whether or not the value in the pointer is valid, because it can already have
+ * been updated by a CP after the first access from the AP.
+ */
+static inline u32 get_rxq_head(struct shmem_link_device *shmd, int id)
+{
+ return ioread32(shmd->dev[id]->rxq.head);
+}
+
+/**
+ * get_rxq_tail
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the value of a tail (in) pointer in an RX queue.
+ */
+static inline u32 get_rxq_tail(struct shmem_link_device *shmd, int id)
+{
+ return ioread32(shmd->dev[id]->rxq.tail);
+}
+
+/**
+ * get_rxq_buff
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the start address of the buffer in an RXQ.
+ */
+static inline u8 *get_rxq_buff(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->rxq.buff;
+}
+
+/**
+ * get_rxq_buff_size
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the size of the buffer in an RXQ.
+ */
+static inline u32 get_rxq_buff_size(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->rxq.size;
+}
+
+/**
+ * set_txq_head
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @in: value to be written to the head pointer in a TXQ
+ */
+static inline void set_txq_head(struct shmem_link_device *shmd, int id, u32 in)
+{
+ iowrite32(in, shmd->dev[id]->txq.head);
+}
+
+/**
+ * set_txq_tail
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @out: value to be written to the tail pointer in a TXQ
+ */
+static inline void set_txq_tail(struct shmem_link_device *shmd, int id, u32 out)
+{
+ iowrite32(out, shmd->dev[id]->txq.tail);
+}
+
+/**
+ * set_rxq_head
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @in: value to be written to the head pointer in an RXQ
+ */
+static inline void set_rxq_head(struct shmem_link_device *shmd, int id, u32 in)
+{
+ iowrite32(in, shmd->dev[id]->rxq.head);
+}
+
+/**
+ * set_rxq_tail
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @out: value to be written to the tail pointer in an RXQ
+ */
+static inline void set_rxq_tail(struct shmem_link_device *shmd, int id, u32 out)
+{
+ iowrite32(out, shmd->dev[id]->rxq.tail);
+}
+
+/**
+ * get_mask_req_ack
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the REQ_ACK mask value for the IPC device.
+ */
+static inline u16 get_mask_req_ack(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->mask_req_ack;
+}
+
+/**
+ * get_mask_res_ack
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the RES_ACK mask value for the IPC device.
+ */
+static inline u16 get_mask_res_ack(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->mask_res_ack;
+}
+
+/**
+ * get_mask_send
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @id: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Returns the SEND mask value for the IPC device.
+ */
+static inline u16 get_mask_send(struct shmem_link_device *shmd, int id)
+{
+ return shmd->dev[id]->mask_send;
+}
+
+#ifndef CONFIG_LINK_DEVICE_C2C
+/**
+ * read_int2cp
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Returns the value of the AP-to-CP interrupt register.
+ */
+static inline u16 read_int2cp(struct shmem_link_device *shmd)
+{
+ if (shmd->mbx2cp)
+ return ioread16(shmd->mbx2cp);
+ else
+ return 0;
+}
+#endif
+
+/**
+ * reset_txq_circ
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Empties a TXQ by resetting the head (in) pointer with the value in the tail
+ * (out) pointer.
+ */
+static inline void reset_txq_circ(struct shmem_link_device *shmd, int dev)
+{
+ struct link_device *ld = &shmd->ld;
+ u32 head = get_txq_head(shmd, dev);
+ u32 tail = get_txq_tail(shmd, dev);
+
+ mif_err("%s: %s_TXQ: HEAD[%u] <== TAIL[%u]\n",
+ ld->name, get_dev_name(dev), head, tail);
+
+ set_txq_head(shmd, dev, tail);
+}
+
+/**
+ * reset_rxq_circ
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ *
+ * Empties an RXQ by resetting the tail (out) pointer with the value in the head
+ * (in) pointer.
+ */
+static inline void reset_rxq_circ(struct shmem_link_device *shmd, int dev)
+{
+ struct link_device *ld = &shmd->ld;
+ u32 head = get_rxq_head(shmd, dev);
+ u32 tail = get_rxq_tail(shmd, dev);
+
+ mif_err("%s: %s_RXQ: TAIL[%u] <== HEAD[%u]\n",
+ ld->name, get_dev_name(dev), tail, head);
+
+ set_rxq_tail(shmd, dev, head);
+}
+
+/**
+ * ipc_active
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Returns whether or not IPC via the shmem_link_device instance is possible.
+ */
+static bool ipc_active(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+ u32 magic = get_magic(shmd);
+ u32 access = get_access(shmd);
+
+ /* Check link mode */
+ if (unlikely(ld->mode != LINK_MODE_IPC)) {
+ mif_err("%s: <by %pf> ERR! ld->mode != LINK_MODE_IPC\n",
+ ld->name, CALLER);
+ return false;
+ }
+
+ /* Check "magic code" and "access enable" values */
+ if (unlikely(magic != SHM_IPC_MAGIC || access != 1)) {
+ mif_err("%s: <by %pf> ERR! magic:0x%X access:%d\n",
+ ld->name, CALLER, magic, access);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * get_rxq_rcvd
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ * OUT @circ: pointer to an instance of circ_status structure
+ *
+ * Stores {start address of the buffer in a RXQ, size of the buffer, in & out
+ * pointer values, size of received data} into the 'circ' instance.
+ *
+ * Returns an error code.
+ */
+static int get_rxq_rcvd(struct shmem_link_device *shmd, int dev,
+ struct mem_status *mst, struct circ_status *circ)
+{
+ struct link_device *ld = &shmd->ld;
+
+ circ->buff = get_rxq_buff(shmd, dev);
+ circ->qsize = get_rxq_buff_size(shmd, dev);
+ circ->in = mst->head[dev][RX];
+ circ->out = mst->tail[dev][RX];
+ circ->size = circ_get_usage(circ->qsize, circ->in, circ->out);
+
+ if (circ_valid(circ->qsize, circ->in, circ->out)) {
+ mif_debug("%s: %s_RXQ qsize[%u] in[%u] out[%u] rcvd[%u]\n",
+ ld->name, get_dev_name(dev), circ->qsize, circ->in,
+ circ->out, circ->size);
+ return 0;
+ } else {
+ mif_err("%s: ERR! %s_RXQ invalid (qsize[%d] in[%d] out[%d])\n",
+ ld->name, get_dev_name(dev), circ->qsize, circ->in,
+ circ->out);
+ return -EIO;
+ }
+}
+
+/**
+ * get_txq_space
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * OUT @circ: pointer to an instance of circ_status structure
+ *
+ * Stores {start address of the buffer in a TXQ, size of the buffer, in & out
+ * pointer values, size of free space} into the 'circ' instance.
+ *
+ * Returns the size of free space in the buffer or an error code.
+ */
+static int get_txq_space(struct shmem_link_device *shmd, int dev,
+ struct circ_status *circ)
+{
+ struct link_device *ld = &shmd->ld;
+ int cnt = 0;
+ u32 qsize;
+ u32 head;
+ u32 tail;
+ int space;
+
+ while (1) {
+ qsize = get_txq_buff_size(shmd, dev);
+ head = get_txq_head(shmd, dev);
+ tail = get_txq_tail(shmd, dev);
+ space = circ_get_space(qsize, head, tail);
+
+ mif_debug("%s: %s_TXQ{qsize:%u in:%u out:%u space:%u}\n",
+ ld->name, get_dev_name(dev), qsize, head, tail, space);
+
+ if (circ_valid(qsize, head, tail))
+ break;
+
+ cnt++;
+ mif_err("%s: ERR! invalid %s_TXQ{qsize:%d in:%d out:%d "
+ "space:%d}, count %d\n",
+ ld->name, get_dev_name(dev), qsize, head, tail,
+ space, cnt);
+ if (cnt >= MAX_RETRY_CNT) {
+ space = -EIO;
+ break;
+ }
+
+ udelay(100);
+ }
+
+ circ->buff = get_txq_buff(shmd, dev);
+ circ->qsize = qsize;
+ circ->in = head;
+ circ->out = tail;
+ circ->size = space;
+
+ return space;
+}
+
+/**
+ * get_txq_saved
+ * @shmd: pointer to an instance of shmem_link_device structure
+ * @dev: IPC device (IPC_FMT, IPC_RAW, etc.)
+ * @mst: pointer to an instance of mem_status structure
+ * OUT @circ: pointer to an instance of circ_status structure
+ *
+ * Stores {start address of the buffer in a TXQ, size of the buffer, in & out
+ * pointer values, size of stored data} into the 'circ' instance.
+ *
+ * Returns an error code.
+ */
+static int get_txq_saved(struct shmem_link_device *shmd, int dev,
+ struct circ_status *circ)
+{
+ struct link_device *ld = &shmd->ld;
+ int cnt = 0;
+ u32 qsize;
+ u32 head;
+ u32 tail;
+ int saved;
+
+ while (1) {
+ qsize = get_txq_buff_size(shmd, dev);
+ head = get_txq_head(shmd, dev);
+ tail = get_txq_tail(shmd, dev);
+ saved = circ_get_usage(qsize, head, tail);
+
+ mif_debug("%s: %s_TXQ{qsize:%u in:%u out:%u saved:%u}\n",
+ ld->name, get_dev_name(dev), qsize, head, tail, saved);
+
+ if (circ_valid(qsize, head, tail))
+ break;
+
+ cnt++;
+ mif_err("%s: ERR! invalid %s_TXQ{qsize:%d in:%d out:%d "
+ "saved:%d}, count %d\n",
+ ld->name, get_dev_name(dev), qsize, head, tail,
+ saved, cnt);
+ if (cnt >= MAX_RETRY_CNT) {
+ saved = -EIO;
+ break;
+ }
+
+ udelay(100);
+ }
+
+ circ->buff = get_txq_buff(shmd, dev);
+ circ->qsize = qsize;
+ circ->in = head;
+ circ->out = tail;
+ circ->size = saved;
+
+ return saved;
+}
+
+/**
+ * clear_shmem_map
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Clears all pointers in every circular queue.
+ */
+static void clear_shmem_map(struct shmem_link_device *shmd)
+{
+ set_txq_head(shmd, IPC_FMT, 0);
+ set_txq_tail(shmd, IPC_FMT, 0);
+ set_rxq_head(shmd, IPC_FMT, 0);
+ set_rxq_tail(shmd, IPC_FMT, 0);
+
+ set_txq_head(shmd, IPC_RAW, 0);
+ set_txq_tail(shmd, IPC_RAW, 0);
+ set_rxq_head(shmd, IPC_RAW, 0);
+ set_rxq_tail(shmd, IPC_RAW, 0);
+}
+
+/**
+ * reset_shmem_ipc
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Reset SHMEM with IPC map.
+ */
+static void reset_shmem_ipc(struct shmem_link_device *shmd)
+{
+ set_access(shmd, 0);
+
+ clear_shmem_map(shmd);
+
+ atomic_set(&shmd->res_required[IPC_FMT], 0);
+ atomic_set(&shmd->res_required[IPC_RAW], 0);
+
+ atomic_set(&shmd->ref_cnt, 0);
+
+ set_magic(shmd, SHM_IPC_MAGIC);
+ set_access(shmd, 1);
+}
+
+/**
+ * init_shmem_ipc
+ * @shmd: pointer to an instance of shmem_link_device structure
+ *
+ * Initializes IPC via SHMEM.
+ */
+static int init_shmem_ipc(struct shmem_link_device *shmd)
+{
+ struct link_device *ld = &shmd->ld;
+
+ if (ld->mode == LINK_MODE_IPC &&
+ get_magic(shmd) == SHM_IPC_MAGIC &&
+ get_access(shmd) == 1) {
+ mif_err("%s: IPC already initialized\n", ld->name);
+ return 0;
+ }
+
+ /* Initialize variables for efficient TX/RX processing */
+ shmd->iod[IPC_FMT] = link_get_iod_with_format(ld, IPC_FMT);
+ shmd->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW);
+
+ reset_shmem_ipc(shmd);
+
+ if (get_magic(shmd) != SHM_IPC_MAGIC || get_access(shmd) != 1)
+ return -EACCES;
+
+ return 0;
+}
+
+#endif
+
diff --git a/drivers/misc/modem_if/modem_link_device_spi.c b/drivers/misc/modem_if/modem_link_device_spi.c
index c4715e0..ece6b65 100644
--- a/drivers/misc/modem_if/modem_link_device_spi.c
+++ b/drivers/misc/modem_if/modem_link_device_spi.c
@@ -26,9 +26,10 @@
#include <linux/if_arp.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/suspend.h>
#include <linux/kthread.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_spi.h"
#include "modem_utils.h"
@@ -66,8 +67,7 @@ static irqreturn_t spi_srdy_irq_handler(int irq, void *p_ld)
if (!spild->boot_done)
return result;
- if (!wake_lock_active(&spild->spi_wake_lock)
- && spild->send_modem_spi != 1) {
+ if (!wake_lock_active(&spild->spi_wake_lock)) {
wake_lock(&spild->spi_wake_lock);
pr_debug("[SPI] [%s](%d) spi_wakelock locked . spild->spi_state[%d]\n",
__func__, __LINE__, (int)spild->spi_state);
@@ -311,7 +311,7 @@ static void spi_prepare_tx_packet(void)
ld = &p_spild->ld;
- for (i = 0; i < p_spild->max_ipc_dev; i++) {
+ for (i = 0; i < ld->max_ipc_dev; i++) {
while ((skb = skb_dequeue(ld->skb_txq[i]))) {
ret = spi_buff_write(p_spild, i, skb->data, skb->len);
if (!ret) {
@@ -331,7 +331,7 @@ static void spi_start_data_send(void)
ld = &p_spild->ld;
- for (i = 0; i < p_spild->max_ipc_dev; i++) {
+ for (i = 0; i < ld->max_ipc_dev; i++) {
if (skb_queue_len(ld->skb_txq[i]) > 0)
spi_send_work(SPI_WORK_SEND, SPI_WORK);
}
@@ -345,6 +345,14 @@ static void spi_tx_work(void)
char *spi_sync_buf;
spild = p_spild;
+ iod = link_get_iod_with_format(&spild->ld, IPC_FMT);
+ if (!iod) {
+ mif_err("no iodevice for modem control\n");
+ return;
+ }
+
+ if (iod->mc->phone_state == STATE_CRASH_EXIT)
+ return;
/* check SUB SRDY, SRDY state */
if (gpio_get_value(spild->gpio_ipc_sub_srdy) ==
@@ -420,8 +428,6 @@ static void spi_tx_work(void)
pr_err("[SPI] spi_dev_send fail\n");
/* add cp reset when spi sync fail */
- iod = link_get_iod_with_format(&spild->ld, IPC_FMT);
-
if (iod)
iod->modem_state_changed(iod,
STATE_CRASH_RESET);
@@ -553,6 +559,15 @@ static void spi_rx_work(void)
if (!spild)
pr_err("[LNK/E] <%s> dpld == NULL\n", __func__);
+ iod = link_get_iod_with_format(&spild->ld, IPC_FMT);
+ if (!iod) {
+ mif_err("no iodevice for modem control\n");
+ return;
+ }
+
+ if (iod->mc->phone_state == STATE_CRASH_EXIT)
+ return;
+
if (!wake_lock_active(&spild->spi_wake_lock) ||
gpio_get_value(spild->gpio_ipc_srdy) == SPI_GPIOLEVEL_LOW ||
get_console_suspended() ||
@@ -606,7 +621,7 @@ static void spi_rx_work(void)
/* parsing SPI packet */
if (spi_buff_read(spild) > 0) {
/* call function for send data to IPC, RAW, RFS */
- for (i = 0; i < spild->max_ipc_dev; i++) {
+ for (i = 0; i < ld->max_ipc_dev; i++) {
iod = spild->iod[i];
while ((skb = skb_dequeue(&spild->skb_rxq[i]))
!= NULL) {
@@ -623,8 +638,6 @@ static void spi_rx_work(void)
"spi sync failed");
/* add cp reset when spi sync fail */
- iod = link_get_iod_with_format(&spild->ld, IPC_FMT);
-
if (iod)
iod->modem_state_changed(iod,
STATE_CRASH_RESET);
@@ -639,6 +652,34 @@ static void spi_rx_work(void)
spi_start_data_send();
}
+
+static int spi_init_ipc(struct spi_link_device *spild)
+{
+ struct link_device *ld = &spild->ld;
+
+ int i;
+
+ /* Make aliases to each IO device */
+ for (i = 0; i < MAX_DEV_FORMAT; i++)
+ spild->iod[i] = link_get_iod_with_format(ld, i);
+
+ spild->iod[IPC_RAW] = spild->iod[IPC_MULTI_RAW];
+
+ /* List up the IO devices connected to each IPC channel */
+ for (i = 0; i < MAX_DEV_FORMAT; i++) {
+ if (spild->iod[i])
+ pr_err("[LNK] <%s:%s> spild->iod[%d]->name = %s\n",
+ __func__, ld->name, i, spild->iod[i]->name);
+ else
+ pr_err("[LNK] <%s:%s> No spild->iod[%d]\n",
+ __func__, ld->name, i);
+ }
+
+ ld->mode = LINK_MODE_IPC;
+
+ return 0;
+}
+
unsigned int sprd_crc_calc(char *buf_ptr, unsigned int len)
{
unsigned int i;
@@ -1239,10 +1280,19 @@ err3:
static void spi_send_modem_bin(struct work_struct *send_modem_w)
{
+ struct spi_link_device *spild;
+ struct io_device *iod;
int retval;
struct image_buf img;
unsigned long tick1, tick2 = 0;
+ spild = p_spild;
+ iod = link_get_iod_with_format(&spild->ld, IPC_FMT);
+ if (!iod) {
+ mif_err("no iodevice for modem control\n");
+ return;
+ }
+
tick1 = jiffies_to_msecs(jiffies);
retval = spi_send_modem_bin_xmit_img(MODEM_MAIN, &img);
@@ -1285,16 +1335,25 @@ static void spi_send_modem_bin(struct work_struct *send_modem_w)
tick2 = jiffies_to_msecs(jiffies);
pr_info("Downloading takes %lu msec\n", (tick2-tick1));
- complete_all(&p_spild->ril_init);
+ spi_init_ipc(p_spild);
+
sprd_boot_done = 1;
p_spild->ril_send_cnt = 0;
+ p_spild->spi_state = SPI_STATE_IDLE;
+ if (iod)
+ iod->modem_state_changed(iod,
+ STATE_ONLINE);
+ return;
err:
+ if (iod)
+ iod->modem_state_changed(iod,
+ STATE_OFFLINE);
return;
}
-static inline int _request_mem(struct ipc_spi *od)
+static inline int _request_mem(struct spi_v_buff *od)
{
if (!p_spild->p_virtual_buff) {
od->mmio = vmalloc(od->size);
@@ -1320,7 +1379,7 @@ void spi_tx_timer_callback(unsigned long param)
{
if (p_spild->spi_state == SPI_STATE_TX_WAIT) {
p_spild->spi_timer_tx_state = SPI_STATE_TIME_OVER;
- pr_err("[SPI] spi_tx_timer_callback -timer expires\n");
+ pr_debug("[SPI] spi_tx_timer_callback -timer expires\n");
}
}
@@ -1328,7 +1387,7 @@ void spi_rx_timer_callback(unsigned long param)
{
if (p_spild->spi_state == SPI_STATE_RX_WAIT) {
p_spild->spi_timer_rx_state = SPI_STATE_TIME_OVER;
- pr_err("[SPI] spi_rx_timer_callback -timer expires\n");
+ pr_debug("[SPI] spi_rx_timer_callback -timer expires\n");
}
}
@@ -1381,96 +1440,37 @@ static void spi_work(struct work_struct *work)
}
}
-static int spi_init_ipc(struct spi_link_device *spild)
+static int link_pm_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
{
- struct link_device *ld = &spild->ld;
-
- int i;
-
- /* Make aliases to each IO device */
- for (i = 0; i < MAX_DEV_FORMAT; i++)
- spild->iod[i] = link_get_iod_with_format(ld, i);
-
- spild->iod[IPC_RAW] = spild->iod[IPC_MULTI_RAW];
-
- /* List up the IO devices connected to each IPC channel */
- for (i = 0; i < MAX_DEV_FORMAT; i++) {
- if (spild->iod[i])
- pr_err("[LNK] <%s:%s> spild->iod[%d]->name = %s\n",
- __func__, ld->name, i, spild->iod[i]->name);
- else
- pr_err("[LNK] <%s:%s> No spild->iod[%d]\n",
- __func__, ld->name, i);
- }
-
- ld->mode = LINK_MODE_IPC;
-
- return 0;
-}
-
-static int spi_thread(void *data)
-{
- struct spi_link_device *spild = (struct spi_link_device *)data;
+ struct io_device *iod;
+ struct link_pm_data *pm_data =
+ container_of(this, struct link_pm_data, pm_notifier);
- if (lpcharge == 1) {
- pr_err("[LPM MODE] spi_thread_exit!\n");
- return 0;
+ iod = link_get_iod_with_format(&pm_data->spild->ld, IPC_FMT);
+ if (!iod) {
+ pr_err("no iodevice for modem control\n");
+ return NOTIFY_BAD;
}
- daemonize("spi_thread");
-
- pr_info("[%s] spi_thread start.\n", __func__);
- p_spild->boot_done = 1;
-
- wait_for_completion(&p_spild->ril_init);
-
- pr_info("[%s] ril_init completed.\n", __func__);
+ if (!gpio_get_value(iod->mc->gpio_phone_active))
+ return NOTIFY_DONE;
- pr_info("<%s> wait 2 sec... srdy : %d\n",
- __func__, gpio_get_value(spild->gpio_ipc_srdy));
- msleep_interruptible(1700);
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ /* set TD PDA Active High if previous state was LPA */
+ mif_info("TD PDA active low to LPA suspend spot\n");
+ gpio_set_value(iod->mc->gpio_pda_active, 0);
- while (gpio_get_value(spild->gpio_ipc_srdy))
- ;
- pr_info("(%s) cp booting... Done.\n", __func__);
-
- spi_init_ipc(spild);
-
- pr_info("[spi_thread] Start IPC Communication. SRDY : %d\n",
- gpio_get_value(spild->gpio_ipc_srdy));
-
- /* CP booting is already completed, just set submrdy to high */
- if (gpio_get_value(spild->gpio_ipc_sub_srdy) == SPI_GPIOLEVEL_HIGH) {
- gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_HIGH);
- pr_err("[spi_thread] CP booting is already completed\n");
+ return NOTIFY_OK;
+ case PM_POST_SUSPEND:
+ /* LPA to Kernel suspend and User Freezing task fail resume,
+ restore to LPA GPIO states. */
+ mif_info("TD PDA active High to LPA GPIO state\n");
+ gpio_set_value(iod->mc->gpio_pda_active, 1);
+ return NOTIFY_OK;
}
- /* CP booting is not completed.
- set submrdy to high and wait until subsrdy is high */
- else {
- pr_err("[spi_thread] CP booting is not completed. wait...\n");
-
- gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_HIGH);
- do {
- msleep_interruptible(5);
- } while (gpio_get_value(spild->gpio_ipc_sub_srdy) ==
- SPI_GPIOLEVEL_LOW);
-
- pr_err("[spi_thread] CP booting is done...\n");
- }
-
- if (p_spild->spi_is_restart)
- msleep_interruptible(100);
- else
- msleep_interruptible(30);
-
- gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_LOW);
-
- pr_info("(%s) spi sync done.\n", __func__);
-
- spild->spi_state = SPI_STATE_IDLE;
- p_spild->spi_is_restart = 0;
-
- return 0;
+ return NOTIFY_DONE;
}
static int spi_probe(struct spi_device *spi)
@@ -1512,8 +1512,7 @@ static struct spi_driver spi_driver = {
static int spi_link_init(void)
{
int ret;
- struct ipc_spi *od;
- struct task_struct *th;
+ struct spi_v_buff *od;
struct link_device *ld = &p_spild->ld;
p_spild->gpio_modem_bin_srdy = p_spild->gpio_ipc_srdy;
@@ -1522,7 +1521,7 @@ static int spi_link_init(void)
p_spild->gpio_ipc_mrdy, p_spild->gpio_modem_bin_srdy,
gpio_get_value(p_spild->gpio_ipc_srdy));
- od = kzalloc(sizeof(struct ipc_spi), GFP_KERNEL);
+ od = kzalloc(sizeof(struct spi_v_buff), GFP_KERNEL);
if (!od) {
pr_err("(%d) failed to allocate device\n", __LINE__);
ret = -ENOMEM;
@@ -1537,7 +1536,6 @@ static int spi_link_init(void)
if (ret)
goto err;
- init_completion(&p_spild->ril_init);
sema_init(&p_spild->srdy_sem, 0);
INIT_WORK(&p_spild->send_modem_w,
@@ -1563,12 +1561,7 @@ static int spi_link_init(void)
if (ret)
goto err;
- th = kthread_create(spi_thread, (void *)p_spild, "spi_thread");
- if (IS_ERR(th)) {
- pr_err("kernel_thread() failed\n");
- goto err;
- }
- wake_up_process(th);
+ p_spild->boot_done = 1;
pr_info("[%s] Done\n", __func__);
return 0;
@@ -1591,7 +1584,6 @@ void spi_set_restart(void)
gpio_set_value(p_spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_LOW);
p_spild->spi_state = SPI_STATE_END;
- p_spild->spi_is_restart = 1;
/* Flush SPI work queue */
flush_workqueue(p_spild->spi_wq);
@@ -1635,6 +1627,35 @@ exit:
}
EXPORT_SYMBOL(spi_thread_restart);
+static int spi_link_pm_init(struct spi_link_device *spild,
+ struct platform_device *pdev)
+{
+ struct modem_data *pdata =
+ (struct modem_data *)pdev->dev.platform_data;
+ struct modemlink_pm_data *pm_pdata;
+ struct link_pm_data *pm_data =
+ kzalloc(sizeof(struct link_pm_data), GFP_KERNEL);
+
+ if (!pdata || !pdata->link_pm_data) {
+ mif_err("platform data is NULL\n");
+ return -EINVAL;
+ }
+ pm_pdata = pdata->link_pm_data;
+
+ if (!pm_data) {
+ mif_err("link_pm_data is NULL\n");
+ return -ENOMEM;
+ }
+
+ pm_data->spild = spild;
+ spild->link_pm_data = pm_data;
+
+ pm_data->pm_notifier.notifier_call = link_pm_notifier_event;
+ register_pm_notifier(&pm_data->pm_notifier);
+
+ return 0;
+}
+
struct link_device *spi_create_link_device(struct platform_device *pdev)
{
struct spi_link_device *spild = NULL;
@@ -1689,9 +1710,9 @@ struct link_device *spi_create_link_device(struct platform_device *pdev)
}
spild->spi_state = SPI_STATE_END;
- spild->max_ipc_dev = IPC_RFS+1; /* FMT, RAW, RFS */
+ ld->max_ipc_dev = (IPC_RFS + 1); /* FMT, RAW, RFS */
- for (i = 0; i < spild->max_ipc_dev; i++)
+ for (i = 0; i < ld->max_ipc_dev; i++)
skb_queue_head_init(&spild->skb_rxq[i]);
/* Prepare a clean buffer for SPI access */
@@ -1738,6 +1759,11 @@ struct link_device *spi_create_link_device(struct platform_device *pdev)
goto err;
}
+ /* create link pm device */
+ ret = spi_link_pm_init(spild, pdev);
+ if (ret)
+ goto err;
+
/* Create SPI device */
ret = spi_link_init();
if (ret)
diff --git a/drivers/misc/modem_if/modem_link_device_spi.h b/drivers/misc/modem_if/modem_link_device_spi.h
index 210d815..b1b334f 100644
--- a/drivers/misc/modem_if/modem_link_device_spi.h
+++ b/drivers/misc/modem_if/modem_link_device_spi.h
@@ -18,7 +18,7 @@
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#define SPI_TIMER_TX_WAIT_TIME 60 /* ms */
@@ -135,20 +135,24 @@ struct spi_data_packet_header {
unsigned long more:1;
};
+struct link_pm_data {
+ struct miscdevice miscdev;
+ struct spi_link_device *spild;
+
+ struct notifier_block pm_notifier;
+};
+
struct spi_link_device {
struct link_device ld;
- /* Link to SPI control functions dependent on each platform */
- int max_ipc_dev;
-
/* Wakelock for SPI device */
struct wake_lock spi_wake_lock;
+
/* Workqueue for modem bin transfers */
struct workqueue_struct *ipc_spi_wq;
/* SPI state */
int spi_state;
- int spi_is_restart;
/* SPI Timer state */
int spi_timer_tx_state;
@@ -182,11 +186,13 @@ struct spi_link_device {
struct io_device *iod[MAX_DEV_FORMAT];
struct sk_buff_head skb_rxq[MAX_DEV_FORMAT];
+ /* LINK PM DEVICE DATA */
+ struct link_pm_data *link_pm_data;
+
/* Multi-purpose miscellaneous buffer */
u8 *buff;
u8 *sync_buff;
- struct completion ril_init;
struct semaphore srdy_sem;
int send_modem_spi;
@@ -202,6 +208,12 @@ struct spi_link_device {
#define to_spi_link_device(linkdev) \
container_of(linkdev, struct spi_link_device, ld)
+struct spi_v_buff {
+ unsigned long base;
+ unsigned long size;
+ void __iomem *mmio;
+};
+
extern unsigned int lpcharge;
extern int get_console_suspended(void);
static void spi_work(struct work_struct *work);
diff --git a/drivers/misc/modem_if/modem_link_device_usb.c b/drivers/misc/modem_if/modem_link_device_usb.c
index 14aee9f..9e6cbea 100644
--- a/drivers/misc/modem_if/modem_link_device_usb.c
+++ b/drivers/misc/modem_if/modem_link_device_usb.c
@@ -13,7 +13,7 @@
*
*/
-/* #define DEBUG */
+#define DEBUG
#include <linux/init.h>
#include <linux/module.h>
@@ -26,7 +26,7 @@
#include <linux/platform_device.h>
#include <linux/suspend.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_usb.h"
#include "modem_utils.h"
@@ -297,10 +297,15 @@ static void
usb_change_modem_state(struct usb_link_device *usb_ld, enum modem_state state)
{
struct io_device *iod;
+ struct io_device *bootd;
iod = link_get_iod_with_format(&usb_ld->ld, IPC_FMT);
if (iod)
iod->modem_state_changed(iod, state);
+
+ bootd = usb_ld->ld.mc->bootd;
+ if (bootd)
+ bootd->modem_state_changed(bootd, state);
}
static int usb_tx_urb_with_skb(struct usb_link_device *usb_ld,
@@ -624,7 +629,12 @@ static void if_usb_disconnect(struct usb_interface *intf)
cancel_delayed_work_sync(&usb_ld->ld.tx_delayed_work);
usb_put_dev(usbdev);
usb_ld->usbdev = NULL;
- pm_runtime_forbid(pm_data->root_hub);
+ if (!has_hub(usb_ld)) {
+ if (pm_data->root_hub)
+ pm_runtime_forbid(pm_data->root_hub);
+ schedule_delayed_work(&usb_ld->wait_enumeration,
+ WAIT_ENUMURATION_TIMEOUT_JIFFIES);
+ }
}
}
diff --git a/drivers/misc/modem_if/modem_link_pm_usb.c b/drivers/misc/modem_if/modem_link_pm_usb.c
index 75ad970..c63f08e 100644
--- a/drivers/misc/modem_if/modem_link_pm_usb.c
+++ b/drivers/misc/modem_if/modem_link_pm_usb.c
@@ -12,7 +12,7 @@
*
*/
-/* #define DEBUG */
+#define DEBUG
#include <linux/init.h>
#include <linux/module.h>
@@ -27,12 +27,15 @@
#include "modem_link_pm_usb.h"
+int during_hub_resume;
+
static inline void start_hub_work(struct link_pm_data *pm_data, int delay)
{
if (pm_data->hub_work_running == false) {
pm_data->hub_work_running = true;
wake_lock(&pm_data->hub_lock);
mif_debug("link_pm_hub_work is started\n");
+ during_hub_resume = 1;
}
schedule_delayed_work(&pm_data->link_pm_hub, msecs_to_jiffies(delay));
@@ -81,12 +84,13 @@ void link_pm_preactive(struct link_pm_data *pm_data)
static void link_pm_hub_work(struct work_struct *work)
{
- int err;
+ int err, cnt;
struct link_pm_data *pm_data =
container_of(work, struct link_pm_data, link_pm_hub.work);
if (pm_data->hub_status == HUB_STATE_ACTIVE) {
end_hub_work(pm_data);
+ during_hub_resume = 0;
return;
}
@@ -111,7 +115,16 @@ static void link_pm_hub_work(struct work_struct *work)
/* skip 1st time before first probe */
if (pm_data->root_hub)
pm_runtime_get_sync(pm_data->root_hub);
- err = pm_data->port_enable(2, 1);
+
+ for (cnt=0;cnt<5;cnt++) {
+ err = pm_data->port_enable(2, 1);
+ if (err >= 0) {
+ mif_err("hub on success\n");
+ break;
+ }
+ mif_err("hub on fail %d th\n", cnt);
+ msleep(100);
+ }
if (err < 0) {
mif_err("hub on fail err=%d\n", err);
err = pm_data->port_enable(2, 0);
@@ -132,6 +145,8 @@ static void link_pm_hub_work(struct work_struct *work)
pm_data->hub_status = HUB_STATE_OFF;
if (pm_data->root_hub)
pm_runtime_put_sync(pm_data->root_hub);
+
+ mif_err("USB Hub resume fail !!!\n");
end_hub_work(pm_data);
} else {
mif_info("hub resumming: %d\n",
@@ -164,9 +179,6 @@ static int link_pm_hub_standby(void *args)
/* this function is atomic.
* make force disconnect in workqueue..
*/
- if (pm_data->usb_ld->if_usb_connected)
- schedule_work(&usb_ld->disconnect_work);
-
return err;
}
@@ -210,6 +222,7 @@ static long link_pm_ioctl(struct file *file, unsigned int cmd,
sizeof(int)))
return -EFAULT;
gpio_set_value(pm_data->gpio_link_active, value);
+ mif_info("> H-ACT %d\n", value);
break;
case IOCTL_LINK_GET_HOSTWAKE:
return !gpio_get_value(pm_data->gpio_link_hostwake);
@@ -233,7 +246,7 @@ static long link_pm_ioctl(struct file *file, unsigned int cmd,
case IOCTL_LINK_PORT_OFF:
err = link_pm_hub_standby(pm_data);
if (err < 0) {
- mif_err("usb3503 active fail\n");
+ mif_err("usb3503 standby fail\n");
goto exit;
}
pm_data->hub_init_lock = 1;
@@ -363,6 +376,8 @@ int link_pm_init(struct usb_link_device *usb_ld, void *data)
pm_data->miscdev.name = "link_pm";
pm_data->miscdev.fops = &link_pm_fops;
+ during_hub_resume = 0;
+
err = misc_register(&pm_data->miscdev);
if (err < 0) {
mif_err("fail to register pm device(%d)\n", err);
diff --git a/drivers/misc/modem_if/modem_link_pm_usb.h b/drivers/misc/modem_if/modem_link_pm_usb.h
index d26af76..5fc762d 100644
--- a/drivers/misc/modem_if/modem_link_pm_usb.h
+++ b/drivers/misc/modem_if/modem_link_pm_usb.h
@@ -15,7 +15,7 @@
#ifndef __MODEM_LINK_PM_USB_H__
#define __MODEM_LINK_PM_USB_H__
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_usb.h"
diff --git a/drivers/misc/modem_if/modem_modemctl_device_cbp71.c b/drivers/misc/modem_if/modem_modemctl_device_cbp71.c
index 28f2ce7..5a4db56 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_cbp71.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_cbp71.c
@@ -23,7 +23,7 @@
#include <linux/wait.h>
#include <linux/sched.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_dpram.h"
diff --git a/drivers/misc/modem_if/modem_modemctl_device_cbp72.c b/drivers/misc/modem_if/modem_modemctl_device_cbp72.c
index 2617be8..d8f2af9 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_cbp72.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_cbp72.c
@@ -1,6 +1,4 @@
-/* /linux/drivers/misc/modem_if/modem_modemctl_device_cbp7.1.c
- *
- * Copyright (C) 2010 Google, Inc.
+/*
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -24,14 +22,13 @@
#include <linux/sched.h>
#include <linux/platform_device.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_link_device_dpram.h"
#define PIF_TIMEOUT (180 * HZ)
#define DPRAM_INIT_TIMEOUT (30 * HZ)
-
static irqreturn_t phone_active_handler(int irq, void *arg)
{
struct modem_ctl *mc = (struct modem_ctl *)arg;
@@ -163,13 +160,13 @@ static int cbp72_boot_off(struct modem_ctl *mc)
{
int ret;
struct link_device *ld = get_current_link(mc->bootd);
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
+
mif_debug("\n");
/* Wait here until the PHONE is up.
* Waiting as the this called from IOCTL->UM thread */
mif_info("Waiting for INT_CMD_PHONE_START\n");
- ret = wait_for_completion_interruptible_timeout(
- &dpld->dpram_init_cmd, DPRAM_INIT_TIMEOUT);
+ ret = wait_for_completion_interruptible_timeout(&ld->init_cmpl,
+ DPRAM_INIT_TIMEOUT);
if (!ret) {
/* ret == 0 on timeout, ret < 0 if interrupted */
mif_err("Timeout!!! (PHONE_START was not arrived.)\n");
@@ -177,8 +174,8 @@ static int cbp72_boot_off(struct modem_ctl *mc)
}
mif_info("Waiting for INT_CMD_PIF_INIT_DONE\n");
- ret = wait_for_completion_interruptible_timeout(
- &dpld->modem_pif_init_done, PIF_TIMEOUT);
+ ret = wait_for_completion_interruptible_timeout(&ld->pif_cmpl,
+ PIF_TIMEOUT);
if (!ret) {
mif_err("Timeout!!! (PIF_INIT_DONE was not arrived.)\n");
return -ENXIO;
@@ -199,10 +196,6 @@ static int cbp72_force_crash_exit(struct modem_ctl *mc)
/* Make DUMP start */
ld->force_dump(ld, mc->bootd);
- msleep_interruptible(1000);
-
- mc->bootd->modem_state_changed(mc->bootd, STATE_CRASH_EXIT);
-
return 0;
}
@@ -221,16 +214,15 @@ int cbp72_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
int ret = 0;
int irq = 0;
unsigned long flag = 0;
- struct platform_device *pdev = NULL;
-
- mc->gpio_cp_on = pdata->gpio_cp_on;
- mc->gpio_cp_off = pdata->gpio_cp_off;
- mc->gpio_reset_req_n = pdata->gpio_reset_req_n;
- mc->gpio_cp_reset = pdata->gpio_cp_reset;
- mc->gpio_pda_active = pdata->gpio_pda_active;
- mc->gpio_phone_active = pdata->gpio_phone_active;
- mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int;
- mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel;
+
+ mc->gpio_cp_on = pdata->gpio_cp_on;
+ mc->gpio_cp_off = pdata->gpio_cp_off;
+ mc->gpio_reset_req_n = pdata->gpio_reset_req_n;
+ mc->gpio_cp_reset = pdata->gpio_cp_reset;
+ mc->gpio_pda_active = pdata->gpio_pda_active;
+ mc->gpio_phone_active = pdata->gpio_phone_active;
+ mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int;
+ mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel;
mc->gpio_cp_warm_reset = pdata->gpio_cp_warm_reset;
if (!mc->gpio_cp_on || !mc->gpio_cp_reset || !mc->gpio_phone_active) {
@@ -245,10 +237,9 @@ int cbp72_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
cbp72_get_ops(mc);
- pdev = to_platform_device(mc->dev);
- mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq");
+ mc->irq_phone_active = pdata->irq_phone_active;
if (!mc->irq_phone_active) {
- mif_err("get irq fail\n");
+ mif_err("get irq_phone_active fail\n");
return -1;
}
diff --git a/drivers/misc/modem_if/modem_modemctl_device_cbp82.c b/drivers/misc/modem_if/modem_modemctl_device_cbp82.c
new file mode 100644
index 0000000..dc5799e
--- /dev/null
+++ b/drivers/misc/modem_if/modem_modemctl_device_cbp82.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/init.h>
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+
+#include "modem.h"
+#include "modem_prj.h"
+#include "modem_utils.h"
+
+#define DPRAM_INIT_TIMEOUT (30 * HZ)
+#define PIF_TIMEOUT (180 * HZ)
+
+static irqreturn_t phone_active_handler(int irq, void *arg)
+{
+ struct modem_ctl *mc = (struct modem_ctl *)arg;
+ int cp_on = gpio_get_value(mc->gpio_cp_on);
+ int cp_reset = gpio_get_value(mc->gpio_cp_reset);
+ int cp_active = gpio_get_value(mc->gpio_phone_active);
+ int old_state = mc->phone_state;
+ int new_state = mc->phone_state;
+
+ mif_info("old_state:%s cp_on:%d cp_reset:%d cp_active:%d\n",
+ get_cp_state_str(old_state), cp_on, cp_reset, cp_active);
+
+ if (cp_reset && cp_active) {
+ if (mc->phone_state == STATE_BOOTING) {
+ new_state = STATE_ONLINE;
+ mc->bootd->modem_state_changed(mc->bootd, new_state);
+ }
+ } else if (cp_reset && !cp_active) {
+ if (mc->phone_state == STATE_ONLINE) {
+ new_state = STATE_CRASH_EXIT;
+ mc->bootd->modem_state_changed(mc->bootd, new_state);
+ }
+ } else {
+ new_state = STATE_OFFLINE;
+ if (mc->bootd && mc->bootd->modem_state_changed)
+ mc->bootd->modem_state_changed(mc->bootd, new_state);
+ }
+
+ if (new_state != old_state) {
+ mif_err("%s: phone_state changed (%s -> %s\n)",
+ mc->name, get_cp_state_str(old_state),
+ get_cp_state_str(new_state));
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int cbp82_on(struct modem_ctl *mc)
+{
+ int cp_on = gpio_get_value(mc->gpio_cp_on);
+ int cp_off = gpio_get_value(mc->gpio_cp_off);
+ int cp_reset = gpio_get_value(mc->gpio_cp_reset);
+ int cp_active = gpio_get_value(mc->gpio_phone_active);
+ mif_err("+++\n");
+
+ mif_err("phone_state:%s cp_on:%d cp_off:%d cp_reset:%d cp_active:%d\n",
+ get_cp_state_str(mc->phone_state), cp_on, cp_off, cp_reset,
+ cp_active);
+
+ /* prevent sleep during bootloader downloading */
+ if (!wake_lock_active(&mc->mc_wake_lock))
+ wake_lock(&mc->mc_wake_lock);
+
+ gpio_set_value(mc->gpio_cp_on, 0);
+ gpio_set_value(mc->gpio_cp_off, 1);
+ gpio_set_value(mc->gpio_cp_reset, 0);
+
+ msleep(500);
+
+ cp_on = gpio_get_value(mc->gpio_cp_on);
+ cp_off = gpio_get_value(mc->gpio_cp_off);
+ cp_reset = gpio_get_value(mc->gpio_cp_reset);
+ cp_active = gpio_get_value(mc->gpio_phone_active);
+ mif_err("phone_state:%s cp_on:%d cp_off:%d cp_reset:%d cp_active:%d\n",
+ get_cp_state_str(mc->phone_state), cp_on, cp_off, cp_reset,
+ cp_active);
+
+ gpio_set_value(mc->gpio_cp_off, 0);
+ gpio_set_value(mc->gpio_cp_on, 1);
+
+ msleep(100);
+
+ gpio_set_value(mc->gpio_cp_reset, 1);
+
+ msleep(300);
+
+ cp_on = gpio_get_value(mc->gpio_cp_on);
+ cp_off = gpio_get_value(mc->gpio_cp_off);
+ cp_reset = gpio_get_value(mc->gpio_cp_reset);
+ cp_active = gpio_get_value(mc->gpio_phone_active);
+ mif_err("phone_state:%s cp_on:%d cp_off:%d cp_reset:%d cp_active:%d\n",
+ get_cp_state_str(mc->phone_state), cp_on, cp_off, cp_reset,
+ cp_active);
+
+ if (mc->gpio_pda_active)
+ gpio_set_value(mc->gpio_pda_active, 1);
+
+ if (mc->bootd)
+ mc->bootd->modem_state_changed(mc->bootd, STATE_BOOTING);
+ else
+ mif_err("no mc->bootd\n");
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int cbp82_off(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+ mif_err("+++\n");
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ gpio_set_value(mc->gpio_cp_on, 0);
+ gpio_set_value(mc->gpio_cp_off, 1);
+
+ mc->bootd->modem_state_changed(mc->bootd, STATE_OFFLINE);
+ ld->mode = LINK_MODE_OFFLINE;
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int cbp82_reset(struct modem_ctl *mc)
+{
+ int ret = 0;
+
+ mif_debug("cbp82_reset()\n");
+
+ ret = cbp82_off(mc);
+ if (ret)
+ return -ENXIO;
+
+ msleep(100);
+
+ ret = cbp82_on(mc);
+ if (ret)
+ return -ENXIO;
+
+ return 0;
+}
+
+static int cbp82_boot_on(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+ mif_info("+++\n");
+
+ ld->mode = LINK_MODE_BOOT;
+
+ mif_info("---\n");
+ return 0;
+}
+
+static int cbp82_boot_off(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+ int ret;
+ mif_err("+++\n");
+
+ /* Wait here until the PHONE is up.
+ * Waiting as the this called from IOCTL->UM thread */
+ mif_err("Waiting for PHONE_START\n");
+ ret = wait_for_completion_timeout(&ld->init_cmpl, DPRAM_INIT_TIMEOUT);
+ if (!ret) {
+ /* ret == 0 on timeout */
+ mif_err("T-I-M-E-O-U-T (PHONE_START)\n");
+ cbp82_off(mc);
+ ret = -EIO;
+ goto exit;
+ }
+ mif_err("recv PHONE_START\n");
+
+ mif_err("Waiting for PIF_INIT_DONE\n");
+ ret = wait_for_completion_timeout(&ld->pif_cmpl, PIF_TIMEOUT);
+ if (!ret) {
+ /* ret == 0 on timeout */
+ mif_err("T-I-M-E-O-U-T (PIF_INIT_DONE)!!!\n");
+ cbp82_off(mc);
+ ret = -EIO;
+ goto exit;
+ }
+ mif_err("recv PIF_INIT_DONE\n");
+
+ mc->bootd->modem_state_changed(mc->bootd, STATE_ONLINE);
+ ret = 0;
+
+exit:
+ wake_unlock(&mc->mc_wake_lock);
+ mif_err("---\n");
+ return ret;
+}
+
+static int cbp82_force_crash_exit(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+
+ mif_err("device = %s\n", mc->bootd->name);
+
+ /* Make DUMP start */
+ ld->force_dump(ld, mc->bootd);
+
+ return 0;
+}
+
+static void cbp82_get_ops(struct modem_ctl *mc)
+{
+ mc->ops.modem_on = cbp82_on;
+ mc->ops.modem_off = cbp82_off;
+ mc->ops.modem_reset = cbp82_reset;
+ mc->ops.modem_boot_on = cbp82_boot_on;
+ mc->ops.modem_boot_off = cbp82_boot_off;
+ mc->ops.modem_force_crash_exit = cbp82_force_crash_exit;
+}
+
+int cbp82_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
+{
+ int ret = 0;
+ int irq = 0;
+ unsigned long flag = 0;
+ mif_err("+++\n");
+
+ mc->gpio_cp_on = pdata->gpio_cp_on;
+ mc->gpio_cp_off = pdata->gpio_cp_off;
+ mc->gpio_cp_reset = pdata->gpio_cp_reset;
+ mc->gpio_phone_active = pdata->gpio_phone_active;
+
+ if (!mc->gpio_cp_on || !mc->gpio_cp_off || !mc->gpio_cp_reset
+ || !mc->gpio_phone_active) {
+ mif_err("no GPIO data\n");
+ mif_err("---\n");
+ return -ENXIO;
+ }
+
+ mc->gpio_pda_active = pdata->gpio_pda_active;
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ gpio_set_value(mc->gpio_cp_off, 1);
+ gpio_set_value(mc->gpio_cp_on, 0);
+
+ cbp82_get_ops(mc);
+
+ wake_lock_init(&mc->mc_wake_lock, WAKE_LOCK_SUSPEND, "cbp82_wake_lock");
+
+ mc->irq_phone_active = pdata->irq_phone_active;
+ if (!mc->irq_phone_active) {
+ mif_err("get irq fail\n");
+ mif_err("---\n");
+ return -1;
+ }
+ mif_info("PHONE_ACTIVE IRQ# = %d\n", mc->irq_phone_active);
+
+ irq = mc->irq_phone_active;
+ flag = IRQF_NO_SUSPEND | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
+ ret = request_irq(irq, phone_active_handler, flag, "cdma_active", mc);
+ if (ret) {
+ mif_err("request_irq fail (%d)\n", ret);
+ mif_err("---\n");
+ return ret;
+ }
+
+ ret = enable_irq_wake(irq);
+ if (ret)
+ mif_err("enable_irq_wake fail (%d)\n", ret);
+
+ mif_err("---\n");
+ return 0;
+}
+
diff --git a/drivers/misc/modem_if/modem_modemctl_device_cmc221.c b/drivers/misc/modem_if/modem_modemctl_device_cmc221.c
index fe8ce69..a960edb 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_cmc221.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_cmc221.c
@@ -1,6 +1,4 @@
-/* /linux/drivers/misc/modem_if/modem_modemctl_device_cmc221.c
- *
- * Copyright (C) 2010 Google, Inc.
+/*
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -13,15 +11,15 @@
* GNU General Public License for more details.
*
*/
-#include <linux/init.h>
+#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include "modem.h"
-#include <linux/platform_data/modem.h>
#include "modem_prj.h"
#include "modem_link_device_usb.h"
#include "modem_link_device_dpram.h"
@@ -77,7 +75,7 @@ static irqreturn_t phone_active_handler(int irq, void *arg)
static irqreturn_t dynamic_switching_handler(int irq, void *arg)
{
struct modem_ctl *mc = (struct modem_ctl *)arg;
- int txpath = gpio_get_value(mc->gpio_dynamic_switching);
+ int txpath = gpio_get_value(mc->gpio_link_switch);
bool enumerated = usb_is_enumerated(mc->msd);
mif_err("txpath=%d, enumeration=%d\n", txpath, enumerated);
@@ -94,6 +92,52 @@ static irqreturn_t dynamic_switching_handler(int irq, void *arg)
return IRQ_HANDLED;
}
+#ifdef CONFIG_EXYNOS4_CPUFREQ /* Set cpu clock to 800MHz for high TP */
+static void cmc221_cpufreq_lock(struct work_struct *work)
+{
+ struct modem_ctl *mc;
+
+ mc = container_of(work, struct modem_ctl, work_cpu_lock.work);
+ if (mc->mdm_data->link_pm_data->freq_lock) {
+ mif_debug("Call freq lock func.\n");
+ mc->mdm_data->link_pm_data->freq_lock(mc->dev);
+
+ cancel_delayed_work(&mc->work_cpu_unlock);
+ schedule_delayed_work(&mc->work_cpu_unlock,
+ msecs_to_jiffies(5000));
+ }
+}
+
+static void cmc221_cpufreq_unlock(struct work_struct *work)
+{
+ struct modem_ctl *mc;
+ int tp_level;
+
+ mc = container_of(work, struct modem_ctl, work_cpu_unlock.work);
+ tp_level = gpio_get_value(mc->gpio_cpufreq_lock);
+
+ mif_debug("TP Level is (%d)\n", tp_level);
+ if (tp_level) {
+ mif_debug("maintain cpufreq lock !!!\n");
+ schedule_delayed_work(&mc->work_cpu_unlock,
+ msecs_to_jiffies(5000));
+ } else {
+ if (mc->mdm_data->link_pm_data->freq_unlock) {
+ mif_debug("Call freq unlock func.\n");
+ mc->mdm_data->link_pm_data->freq_unlock(mc->dev);
+ }
+ }
+}
+
+static irqreturn_t cpufreq_lock_handler(int irq, void *arg)
+{
+ struct modem_ctl *mc = (struct modem_ctl *)arg;
+
+ schedule_delayed_work(&mc->work_cpu_lock, 0);
+ return IRQ_HANDLED;
+}
+#endif
+
static int cmc221_on(struct modem_ctl *mc)
{
struct link_device *ld = get_current_link(mc->iod);
@@ -204,11 +248,10 @@ static int cmc221_boot_off(struct modem_ctl *mc)
{
int ret;
struct link_device *ld = get_current_link(mc->bootd);
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
mif_err("%s\n", mc->name);
- ret = wait_for_completion_interruptible_timeout(&dpld->dpram_init_cmd,
+ ret = wait_for_completion_interruptible_timeout(&ld->init_cmpl,
DPRAM_INIT_TIMEOUT);
if (!ret) {
/* ret == 0 on timeout, ret < 0 if interrupted */
@@ -249,22 +292,23 @@ int cmc221_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
int ret = 0;
int irq = 0;
unsigned long flag = 0;
- struct platform_device *pdev = NULL;
- mc->gpio_cp_on = pdata->gpio_cp_on;
- mc->gpio_cp_reset = pdata->gpio_cp_reset;
+ mc->gpio_cp_on = pdata->gpio_cp_on;
+ mc->gpio_cp_reset = pdata->gpio_cp_reset;
mc->gpio_phone_active = pdata->gpio_phone_active;
- mc->gpio_pda_active = pdata->gpio_pda_active;
+ mc->gpio_pda_active = pdata->gpio_pda_active;
#if 0 /*TODO: check the GPIO map*/
- mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int;
+ mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int;
mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel;
mc->gpio_slave_wakeup = pdata->gpio_slave_wakeup;
- mc->gpio_host_active = pdata->gpio_host_active;
- mc->gpio_host_wakeup = pdata->gpio_host_wakeup;
+ mc->gpio_host_active = pdata->gpio_host_active;
+ mc->gpio_host_wakeup = pdata->gpio_host_wakeup;
#endif
- mc->gpio_dynamic_switching = pdata->gpio_dynamic_switching;
+ mc->gpio_link_switch = pdata->gpio_link_switch;
mc->need_switch_to_usb = false;
-
+#ifdef CONFIG_EXYNOS4_CPUFREQ
+ mc->gpio_cpufreq_lock = pdata->gpio_cpufreq_lock;
+#endif
if (!mc->gpio_cp_on || !mc->gpio_cp_reset || !mc->gpio_phone_active) {
mif_err("%s: ERR! no GPIO data\n", mc->name);
return -ENXIO;
@@ -276,10 +320,9 @@ int cmc221_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
cmc221_get_ops(mc);
dev_set_drvdata(mc->dev, mc);
- pdev = to_platform_device(mc->dev);
- mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq");
+ mc->irq_phone_active = pdata->irq_phone_active;
if (!mc->irq_phone_active) {
- mif_err("%s: ERR! get cp_active_irq fail\n", mc->name);
+ mif_err("%s: ERR! get irq_phone_active fail\n", mc->name);
return -1;
}
mif_err("%s: PHONE_ACTIVE IRQ# = %d\n", mc->name, mc->irq_phone_active);
@@ -301,8 +344,8 @@ int cmc221_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
}
flag = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND;
- if (mc->gpio_dynamic_switching) {
- irq = gpio_to_irq(mc->gpio_dynamic_switching);
+ if (mc->gpio_link_switch) {
+ irq = gpio_to_irq(mc->gpio_link_switch);
mif_err("%s: DYNAMIC_SWITCH IRQ# = %d\n", mc->name, irq);
ret = request_irq(irq, dynamic_switching_handler, flag,
"dynamic_switching", mc);
@@ -313,5 +356,23 @@ int cmc221_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
}
}
+#ifdef CONFIG_EXYNOS4_CPUFREQ
+ INIT_DELAYED_WORK(&mc->work_cpu_lock, cmc221_cpufreq_lock);
+ INIT_DELAYED_WORK(&mc->work_cpu_unlock, cmc221_cpufreq_unlock);
+
+ flag = IRQF_TRIGGER_RISING;
+ if (mc->gpio_cpufreq_lock) {
+ irq = gpio_to_irq(mc->gpio_cpufreq_lock);
+ mif_err("%s: CPUFREQ_LOCK_CNT IRQ# = %d\n", mc->name, irq);
+ ret = request_irq(irq, cpufreq_lock_handler, flag,
+ "cpufreq_lock", mc);
+ if (ret) {
+ mif_err("%s: ERR! request_irq(#%d) fail (err %d)\n",
+ mc->name, irq, ret);
+ return ret;
+ }
+ }
+#endif
+
return 0;
}
diff --git a/drivers/misc/modem_if/modem_modemctl_device_esc6270.c b/drivers/misc/modem_if/modem_modemctl_device_esc6270.c
index 5a42755..79cdd95 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_esc6270.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_esc6270.c
@@ -24,7 +24,7 @@
#include <linux/sched.h>
#include <linux/platform_device.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include <linux/regulator/consumer.h>
@@ -115,6 +115,13 @@ static int esc6270_reset(struct modem_ctl *mc)
int esc6270_boot_on(struct modem_ctl *mc)
{
struct link_device *ld = get_current_link(mc->iod);
+#if defined(CONFIG_LINK_DEVICE_DPRAM)
+ /* clear intr */
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+ u16 recv_msg = dpld->recv_intr(dpld);
+
+ pr_info("[MODEM_IF:ESC] dpram intr: %x\n", recv_msg);
+#endif
pr_info("[MODEM_IF:ESC] <%s>\n", __func__);
@@ -273,8 +280,11 @@ int esc6270_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
gpio_set_value(mc->gpio_cp_reset, 0);
gpio_set_value(mc->gpio_cp_on, 0);
- pdev = to_platform_device(mc->dev);
- mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq");
+ mc->irq_phone_active = pdata->irq_phone_active;
+ if (!mc->irq_phone_active) {
+ mif_err("%s: ERR! get irq_phone_active fail\n", mc->name);
+ return -1;
+ }
pr_info("[MODEM_IF:ESC] <%s> PHONE_ACTIVE IRQ# = %d\n",
__func__, mc->irq_phone_active);
@@ -302,7 +312,7 @@ int esc6270_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
}
#if defined(CONFIG_SIM_DETECT)
- mc->irq_sim_detect = platform_get_irq_byname(pdev, "sim_irq");
+ mc->irq_sim_detect = pdata->irq_sim_detect;
pr_info("[MODEM_IF:ESC] <%s> SIM_DECTCT IRQ# = %d\n",
__func__, mc->irq_sim_detect);
diff --git a/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c b/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c
index ad44579..38bef9a 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c
@@ -24,12 +24,14 @@
#include <linux/sched.h>
#include <linux/platform_device.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include <linux/regulator/consumer.h>
#include <plat/gpio-cfg.h>
+#include "modem_link_device_pld.h"
+
#if defined(CONFIG_MACH_M0_CTC)
#include <linux/mfd/max77693.h>
#endif
@@ -39,6 +41,8 @@
static int mdm6600_on(struct modem_ctl *mc)
{
+ struct link_device *ld = get_current_link(mc->iod);
+
pr_info("[MODEM_IF] mdm6600_on()\n");
if (!mc->gpio_cp_reset || !mc->gpio_cp_reset_msm || !mc->gpio_cp_on) {
@@ -58,6 +62,7 @@ static int mdm6600_on(struct modem_ctl *mc)
gpio_set_value(mc->gpio_pda_active, 1);
mc->iod->modem_state_changed(mc->iod, STATE_BOOTING);
+ ld->mode = LINK_MODE_BOOT;
return 0;
}
@@ -82,7 +87,8 @@ static int mdm6600_off(struct modem_ctl *mc)
static int mdm6600_reset(struct modem_ctl *mc)
{
- int ret;
+ struct link_device *ld = get_current_link(mc->iod);
+ /* int ret; */
pr_info("[MODEM_IF] mdm6600_reset()\n");
@@ -109,6 +115,9 @@ static int mdm6600_reset(struct modem_ctl *mc)
msleep(40); /* > 37.2 + 2 msec */
}
+ mc->iod->modem_state_changed(mc->iod, STATE_BOOTING);
+ ld->mode = LINK_MODE_BOOT;
+
return 0;
}
@@ -159,6 +168,7 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
int cp_dump_value = 0;
int phone_state = 0;
struct modem_ctl *mc = (struct modem_ctl *)_mc;
+ struct link_device *ld;
if (!mc->gpio_cp_reset || !mc->gpio_phone_active
/*|| !mc->gpio_cp_dump_int */) {
@@ -179,11 +189,6 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
} else if (phone_reset && !phone_active_value) {
if (count == 1) {
phone_state = STATE_CRASH_EXIT;
- if (mc->iod) {
- ld = get_current_link(mc->iod);
- if (ld->terminate_comm)
- ld->terminate_comm(ld, mc->iod);
- }
if (mc->iod && mc->iod->modem_state_changed)
mc->iod->modem_state_changed
(mc->iod, phone_state);
@@ -226,8 +231,11 @@ int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
mc->vbus_on = pdata->vbus_on;
mc->vbus_off = pdata->vbus_off;
- pdev = to_platform_device(mc->dev);
- mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq");
+ mc->irq_phone_active = pdata->irq_phone_active;
+ if (!mc->irq_phone_active) {
+ mif_err("%s: ERR! get irq_phone_active fail\n", mc->name);
+ return -1;
+ }
pr_info("[MODEM_IF] <%s> PHONE_ACTIVE IRQ# = %d\n",
__func__, mc->irq_phone_active);
@@ -332,7 +340,7 @@ static int mdm6600_on(struct modem_ctl *mc)
return -ENXIO;
}
- gpio_set_value(mc->gpio_pda_active, 0);
+ gpio_set_value(mc->gpio_pda_active, 1);
gpio_set_value(mc->gpio_cp_on, 1);
msleep(500);
@@ -346,8 +354,6 @@ static int mdm6600_on(struct modem_ctl *mc)
gpio_set_value(mc->gpio_cp_on, 0);
msleep(500);
- gpio_set_value(mc->gpio_pda_active, 1);
-
#if defined(CONFIG_LINK_DEVICE_PLD)
gpio_set_value(mc->gpio_fpga_cs_n, 1);
#endif
@@ -420,9 +426,13 @@ static int mdm6600_reset(struct modem_ctl *mc)
static int mdm6600_boot_on(struct modem_ctl *mc)
{
struct regulator *regulator;
+ struct link_device *ld = get_current_link(mc->iod);
+ struct pld_link_device *dpld = to_pld_link_device(ld);
pr_info("[MSM] <%s>\n", __func__);
+ dpld->recv_intr(dpld);
+
if (!mc->gpio_flm_uart_sel) {
pr_err("[MSM] no gpio data\n");
return -ENXIO;
@@ -729,8 +739,11 @@ int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
gpio_set_value(mc->gpio_cp_reset, 0);
gpio_set_value(mc->gpio_cp_on, 0);
- pdev = to_platform_device(mc->dev);
- mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq");
+ mc->irq_phone_active = pdata->irq_phone_active;
+ if (!mc->irq_phone_active) {
+ mif_err("%s: ERR! get irq_phone_active fail\n", mc->name);
+ return -1;
+ }
pr_info("[MSM] <%s> PHONE_ACTIVE IRQ# = %d\n",
__func__, mc->irq_phone_active);
@@ -754,7 +767,7 @@ int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
}
#if defined(CONFIG_SIM_DETECT)
- mc->irq_sim_detect = platform_get_irq_byname(pdev, "sim_irq");
+ mc->irq_sim_detect = pdata->irq_sim_detect;
pr_info("[MSM] <%s> SIM_DECTCT IRQ# = %d\n",
__func__, mc->irq_sim_detect);
diff --git a/drivers/misc/modem_if/modem_modemctl_device_qsc6085.c b/drivers/misc/modem_if/modem_modemctl_device_qsc6085.c
new file mode 100644
index 0000000..25d3cfe
--- /dev/null
+++ b/drivers/misc/modem_if/modem_modemctl_device_qsc6085.c
@@ -0,0 +1,218 @@
+/* /linux/drivers/misc/modem_if/modem_modemctl_device_qsc6085.c
+ *
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include "modem.h"
+
+#include "modem_prj.h"
+#include "modem_link_device_dpram.h"
+#include "modem_utils.h"
+
+#define IDPRAM_NORMAL_BOOT_MAGIC 0x4D4E
+
+static irqreturn_t phone_active_irq_handler(int irq, void *arg)
+{
+ struct modem_ctl *mc = (struct modem_ctl *)arg;
+ int phone_reset = gpio_get_value(mc->gpio_cp_reset);
+ int phone_active = gpio_get_value(mc->gpio_phone_active);
+ int phone_state = mc->phone_state;
+
+ pr_info("MIF: <%s> state = %d, phone_reset = %d, phone_active = %d\n",
+ __func__, phone_state, phone_reset, phone_active);
+
+ if (phone_reset && phone_active) {
+ phone_state = STATE_ONLINE;
+ if (mc->phone_state != STATE_BOOTING)
+ mc->iod->modem_state_changed(mc->iod, phone_state);
+ } else if (phone_reset && !phone_active) {
+ if (mc->phone_state == STATE_ONLINE) {
+ phone_state = STATE_CRASH_EXIT;
+ mc->iod->modem_state_changed(mc->iod, phone_state);
+ }
+ } else {
+ phone_state = STATE_OFFLINE;
+ if (mc->iod && mc->iod->modem_state_changed)
+ mc->iod->modem_state_changed(mc->iod, phone_state);
+ }
+
+ if (phone_active)
+ irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_LOW);
+ else
+ irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_HIGH);
+
+ pr_info("MIF: <%s> phone_state = %d\n", __func__, phone_state);
+
+ return IRQ_HANDLED;
+}
+
+static void set_idpram_boot_magic(struct dpram_link_device *dpld)
+{
+ dpld->set_access(dpld, 0);
+ dpld->set_magic(dpld, IDPRAM_NORMAL_BOOT_MAGIC);
+ dpld->set_access(dpld, 1);
+}
+
+static int qsc6085_on(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->iod);
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+
+ mif_err("+++\n");
+
+ if (!mc->gpio_cp_on || !mc->gpio_cp_reset) {
+ mif_err("no gpio_cp_on or no gpio_cp_reset\n");
+ return -ENXIO;
+ }
+
+ set_idpram_boot_magic(dpld);
+
+ mc->iod->modem_state_changed(mc->iod, STATE_BOOTING);
+
+ gpio_set_value(mc->gpio_cp_reset, 1);
+ gpio_set_value(mc->gpio_cp_on, 0);
+
+ msleep(100);
+
+ gpio_set_value(mc->gpio_cp_on, 1);
+
+ msleep(400);
+ msleep(400);
+ msleep(200);
+
+ gpio_set_value(mc->gpio_cp_on, 0);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int qsc6085_off(struct modem_ctl *mc)
+{
+ int phone_wait_cnt = 0;
+
+ pr_info("MIF: <%s+>\n", __func__);
+
+ if (!mc->gpio_cp_on || !mc->gpio_cp_reset ||
+ !mc->gpio_phone_active) {
+ pr_err("MIF: <%s> no gpio data\n", __func__);
+ return -ENXIO;
+ }
+
+ gpio_set_value(mc->gpio_cp_on, 0);
+
+ /* confirm phone off */
+ while (1) {
+ if (gpio_get_value(mc->gpio_phone_active)) {
+ pr_err("MIF: <%s> Try to Turn Phone Off by CP_RST\n",
+ __func__);
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ if (phone_wait_cnt > 10) {
+ pr_emerg("MIF: <%s> OFF Failed\n", __func__);
+ break;
+ }
+ phone_wait_cnt++;
+ mdelay(100);
+ } else {
+ pr_emerg("MIF: <%s> OFF Success\n", __func__);
+ break;
+ }
+ }
+
+ mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE);
+
+ pr_info("MIF: <%s->\n", __func__);
+
+ return 0;
+}
+
+static int qsc6085_reset(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->iod);
+ struct dpram_link_device *dpld = to_dpram_link_device(ld);
+
+ mif_err("+++\n");
+
+ set_idpram_boot_magic(dpld);
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ msleep(100);
+ gpio_set_value(mc->gpio_cp_reset, 1);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int qsc6085_modem_dump_reset(struct modem_ctl *mc)
+{
+ pr_info("MIF: <%s>\n", __func__);
+ panic("CP Crashed");
+}
+
+static void qsc6085_get_ops(struct modem_ctl *mc)
+{
+ mc->ops.modem_on = qsc6085_on;
+ mc->ops.modem_off = qsc6085_off;
+ mc->ops.modem_reset = qsc6085_reset;
+ mc->ops.modem_dump_reset = qsc6085_modem_dump_reset;
+}
+
+int qsc6085_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
+{
+ int ret = 0;
+ unsigned long flag = 0;
+
+ mc->gpio_cp_on = pdata->gpio_cp_on;
+ mc->gpio_cp_reset = pdata->gpio_cp_reset;
+ mc->gpio_pda_active = pdata->gpio_pda_active;
+ mc->gpio_phone_active = pdata->gpio_phone_active;
+ mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int;
+
+ if (!mc->gpio_cp_on || !mc->gpio_cp_reset || !mc->gpio_phone_active) {
+ mif_err("no GPIO data\n");
+ return -ENXIO;
+ }
+
+ mc->irq_phone_active = gpio_to_irq(mc->gpio_phone_active);
+ pr_err("MIF: <%s> PHONE_ACTIVE IRQ# = %d\n",
+ __func__, mc->irq_phone_active);
+
+ qsc6085_get_ops(mc);
+
+ /*register phone_active_handler*/
+ flag = IRQF_TRIGGER_HIGH;
+
+ ret = request_irq(mc->irq_phone_active,
+ phone_active_irq_handler,
+ flag, "phone_active", mc);
+ if (ret) {
+ pr_err("MIF: failed to irq_phone_active request_irq: %d\n"
+ , ret);
+ return ret;
+ }
+
+ ret = enable_irq_wake(mc->irq_phone_active);
+ if (ret) {
+ pr_err("MIF: <%s> failed to enable_irq_wake:%d\n",
+ __func__, ret);
+ free_irq(mc->irq_phone_active, mc);
+ return ret;
+ }
+ return ret;
+}
diff --git a/drivers/misc/modem_if/modem_modemctl_device_sprd8803.c b/drivers/misc/modem_if/modem_modemctl_device_sprd8803.c
index cfa2896..7a6e6fc 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_sprd8803.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_sprd8803.c
@@ -22,10 +22,13 @@
#include <linux/platform_device.h>
#include <linux/cma.h>
#include <plat/devs.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include <plat/gpio-cfg.h>
+spinlock_t irq_lock;
+int irq_lock_flag;
+
int sprd_boot_done;
extern int spi_thread_restart(void);
@@ -45,10 +48,20 @@ static int sprd8803_on(struct modem_ctl *mc)
gpio_set_value(mc->gpio_cp_ctrl2, 1);
#endif
msleep(100);
-// pr_info("[MODEM_IF] %s\n", __func__); // Kill spam
+ pr_info("[MODEM_IF] %s\n", __func__);
gpio_set_value(mc->gpio_cp_on, 1);
gpio_set_value(mc->gpio_pda_active, 1);
+ spin_lock(&irq_lock);
+ if (!irq_lock_flag) {
+ enable_irq(mc->irq_phone_active);
+ enable_irq(gpio_to_irq(mc->gpio_cp_dump_int));
+ enable_irq_wake(mc->irq_phone_active);
+ enable_irq_wake(gpio_to_irq(mc->gpio_cp_dump_int));
+ irq_lock_flag = 1;
+ }
+ spin_unlock(&irq_lock);
+
mc->phone_state = STATE_BOOTING;
return 0;
@@ -56,7 +69,7 @@ static int sprd8803_on(struct modem_ctl *mc)
static int sprd8803_off(struct modem_ctl *mc)
{
- pr_debug("[MODEM_IF] %s\n", __func__);
+ pr_info("[MODEM_IF] %s\n", __func__);
if (!mc->gpio_cp_on) {
mif_err("no gpio data\n");
@@ -64,6 +77,17 @@ static int sprd8803_off(struct modem_ctl *mc)
}
gpio_set_value(mc->gpio_cp_on, 0);
+ gpio_set_value(mc->gpio_pda_active, 0);
+
+ spin_lock(&irq_lock);
+ if (irq_lock_flag) {
+ disable_irq(mc->irq_phone_active);
+ disable_irq(gpio_to_irq(mc->gpio_cp_dump_int));
+ disable_irq_wake(mc->irq_phone_active);
+ disable_irq_wake(gpio_to_irq(mc->gpio_cp_dump_int));
+ irq_lock_flag = 0;
+ }
+ spin_unlock(&irq_lock);
mc->phone_state = STATE_OFFLINE;
@@ -72,7 +96,7 @@ static int sprd8803_off(struct modem_ctl *mc)
static int sprd8803_reset(struct modem_ctl *mc)
{
- pr_debug("[MODEM_IF] %s\n", __func__);
+ pr_info("[MODEM_IF] %s\n", __func__);
spi_thread_restart();
@@ -81,20 +105,20 @@ static int sprd8803_reset(struct modem_ctl *mc)
static int sprd8803_boot_on(struct modem_ctl *mc)
{
- pr_debug("[MODEM_IF] %s %d\n", __func__, sprd_boot_done);
- return sprd_boot_done;
+ pr_info("[MODEM_IF] %s %d\n", __func__, mc->phone_state);
+ return mc->phone_state;
}
static int sprd8803_boot_off(struct modem_ctl *mc)
{
- pr_debug("[MODEM_IF] %s\n", __func__);
+ pr_info("[MODEM_IF] %s\n", __func__);
spi_sema_init();
return 0;
}
static int sprd8803_dump_reset(struct modem_ctl *mc)
{
- pr_debug("[MODEM_IF] %s\n", __func__);
+ pr_info("[MODEM_IF] %s\n", __func__);
if (!mc->gpio_ap_cp_int2)
return -ENXIO;
@@ -115,6 +139,8 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
int phone_state = 0;
struct modem_ctl *mc = (struct modem_ctl *)_mc;
+ disable_irq_nosync(mc->irq_phone_active);
+
if (!mc->gpio_phone_active ||
!mc->gpio_cp_dump_int) {
pr_err("[MODEM_IF] no gpio data\n");
@@ -135,7 +161,7 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
else
phone_state = STATE_OFFLINE;
- if (cp_dump_value)
+ if (phone_active_value && cp_dump_value)
phone_state = STATE_CRASH_EXIT;
if (mc->iod && mc->iod->modem_state_changed)
@@ -145,6 +171,8 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
mc->bootd->modem_state_changed(mc->bootd, phone_state);
exit:
+ enable_irq(mc->irq_phone_active);
+
return IRQ_HANDLED;
}
@@ -217,5 +245,19 @@ int sprd8803_init_modemctl_device(struct modem_ctl *mc,
__func__, ret);
free_irq(irq_cp_dump_int, mc);
}
+
+ irq_lock_flag = 1;
+ spin_lock_init(&irq_lock);
+
+ spin_lock(&irq_lock);
+ if (irq_lock_flag) {
+ disable_irq(mc->irq_phone_active);
+ disable_irq(gpio_to_irq(mc->gpio_cp_dump_int));
+ disable_irq_wake(mc->irq_phone_active);
+ disable_irq_wake(gpio_to_irq(mc->gpio_cp_dump_int));
+ irq_lock_flag = 0;
+ }
+ spin_unlock(&irq_lock);
+
return ret;
}
diff --git a/drivers/misc/modem_if/modem_modemctl_device_ss222.c b/drivers/misc/modem_if/modem_modemctl_device_ss222.c
new file mode 100644
index 0000000..5dbda45
--- /dev/null
+++ b/drivers/misc/modem_if/modem_modemctl_device_ss222.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <mach/c2c.h>
+#include "modem.h"
+#include "modem_prj.h"
+#include "modem_utils.h"
+
+#define MIF_INIT_TIMEOUT (30 * HZ)
+
+static void ss222_mc_state_fsm(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->iod);
+ int cp_on = gpio_get_value(mc->gpio_cp_on);
+ int cp_reset = gpio_get_value(mc->gpio_cp_reset);
+ int cp_active = gpio_get_value(mc->gpio_phone_active);
+ int old_state = mc->phone_state;
+ int new_state = mc->phone_state;
+
+ mif_err("old_state:%s cp_on:%d cp_reset:%d cp_active:%d\n",
+ get_cp_state_str(old_state), cp_on, cp_reset, cp_active);
+
+ if (cp_active) {
+ if (!cp_on) {
+ new_state = STATE_OFFLINE;
+ ld->mode = LINK_MODE_OFFLINE;
+ } else if (old_state == STATE_ONLINE) {
+ new_state = STATE_CRASH_EXIT;
+ ld->mode = LINK_MODE_ULOAD;
+ } else {
+ mif_err("don't care!!!\n");
+ }
+ }
+
+ if (old_state != new_state) {
+ mif_err("new_state = %s\n", get_cp_state_str(new_state));
+ mc->bootd->modem_state_changed(mc->bootd, new_state);
+ mc->iod->modem_state_changed(mc->iod, new_state);
+ }
+}
+
+static irqreturn_t phone_active_handler(int irq, void *arg)
+{
+ struct modem_ctl *mc = (struct modem_ctl *)arg;
+ int cp_reset = gpio_get_value(mc->gpio_cp_reset);
+
+ if (cp_reset)
+ ss222_mc_state_fsm(mc);
+
+ return IRQ_HANDLED;
+}
+
+static inline void make_gpio_floating(int gpio, bool floating)
+{
+ if (floating)
+ gpio_direction_input(gpio);
+ else
+ gpio_direction_output(gpio, 0);
+}
+
+static int ss222_on(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->iod);
+ int cp_on = gpio_get_value(mc->gpio_cp_on);
+ int cp_off = gpio_get_value(mc->gpio_cp_off);
+ int cp_reset = gpio_get_value(mc->gpio_cp_reset);
+ int cp_active = gpio_get_value(mc->gpio_phone_active);
+ int cp_status = gpio_get_value(mc->gpio_cp_status);
+ mif_err("+++\n");
+ mif_err("cp_on:%d cp_reset:%d ps_hold:%d cp_active:%d cp_status:%d\n",
+ cp_on, cp_reset, cp_off, cp_active, cp_status);
+
+ gpio_set_value(mc->gpio_pda_active, 1);
+
+ if (!wake_lock_active(&mc->mc_wake_lock))
+ wake_lock(&mc->mc_wake_lock);
+
+ mc->phone_state = STATE_OFFLINE;
+ ld->mode = LINK_MODE_OFFLINE;
+
+ /* Make PS_HOLD floating (Hi-Z) for CP ON */
+ make_gpio_floating(mc->gpio_cp_off, true);
+
+ gpio_set_value(mc->gpio_cp_on, 0);
+ msleep(100);
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ msleep(500);
+
+ gpio_set_value(mc->gpio_cp_on, 1);
+ msleep(100);
+
+ c2c_reload();
+ gpio_set_value(mc->gpio_cp_reset, 1);
+ msleep(300);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int ss222_off(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->iod);
+ int cp_on = gpio_get_value(mc->gpio_cp_on);
+ mif_err("+++\n");
+
+ if (mc->phone_state == STATE_OFFLINE || cp_on == 0)
+ return 0;
+
+ mc->phone_state = STATE_OFFLINE;
+ ld->mode = LINK_MODE_OFFLINE;
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+
+ /* Make PS_HOLD LOW for CP OFF */
+ make_gpio_floating(mc->gpio_cp_off, false);
+ gpio_set_value(mc->gpio_cp_on, 0);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int ss222_reset(struct modem_ctl *mc)
+{
+ mif_err("+++\n");
+
+ if (ss222_off(mc))
+ return -EIO;
+
+ msleep(100);
+
+ if (ss222_on(mc))
+ return -EIO;
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int ss222_force_crash_exit(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+ mif_err("+++\n");
+
+ /* Make DUMP start */
+ ld->force_dump(ld, mc->bootd);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int ss222_dump_reset(struct modem_ctl *mc)
+{
+ unsigned int gpio_cp_reset = mc->gpio_cp_reset;
+ mif_err("+++\n");
+
+ if (!wake_lock_active(&mc->mc_wake_lock))
+ wake_lock(&mc->mc_wake_lock);
+
+ gpio_set_value(gpio_cp_reset, 0);
+ udelay(200);
+
+ c2c_reload();
+ gpio_set_value(gpio_cp_reset, 1);
+ msleep(300);
+
+ gpio_set_value(mc->gpio_ap_status, 1);
+
+ mif_err("---\n");
+ return 0;
+}
+
+static int ss222_boot_on(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+ mif_debug("+++\n");
+
+ disable_irq_nosync(mc->irq_phone_active);
+
+ gpio_set_value(mc->gpio_ap_status, 1);
+
+ ld->mode = LINK_MODE_BOOT;
+
+ mc->bootd->modem_state_changed(mc->bootd, STATE_BOOTING);
+ mc->iod->modem_state_changed(mc->iod, STATE_BOOTING);
+
+ INIT_COMPLETION(ld->init_cmpl);
+
+ mif_debug("---\n");
+ return 0;
+}
+
+static int ss222_boot_off(struct modem_ctl *mc)
+{
+ struct link_device *ld = get_current_link(mc->bootd);
+ unsigned long remain;
+ mif_debug("+++\n");
+
+ ld->mode = LINK_MODE_IPC;
+
+ remain = wait_for_completion_timeout(&ld->init_cmpl, MIF_INIT_TIMEOUT);
+ if (remain == 0) {
+ mif_err("T-I-M-E-O-U-T\n");
+ mif_err("xxx\n");
+ return -EAGAIN;
+ }
+
+ mif_debug("---\n");
+ return 0;
+}
+
+static int ss222_boot_done(struct modem_ctl *mc)
+{
+ mif_debug("+++\n");
+
+ if (wake_lock_active(&mc->mc_wake_lock))
+ wake_unlock(&mc->mc_wake_lock);
+
+ enable_irq(mc->irq_phone_active);
+
+ mif_debug("---\n");
+ return 0;
+}
+
+static void ss222_get_ops(struct modem_ctl *mc)
+{
+ mc->ops.modem_on = ss222_on;
+ mc->ops.modem_off = ss222_off;
+ mc->ops.modem_reset = ss222_reset;
+ mc->ops.modem_boot_on = ss222_boot_on;
+ mc->ops.modem_boot_off = ss222_boot_off;
+ mc->ops.modem_boot_done = ss222_boot_done;
+ mc->ops.modem_force_crash_exit = ss222_force_crash_exit;
+ mc->ops.modem_dump_reset = ss222_dump_reset;
+}
+
+int ss222_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
+{
+ int ret = 0;
+ int irq = 0;
+ unsigned long flag = 0;
+ mif_debug("+++\n");
+
+ if (!pdata->gpio_cp_on || !pdata->gpio_cp_off || !pdata->gpio_cp_reset
+ || !pdata->gpio_pda_active || !pdata->gpio_phone_active
+ || !pdata->gpio_ap_wakeup || !pdata->gpio_ap_status
+ || !pdata->gpio_cp_wakeup || !pdata->gpio_cp_status) {
+ mif_err("ERR! no GPIO data\n");
+ mif_err("xxx\n");
+ return -ENXIO;
+ }
+
+ mc->gpio_cp_on = pdata->gpio_cp_on;
+ mc->gpio_cp_off = pdata->gpio_cp_off;
+ mc->gpio_cp_reset = pdata->gpio_cp_reset;
+ mc->gpio_pda_active = pdata->gpio_pda_active;
+ mc->gpio_phone_active = pdata->gpio_phone_active;
+ mc->gpio_ap_wakeup = pdata->gpio_ap_wakeup;
+ mc->gpio_ap_status = pdata->gpio_ap_status;
+ mc->gpio_cp_wakeup = pdata->gpio_cp_wakeup;
+ mc->gpio_cp_status = pdata->gpio_cp_status;
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+
+ gpio_set_value(mc->gpio_cp_on, 0);
+
+ ss222_get_ops(mc);
+ dev_set_drvdata(mc->dev, mc);
+
+ wake_lock_init(&mc->mc_wake_lock, WAKE_LOCK_SUSPEND, "umts_wake_lock");
+
+ mc->irq_phone_active = pdata->irq_phone_active;
+ if (!mc->irq_phone_active) {
+ mif_err("ERR! no irq_phone_active\n");
+ mif_err("xxx\n");
+ return -1;
+ }
+ mif_err("PHONE_ACTIVE IRQ# = %d\n", mc->irq_phone_active);
+
+ irq = mc->irq_phone_active;
+ flag = IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND;
+ ret = request_irq(irq, phone_active_handler, flag, "umts_active", mc);
+ if (ret) {
+ mif_err("ERR! request_irq(#%d) fail (err %d)\n", irq, ret);
+ mif_err("xxx\n");
+ return ret;
+ }
+ ret = enable_irq_wake(irq);
+ if (ret)
+ mif_err("enable_irq_wake(#%d) fail (err %d)\n", irq, ret);
+
+ mif_debug("---\n");
+ return 0;
+}
+
diff --git a/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c b/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c
index d2fcf5b..9741f59 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c
@@ -22,12 +22,12 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
static int xmm6260_on(struct modem_ctl *mc)
{
- mif_debug("xmm6260_on()\n");
+ mif_info("xmm6260_on()\n");
if (!mc->gpio_cp_reset || !mc->gpio_cp_on || !mc->gpio_reset_req_n) {
mif_err("no gpio data\n");
@@ -66,7 +66,7 @@ static int xmm6260_on(struct modem_ctl *mc)
static int xmm6260_off(struct modem_ctl *mc)
{
- mif_debug("xmm6260_off()\n");
+ mif_info("xmm6260_off()\n");
if (!mc->gpio_cp_reset || !mc->gpio_cp_on) {
mif_err("no gpio data\n");
@@ -85,7 +85,7 @@ static int xmm6260_off(struct modem_ctl *mc)
static int xmm6260_reset(struct modem_ctl *mc)
{
- mif_debug("xmm6260_reset()\n");
+ mif_info("xmm6260_reset()\n");
if (!mc->gpio_cp_reset || !mc->gpio_reset_req_n)
return -ENXIO;
@@ -122,7 +122,7 @@ static int xmm6260_reset(struct modem_ctl *mc)
static int xmm6260_boot_on(struct modem_ctl *mc)
{
- mif_debug("xmm6260_boot_on()\n");
+ mif_info("xmm6260_boot_on()\n");
if (!mc->gpio_flm_uart_sel) {
mif_err("no gpio data\n");
@@ -136,7 +136,7 @@ static int xmm6260_boot_on(struct modem_ctl *mc)
static int xmm6260_boot_off(struct modem_ctl *mc)
{
- mif_debug("xmm6260_boot_off()\n");
+ mif_info("xmm6260_boot_off()\n");
if (!mc->gpio_flm_uart_sel) {
mif_err("no gpio data\n");
diff --git a/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c b/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
index 4d0b69c..5473aad 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
@@ -24,9 +24,11 @@
#include <linux/platform_device.h>
#include <linux/cma.h>
#include <plat/devs.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
-
+#ifdef CONFIG_FAST_BOOT
+#include <linux/fake_shut_down.h>
+#endif
static int xmm6262_on(struct modem_ctl *mc)
{
mif_info("\n");
@@ -59,11 +61,13 @@ static int xmm6262_on(struct modem_ctl *mc)
udelay(60);
gpio_set_value(mc->gpio_cp_on, 0);
msleep(20);
+
+ mc->phone_state = STATE_BOOTING;
+
if (mc->gpio_revers_bias_restore)
mc->gpio_revers_bias_restore();
gpio_set_value(mc->gpio_pda_active, 1);
- mc->phone_state = STATE_BOOTING;
return 0;
}
@@ -120,6 +124,20 @@ static int xmm6262_reset(struct modem_ctl *mc)
return 0;
}
+static int xmm6262_force_crash_exit(struct modem_ctl *mc)
+{
+ mif_info("\n");
+
+ if (!mc->gpio_ap_dump_int)
+ return -ENXIO;
+
+ gpio_set_value(mc->gpio_ap_dump_int, 1);
+ mif_info("set ap_dump_int(%d) to high=%d\n",
+ mc->gpio_ap_dump_int, gpio_get_value(mc->gpio_ap_dump_int));
+ return 0;
+}
+
+
static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
{
int phone_reset = 0;
@@ -172,14 +190,72 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
return IRQ_HANDLED;
}
+#ifdef CONFIG_FAST_BOOT
+#include <linux/reboot.h>
+
+static void mif_sim_detect_complete(struct modem_ctl *mc)
+{
+ if (mc->sim_shutdown_req) {
+ mif_info("fake shutdown sim changed shutdown\n");
+ kernel_power_off();
+ /*kernel_restart(NULL);*/
+ mc->sim_shutdown_req = false;
+ }
+}
+
+static int mif_init_sim_shutdown(struct modem_ctl *mc)
+{
+ mc->sim_shutdown_req = false;
+ mc->modem_complete = mif_sim_detect_complete;
+
+ return 0;
+}
+
+static void mif_check_fake_shutdown(struct modem_ctl *mc, bool online)
+{
+ if (fake_shut_down && mc->sim_state.online != online)
+ mc->sim_shutdown_req = true;
+}
+
+#else
+static inline int mif_init_sim_shutdown(struct modem_ctl *mc) { return 0; }
+#define mif_check_fake_shutdown(a, b) do {} while (0)
+#endif
+
+
+#define SIM_DETECT_DEBUG
static irqreturn_t sim_detect_irq_handler(int irq, void *_mc)
{
struct modem_ctl *mc = (struct modem_ctl *)_mc;
+#ifdef SIM_DETECT_DEBUG
+ int val = gpio_get_value(mc->gpio_sim_detect);
+ static int unchange;
+ static int prev_val;
+
+ if (mc->phone_state == STATE_BOOTING) {
+ mif_info("BOOTING, reset unchange\n");
+ unchange = 0;
+ }
- if (mc->iod && mc->iod->sim_state_changed)
+ if (prev_val == val) {
+ if (unchange++ > 50) {
+ mif_err("Abnormal SIM detect GPIO irqs");
+ disable_irq_nosync(mc->gpio_sim_detect);
+ panic("SIM detect IRQ Error");
+ }
+ } else {
+ unchange = 0;
+ }
+ prev_val = val;
+#endif
+ if (mc->iod && mc->iod->sim_state_changed) {
+ mif_check_fake_shutdown(mc,
+ gpio_get_value(mc->gpio_sim_detect) == mc->sim_polarity
+ );
mc->iod->sim_state_changed(mc->iod,
gpio_get_value(mc->gpio_sim_detect) == mc->sim_polarity
);
+ }
return IRQ_HANDLED;
}
@@ -189,6 +265,7 @@ static void xmm6262_get_ops(struct modem_ctl *mc)
mc->ops.modem_on = xmm6262_on;
mc->ops.modem_off = xmm6262_off;
mc->ops.modem_reset = xmm6262_reset;
+ mc->ops.modem_force_crash_exit = xmm6262_force_crash_exit;
}
int xmm6262_init_modemctl_device(struct modem_ctl *mc,
@@ -218,6 +295,7 @@ int xmm6262_init_modemctl_device(struct modem_ctl *mc,
mc->gpio_cp_ctrl2 = pdata->gpio_cp_ctrl2;
#endif
+
pdev = to_platform_device(mc->dev);
mc->irq_phone_active = gpio_to_irq(mc->gpio_phone_active);
@@ -261,6 +339,12 @@ int xmm6262_init_modemctl_device(struct modem_ctl *mc,
/* initialize sim_state => insert: gpio=0, remove: gpio=1 */
mc->sim_state.online =
gpio_get_value(mc->gpio_sim_detect) == mc->sim_polarity;
+
+ ret = mif_init_sim_shutdown(mc);
+ if (ret) {
+ mif_err("failed to sim fake shutdown init: %d\n", ret);
+ goto err_sim_detect_set_wake_irq;
+ }
}
return ret;
diff --git a/drivers/misc/modem_if/modem_net_flowcontrol_device.c b/drivers/misc/modem_if/modem_net_flowcontrol_device.c
index b3f055d..3aa340f 100644
--- a/drivers/misc/modem_if/modem_net_flowcontrol_device.c
+++ b/drivers/misc/modem_if/modem_net_flowcontrol_device.c
@@ -22,7 +22,7 @@
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
diff --git a/drivers/misc/modem_if/modem_prj.h b/drivers/misc/modem_if/modem_prj.h
index f85596f..ccff272 100644
--- a/drivers/misc/modem_if/modem_prj.h
+++ b/drivers/misc/modem_if/modem_prj.h
@@ -1,5 +1,4 @@
/*
- * Copyright (C) 2010 Google, Inc.
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -19,12 +18,18 @@
#include <linux/wait.h>
#include <linux/miscdevice.h>
#include <linux/skbuff.h>
+#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/wakelock.h>
#include <linux/rbtree.h>
#include <linux/spinlock.h>
#include <linux/cdev.h>
#include <linux/types.h>
+#include "modem.h"
+
+#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP
+#define DEBUG_MODEM_IF
+#endif
#define MAX_CPINFO_SIZE 512
@@ -33,7 +38,10 @@
#define MAX_FMT_DEVS 10
#define MAX_RAW_DEVS 32
#define MAX_RFS_DEVS 10
-#define MAX_NUM_IO_DEV (MAX_FMT_DEVS + MAX_RAW_DEVS + MAX_RFS_DEVS)
+#define MAX_BOOT_DEVS 10
+#define MAX_DUMP_DEVS 10
+
+#define MAX_IOD_RXQ_LEN 2048
#define IOCTL_MODEM_ON _IO('o', 0x19)
#define IOCTL_MODEM_OFF _IO('o', 0x20)
@@ -62,22 +70,40 @@
#define IOCTL_MODEM_SWITCH_MODEM _IO('o', 0x37)
#endif
-#define IOCTL_DPRAM_SEND_BOOT _IO('o', 0x40)
-#define IOCTL_DPRAM_INIT_STATUS _IO('o', 0x43)
-
-/* ioctl command definitions. */
-#define IOCTL_DPRAM_PHONE_POWON _IO('o', 0xd0)
-#define IOCTL_DPRAM_PHONEIMG_LOAD _IO('o', 0xd1)
-#define IOCTL_DPRAM_NVDATA_LOAD _IO('o', 0xd2)
-#define IOCTL_DPRAM_PHONE_BOOTSTART _IO('o', 0xd3)
+#define IOCTL_MODEM_RAMDUMP_START _IO('o', 0xCE)
+#define IOCTL_MODEM_RAMDUMP_STOP _IO('o', 0xCF)
-#define IOCTL_DPRAM_PHONE_UPLOAD_STEP1 _IO('o', 0xde)
-#define IOCTL_DPRAM_PHONE_UPLOAD_STEP2 _IO('o', 0xdf)
+#define IOCTL_MODEM_XMIT_BOOT _IO('o', 0x40)
+#define IOCTL_DPRAM_INIT_STATUS _IO('o', 0x43)
/* ioctl command for IPC Logger */
#define IOCTL_MIF_LOG_DUMP _IO('o', 0x51)
#define IOCTL_MIF_DPRAM_DUMP _IO('o', 0x52)
+/* ioctl command definitions. */
+#define IOCTL_DPRAM_PHONE_POWON _IO('o', 0xD0)
+#define IOCTL_DPRAM_PHONEIMG_LOAD _IO('o', 0xD1)
+#define IOCTL_DPRAM_NVDATA_LOAD _IO('o', 0xD2)
+#define IOCTL_DPRAM_PHONE_BOOTSTART _IO('o', 0xD3)
+
+#define IOCTL_DPRAM_PHONE_UPLOAD_STEP1 _IO('o', 0xDE)
+#define IOCTL_DPRAM_PHONE_UPLOAD_STEP2 _IO('o', 0xDF)
+
+#define CPBOOT_DIR_MASK 0xF000
+#define CPBOOT_STAGE_MASK 0x0F00
+#define CPBOOT_CMD_MASK 0x000F
+#define CPBOOT_REQ_RESP_MASK 0x0FFF
+
+#define CPBOOT_DIR_AP2CP 0x9000
+#define CPBOOT_DIR_CP2AP 0xA000
+
+#define CPBOOT_STAGE_SHIFT 8
+
+#define CPBOOT_STAGE_START 0x0000
+#define CPBOOT_CRC_SEND 0x000C
+#define CPBOOT_STAGE_DONE 0x000D
+#define CPBOOT_STAGE_FAIL 0x000F
+
/* modem status */
#define MODEM_OFF 0
#define MODEM_CRASHED 1
@@ -93,83 +119,50 @@
#define PSD_DATA_CHID_BEGIN 0x2A
#define PSD_DATA_CHID_END 0x38
-#define PS_DATA_CH_0 10
-#define PS_DATA_CH_LAST 24
+#define PS_DATA_CH_0 10
+#define PS_DATA_CH_LAST 24
+#define RMNET0_CH_ID PS_DATA_CH_0
#define IP6VERSION 6
#define SOURCE_MAC_ADDR {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}
-/* loopback: CP -> AP -> CP */
-#define CP2AP_LOOPBACK_CHANNEL 30
-
-/* ip loopback */
-#define RMNET0_CH_ID 10
+/* IP loopback */
+#define DATA_DRAIN_CHANNEL 30 /* Drain channel to drop RX packets */
#define DATA_LOOPBACK_CHANNEL 31
/* Debugging features */
-#define MAX_MIF_LOG_PATH_LEN 128
-#define MAX_MIF_LOG_FILE_SIZE 0x800000 /* 8 MB */
-
-#define MAX_MIF_EVT_BUFF_SIZE 256
-#define MAX_MIF_TIME_LEN 32
-#define MAX_MIF_NAME_LEN 16
-#define MAX_MIF_STR_LEN 127
-#define MAX_MIF_LOG_LEN 128
-
-enum mif_event_id {
- MIF_IRQ_EVT = 0,
- MIF_LNK_RX_EVT,
- MIF_MUX_RX_EVT,
- MIF_IOD_RX_EVT,
- MIF_IOD_TX_EVT,
- MIF_MUX_TX_EVT,
- MIF_LNK_TX_EVT,
- MAX_MIF_EVT
-};
-
-struct dpram_queue_status {
- unsigned in;
- unsigned out;
-};
-
-struct dpram_queue_status_pair {
- struct dpram_queue_status txq;
- struct dpram_queue_status rxq;
-};
-
-struct dpram_irq_buff {
- unsigned magic;
- unsigned access;
- struct dpram_queue_status_pair qsp[MAX_IPC_DEV];
- unsigned int2ap;
- unsigned int2cp;
-};
-
-/* Not use */
-struct mif_event_buff {
- char time[MAX_MIF_TIME_LEN];
-
- struct timeval tv;
- enum mif_event_id evt;
-
- char mc[MAX_MIF_NAME_LEN];
-
- char iod[MAX_MIF_NAME_LEN];
-
- char ld[MAX_MIF_NAME_LEN];
- enum modem_link link_type;
-
- unsigned rcvd;
- unsigned len;
- union {
- u8 data[MAX_MIF_LOG_LEN];
- struct dpram_irq_buff dpram_irqb;
- };
+#define MIF_LOG_DIR "/sdcard/log"
+#define MIF_MAX_PATH_LEN 256
+#define MIF_MAX_NAME_LEN 64
+#define MIF_MAX_STR_LEN 32
+
+#define CP_CRASH_TAG "CP Crash "
+
+static const char const *dev_format_str[] = {
+ [IPC_FMT] = "FMT",
+ [IPC_RAW] = "RAW",
+ [IPC_RFS] = "RFS",
+ [IPC_MULTI_RAW] = "MULTI_RAW",
+ [IPC_CMD] = "CMD",
+ [IPC_BOOT] = "BOOT",
+ [IPC_RAMDUMP] = "RAMDUMP",
+ [IPC_DEBUG] = "DEBUG",
};
-#define MIF_LOG_DIR "/sdcard"
-#define MIF_LOG_LV_FILE "/data/.mif_log_level"
+/**
+ * get_dev_name
+ * @dev: IPC device (enum dev_format)
+ *
+ * Returns IPC device name as a string.
+ */
+static const inline char *get_dev_name(unsigned int dev)
+{
+ if (unlikely(dev >= MAX_DEV_FORMAT))
+ return "INVALID";
+ else
+ return dev_format_str[dev];
+}
/* Does modem ctl structure will use state ? or status defined below ?*/
enum modem_state {
@@ -187,6 +180,26 @@ enum modem_state {
#endif
};
+static const char const *cp_state_str[] = {
+ [STATE_OFFLINE] = "OFFLINE",
+ [STATE_CRASH_RESET] = "CRASH_RESET",
+ [STATE_CRASH_EXIT] = "CRASH_EXIT",
+ [STATE_BOOTING] = "BOOTING",
+ [STATE_ONLINE] = "ONLINE",
+ [STATE_NV_REBUILDING] = "NV_REBUILDING",
+ [STATE_LOADER_DONE] = "LOADER_DONE",
+ [STATE_SIM_ATTACH] = "SIM_ATTACH",
+ [STATE_SIM_DETACH] = "SIM_DETACH",
+#if defined(CONFIG_SEC_DUAL_MODEM_MODE)
+ [STATE_MODEM_SWITCH] = "MODEM_SWITCH",
+#endif
+};
+
+static const inline char *get_cp_state_str(int state)
+{
+ return cp_state_str[state];
+}
+
enum com_state {
COM_NONE,
COM_ONLINE,
@@ -208,6 +221,17 @@ struct sim_state {
bool changed; /* online is changed? */
};
+enum cp_boot_mode {
+ CP_BOOT_MODE_NORMAL,
+ CP_BOOT_MODE_DUMP,
+ MAX_CP_BOOT_MODE
+};
+
+struct modem_firmware {
+ char *binary;
+ u32 size;
+};
+
#define HDLC_START 0x7F
#define HDLC_END 0x7E
#define SIZE_OF_HDLC_START 1
@@ -216,8 +240,8 @@ struct sim_state {
struct header_data {
char hdr[HDLC_HEADER_MAX_SIZE];
- unsigned len;
- unsigned frag_len;
+ u32 len;
+ u32 frag_len;
char start; /*hdlc start header 0x7F*/
};
@@ -255,10 +279,14 @@ struct sipc_fmt_hdr {
#define SIPC5_EXT_FIELD_EXIST 0b00000010
#define SIPC5_CTL_FIELD_EXIST 0b00000001
-#define SIPC5_MAX_HEADER_SIZE 6
-#define SIPC5_HEADER_SIZE_WITH_EXT_LEN 6
+#define SIPC5_EXT_LENGTH_MASK SIPC5_EXT_FIELD_EXIST
+#define SIPC5_CTL_FIELD_MASK (SIPC5_EXT_FIELD_EXIST | SIPC5_CTL_FIELD_EXIST)
+
+#define SIPC5_MIN_HEADER_SIZE 4
#define SIPC5_HEADER_SIZE_WITH_CTL_FLD 5
-#define SIPC5_MIN_HEADER_SIZE 4
+#define SIPC5_HEADER_SIZE_WITH_EXT_LEN 6
+#define SIPC5_MAX_HEADER_SIZE SIPC5_HEADER_SIZE_WITH_EXT_LEN
+
#define SIPC5_CONFIG_SIZE 1
#define SIPC5_CH_ID_SIZE 1
@@ -267,13 +295,18 @@ struct sipc_fmt_hdr {
#define SIPC5_LEN_OFFSET 2
#define SIPC5_CTL_OFFSET 4
-#define SIPC5_CH_ID_RAW_0 0
#define SIPC5_CH_ID_PDP_0 10
#define SIPC5_CH_ID_PDP_LAST 24
+#define SIPC5_CH_ID_BOOT0 215
+#define SIPC5_CH_ID_DUMP0 225
#define SIPC5_CH_ID_FMT_0 235
#define SIPC5_CH_ID_RFS_0 245
#define SIPC5_CH_ID_MAX 255
+#define SIPC5_CH_ID_FLOW_CTRL 255
+#define FLOW_CTRL_SUSPEND ((u8)(0xCA))
+#define FLOW_CTRL_RESUME ((u8)(0xCB))
+
/* If iod->id is 0, do not need to store to `iodevs_tree_fmt' in SIPC4 */
#define sipc4_is_not_reserved_channel(ch) ((ch) != 0)
@@ -295,20 +328,6 @@ struct sipc5_link_hdr {
} __packed;
struct sipc5_frame_data {
- /* Config octet */
- u8 config;
-
- /* Channel ID */
- u8 ch_id;
-
- /* Control for multiple FMT frame */
- u8 control;
-
- /* Frame configuration set by header analysis */
- bool padding;
- bool ctl_fld;
- bool ext_len;
-
/* Frame length calculated from the length fields */
unsigned len;
@@ -318,11 +337,17 @@ struct sipc5_frame_data {
/* The length of received header */
unsigned hdr_rcvd;
- /* The length of data payload */
- unsigned data_len;
+ /* The length of link layer payload */
+ unsigned pay_len;
/* The length of received data */
- unsigned data_rcvd;
+ unsigned pay_rcvd;
+
+ /* The length of link layer padding */
+ unsigned pad_len;
+
+ /* The length of received padding */
+ unsigned pad_rcvd;
/* Header buffer */
u8 hdr[SIPC5_MAX_HEADER_SIZE];
@@ -349,8 +374,9 @@ struct skbuff_private {
struct io_device *iod;
struct link_device *ld;
struct io_device *real_iod; /* for rx multipdp */
- u8 ch_id;
- u8 control;
+
+ /* for indicating that thers is only one IPC frame in an skb */
+ bool single_frame;
} __packed;
static inline struct skbuff_private *skbpriv(struct sk_buff *skb)
@@ -359,6 +385,35 @@ static inline struct skbuff_private *skbpriv(struct sk_buff *skb)
return (struct skbuff_private *)&skb->cb;
}
+enum iod_rx_state {
+ IOD_RX_ON_STANDBY = 0,
+ IOD_RX_HEADER,
+ IOD_RX_PAYLOAD,
+ IOD_RX_PADDING,
+ MAX_IOD_RX_STATE
+};
+
+static const char const *rx_state_str[] = {
+ [IOD_RX_ON_STANDBY] = "RX_ON_STANDBY",
+ [IOD_RX_HEADER] = "RX_HEADER",
+ [IOD_RX_PAYLOAD] = "RX_PAYLOAD",
+ [IOD_RX_PADDING] = "RX_PADDING",
+};
+
+/**
+ * get_dev_name
+ * @dev: IPC device (enum dev_format)
+ *
+ * Returns IPC device name as a string.
+ */
+static const inline char *get_rx_state_str(unsigned int state)
+{
+ if (unlikely(state >= MAX_IOD_RX_STATE))
+ return "INVALID_STATE";
+ else
+ return rx_state_str[state];
+}
+
struct io_device {
/* rb_tree node for an io device */
struct rb_node node_chan;
@@ -367,6 +422,7 @@ struct io_device {
/* Name of the IO device */
char *name;
+ /* Reference count */
atomic_t opened;
/* Wait queue for the IO device */
@@ -383,7 +439,11 @@ struct io_device {
enum modem_io io_typ;
enum modem_network net_typ;
- bool use_handover; /* handover 2+ link devices */
+ /* The name of the application that will use this IO device */
+ char *app;
+
+ /* Whether or not handover among 2+ link devices */
+ bool use_handover;
/* SIPC version */
enum sipc_ver ipc_version;
@@ -391,6 +451,10 @@ struct io_device {
/* Rx queue of sk_buff */
struct sk_buff_head sk_rx_q;
+ /* RX state used in RX FSM */
+ enum iod_rx_state curr_rx_state;
+ enum iod_rx_state next_rx_state;
+
/*
** work for each io device, when delayed work needed
** use this for private io device rx action
@@ -447,6 +511,9 @@ struct link_device {
/* SIPC version */
enum sipc_ver ipc_version;
+ /* Maximum IPC device = the last IPC device (e.g. IPC_RFS) + 1 */
+ int max_ipc_dev;
+
/* Modem data */
struct modem_data *mdm_data;
@@ -459,6 +526,12 @@ struct link_device {
/* Operation mode of the link device */
enum link_mode mode;
+ /* completion for waiting for link initialization */
+ struct completion init_cmpl;
+
+ /* completion for waiting for PIF initialization in a CP */
+ struct completion pif_cmpl;
+
struct io_device *fmt_iods[4];
/* TX queue of socket buffers */
@@ -468,13 +541,30 @@ struct link_device {
struct sk_buff_head *skb_txq[MAX_IPC_DEV];
+ /* RX queue of socket buffers */
+ struct sk_buff_head sk_fmt_rx_q;
+ struct sk_buff_head sk_raw_rx_q;
+ struct sk_buff_head sk_rfs_rx_q;
+
+ struct sk_buff_head *skb_rxq[MAX_IPC_DEV];
+
bool raw_tx_suspended; /* for misc dev */
struct completion raw_tx_resumed_by_cp;
+ /**
+ * This flag is for TX flow control on network interface.
+ * This must be set and clear only by a flow control command from CP.
+ */
+ bool suspend_netif_tx;
+
struct workqueue_struct *tx_wq;
struct work_struct tx_work;
struct delayed_work tx_delayed_work;
- struct delayed_work tx_dwork;
+
+ struct delayed_work *tx_dwork[MAX_IPC_DEV];
+ struct delayed_work fmt_tx_dwork;
+ struct delayed_work raw_tx_dwork;
+ struct delayed_work rfs_tx_dwork;
struct workqueue_struct *rx_wq;
struct work_struct rx_work;
@@ -495,20 +585,26 @@ struct link_device {
int (*send)(struct link_device *ld, struct io_device *iod,
struct sk_buff *skb);
- int (*udl_start)(struct link_device *ld, struct io_device *iod);
-
- int (*force_dump)(struct link_device *ld, struct io_device *iod);
-
- int (*dump_start)(struct link_device *ld, struct io_device *iod);
+ /* method for CP booting */
+ int (*xmit_boot)(struct link_device *ld, struct io_device *iod,
+ unsigned long arg);
- int (*modem_update)(struct link_device *ld, struct io_device *iod,
+ /* methods for CP firmware upgrade */
+ int (*dload_start)(struct link_device *ld, struct io_device *iod);
+ int (*firm_update)(struct link_device *ld, struct io_device *iod,
unsigned long arg);
+ /* methods for CP crash dump */
+ int (*force_dump)(struct link_device *ld, struct io_device *iod);
+ int (*dump_start)(struct link_device *ld, struct io_device *iod);
int (*dump_update)(struct link_device *ld, struct io_device *iod,
unsigned long arg);
+ int (*dump_finish)(struct link_device *ld, struct io_device *iod,
+ unsigned long arg);
+ /* IOCTL extension */
int (*ioctl)(struct link_device *ld, struct io_device *iod,
- unsigned cmd, unsigned long _arg);
+ unsigned cmd, unsigned long arg);
};
/** rx_alloc_skb - allocate an skbuff and set skb's iod, ld
@@ -567,6 +663,9 @@ struct modem_shared {
struct mif_storage storage;
spinlock_t lock;
+ /* CP crash information */
+ char cp_crash_info[530];
+
/* loopbacked IP address
* default is 0.0.0.0 (disabled)
* after you setted this, you can use IP packet loopback using this IP.
@@ -586,35 +685,52 @@ struct modem_ctl {
struct sim_state sim_state;
unsigned gpio_cp_on;
+ unsigned gpio_cp_off;
unsigned gpio_reset_req_n;
unsigned gpio_cp_reset;
+
+ /* for broadcasting AP's PM state (active or sleep) */
unsigned gpio_pda_active;
+
+ /* for checking aliveness of CP */
unsigned gpio_phone_active;
+ int irq_phone_active;
+
+ /* for AP-CP power management (PM) handshaking */
+ unsigned gpio_ap_wakeup;
+ int irq_ap_wakeup;
+ unsigned gpio_ap_status;
+ unsigned gpio_cp_wakeup;
+ unsigned gpio_cp_status;
+ int irq_cp_status;
+
+ /* for USB/HSIC PM */
+ unsigned gpio_host_wakeup;
+ int irq_host_wakeup;
+ unsigned gpio_host_active;
+ unsigned gpio_slave_wakeup;
+
+#ifdef CONFIG_EXYNOS4_CPUFREQ
+ /* cpu/bus frequency lock */
+ unsigned gpio_cpufreq_lock;
+ struct delayed_work work_cpu_lock;
+ struct delayed_work work_cpu_unlock;
+#endif
+
unsigned gpio_cp_dump_int;
unsigned gpio_ap_dump_int;
unsigned gpio_flm_uart_sel;
+ unsigned gpio_cp_warm_reset;
#if defined(CONFIG_MACH_M0_CTC)
unsigned gpio_flm_uart_sel_rev06;
#endif
- unsigned gpio_cp_warm_reset;
- unsigned gpio_cp_off;
- unsigned gpio_sim_detect;
- unsigned gpio_dynamic_switching;
- int irq_phone_active;
+ unsigned gpio_sim_detect;
int irq_sim_detect;
-#ifdef CONFIG_LTE_MODEM_CMC221
- const struct attribute_group *group;
- unsigned gpio_slave_wakeup;
- unsigned gpio_host_wakeup;
- unsigned gpio_host_active;
- int irq_host_wakeup;
-
- struct delayed_work dwork;
-#endif /*CONFIG_LTE_MODEM_CMC221*/
-
- struct work_struct work;
+#ifdef CONFIG_LINK_DEVICE_PLD
+ unsigned gpio_fpga_cs_n;
+#endif
#if defined(CONFIG_MACH_U1_KOR_LGT)
unsigned gpio_cp_reset_msm;
@@ -635,9 +751,13 @@ struct modem_ctl {
unsigned gpio_cp_ctrl2;
#endif
-#ifdef CONFIG_LINK_DEVICE_PLD
- unsigned gpio_fpga_cs_n;
-#endif
+ /* Switch with 2 links in a modem */
+ unsigned gpio_link_switch;
+
+ const struct attribute_group *group;
+
+ struct delayed_work dwork;
+ struct work_struct work;
struct modemctl_ops ops;
struct io_device *iod;
@@ -651,119 +771,45 @@ struct modem_ctl {
bool need_switch_to_usb;
bool sim_polarity;
+
+ bool sim_shutdown_req;
+ void (*modem_complete)(struct modem_ctl *mc);
};
int sipc4_init_io_device(struct io_device *iod);
int sipc5_init_io_device(struct io_device *iod);
-/**
- * sipc5_start_valid
- * @cfg: configuration field of an SIPC5 link frame
- *
- * Returns TRUE if the start (configuration field) of an SIPC5 link frame
- * is valid or returns FALSE if it is not valid.
- *
- */
-static inline int sipc5_start_valid(u8 cfg)
-{
- return (cfg & SIPC5_START_MASK) == SIPC5_START_MASK;
-}
-
-/**
- * sipc5_get_hdr_len
- * @cfg: configuration field of an SIPC5 link frame
- *
- * Returns the length of SIPC5 link layer header in an SIPC5 link frame
- *
- */
-static inline unsigned sipc5_get_hdr_len(u8 cfg)
-{
- if (cfg & SIPC5_EXT_FIELD_EXIST) {
- if (cfg & SIPC5_CTL_FIELD_EXIST)
- return SIPC5_HEADER_SIZE_WITH_CTL_FLD;
- else
- return SIPC5_HEADER_SIZE_WITH_EXT_LEN;
- } else {
- return SIPC5_MIN_HEADER_SIZE;
- }
-}
-
-/**
- * sipc5_get_ch_id
- * @frm: pointer to an SIPC5 frame
- *
- * Returns the channel ID in an SIPC5 link frame
- *
- */
-static inline u8 sipc5_get_ch_id(u8 *frm)
-{
- return *(frm + SIPC5_CH_ID_OFFSET);
-}
-
-/**
- * sipc5_get_frame_sz16
- * @frm: pointer to an SIPC5 link frame
- *
- * Returns the length of an SIPC5 link frame without the extended length field
- *
- */
-static inline unsigned sipc5_get_frame_sz16(u8 *frm)
-{
- return *((u16 *)(frm + SIPC5_LEN_OFFSET));
-}
-
-/**
- * sipc5_get_frame_sz32
- * @frm: pointer to an SIPC5 frame
- *
- * Returns the length of an SIPC5 link frame with the extended length field
- *
- */
-static inline unsigned sipc5_get_frame_sz32(u8 *frm)
-{
- return *((u32 *)(frm + SIPC5_LEN_OFFSET));
-}
-
-/**
- * sipc5_calc_padding_size
- * @len: length of an SIPC5 link frame
- *
- * Returns the padding size for an SIPC5 link frame
- *
- */
-static inline unsigned sipc5_calc_padding_size(unsigned len)
-{
- unsigned residue = len & 0x3;
- return residue ? (4 - residue) : 0;
-}
-
-extern void set_sromc_access(bool access);
+bool sipc5_start_valid(u8 *frm);
+bool sipc5_padding_exist(u8 *frm);
+bool sipc5_multi_frame(u8 *frm);
+bool sipc5_ext_len(u8 *frm);
+int sipc5_get_hdr_len(u8 *frm);
+u8 sipc5_get_ch_id(u8 *frm);
+u8 sipc5_get_ctrl_field(u8 *frm);
+int sipc5_get_frame_len(u8 *frm);
+int sipc5_calc_padding_size(int len);
+int sipc5_get_total_len(u8 *frm);
+
+u8 sipc5_build_config(struct io_device *iod, struct link_device *ld, u32 count);
+void sipc5_build_header(struct io_device *iod, struct link_device *ld,
+ u8 *buff, u8 cfg, u8 ctrl, u32 count);
#if defined(CONFIG_TDSCDMA_MODEM_SPRD8803) && defined(CONFIG_LINK_DEVICE_SPI)
extern int spi_sema_init(void);
extern int sprd_boot_done;
-struct ipc_spi {
- struct class *class;
- struct device *dev;
- struct cdev cdev;
- dev_t devid;
-
- wait_queue_head_t waitq;
- struct fasync_struct *async_queue;
- u32 mailbox;
-
- unsigned long base;
- unsigned long size;
- void __iomem *mmio;
+#endif
- int irq;
+#define STD_UDL_STEP_MASK 0x0000000F
+#define STD_UDL_SEND 0x1
+#define STD_UDL_CRC 0xC
- struct completion comp;
- atomic_t ref_sem;
- unsigned long flags;
+struct std_dload_info {
+ u32 size;
+ u32 mtu;
+ u32 num_frames;
+} __packed;
- const struct attribute_group *group;
-};
-#endif
+u32 std_udl_get_cmd(u8 *frm);
+bool std_udl_with_payload(u32 cmd);
#endif
diff --git a/drivers/misc/modem_if/modem_sim_slot_switch.c b/drivers/misc/modem_if/modem_sim_slot_switch.c
index c8e83ed..366d0fa 100644
--- a/drivers/misc/modem_if/modem_sim_slot_switch.c
+++ b/drivers/misc/modem_if/modem_sim_slot_switch.c
@@ -17,7 +17,7 @@ static ssize_t get_slot_switch(struct device *dev, struct device_attribute *attr
//return '0' slot path is '||', return '1' slot path is 'X'
value = gpio_get_value(GPIO_UIM_SIM_SEL);
#if defined(CONFIG_MACH_T0_CHN_CTC)
- if (system_rev < 7)
+ if (system_rev <= 7)
value = (~value & 0x1);
#endif
printk("Current Slot is %x\n", value);
@@ -34,7 +34,7 @@ static ssize_t set_slot_switch(struct device *dev, struct device_attribute *attr
switch(value) {
case 0:
#if defined(CONFIG_MACH_T0_CHN_CTC)
- if (system_rev < 7)
+ if (system_rev <= 7)
gpio_set_value(GPIO_UIM_SIM_SEL, 1);
else
#endif
@@ -43,7 +43,7 @@ static ssize_t set_slot_switch(struct device *dev, struct device_attribute *attr
break;
case 1:
#if defined(CONFIG_MACH_T0_CHN_CTC)
- if (system_rev < 7)
+ if (system_rev <= 7)
gpio_set_value(GPIO_UIM_SIM_SEL, 0);
else
#endif
@@ -57,7 +57,8 @@ static ssize_t set_slot_switch(struct device *dev, struct device_attribute *attr
return size;
}
-static DEVICE_ATTR(slot_sel, S_IRUGO |S_IWUGO | S_IRUSR | S_IWUSR, get_slot_switch, set_slot_switch);
+static DEVICE_ATTR(slot_sel, S_IRUGO | S_IWUSR | S_IWGRP,
+ get_slot_switch, set_slot_switch);
static int __init slot_switch_manager_init(void)
{
@@ -75,7 +76,7 @@ static int __init slot_switch_manager_init(void)
gpio_direction_output(GPIO_UIM_SIM_SEL, 1);
s3c_gpio_setpull(GPIO_UIM_SIM_SEL, S3C_GPIO_PULL_NONE);
#if defined(CONFIG_MACH_T0_CHN_CTC)
- if (system_rev < 7)
+ if (system_rev <= 7)
gpio_set_value(GPIO_UIM_SIM_SEL, 1);
else
#endif
diff --git a/drivers/misc/modem_if/modem_utils.c b/drivers/misc/modem_if/modem_utils.c
index d62aaa6..e829324 100644
--- a/drivers/misc/modem_if/modem_utils.c
+++ b/drivers/misc/modem_if/modem_utils.c
@@ -12,18 +12,35 @@
*
*/
-#include <linux/netdevice.h>
-#include <linux/platform_data/modem.h>
+#include <linux/init.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
+#include <net/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/rtc.h>
#include <linux/time.h>
-#include <net/ip.h>
-
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/wakelock.h>
+
+#include "modem.h"
#include "modem_prj.h"
+#include "modem_variation.h"
#include "modem_utils.h"
#define CMD_SUSPEND ((unsigned short)(0x00CA))
@@ -35,42 +52,29 @@
"mif: ------------------------------------------------------------"
#define LINE_BUFF_SIZE 80
-#ifdef CONFIG_LINK_DEVICE_DPRAM
-#include "modem_link_device_dpram.h"
-int mif_dump_dpram(struct io_device *iod)
-{
- struct link_device *ld = get_current_link(iod);
- struct dpram_link_device *dpld = to_dpram_link_device(ld);
- u32 size = dpld->dp_size;
- unsigned long read_len = 0;
- struct sk_buff *skb;
- char *buff;
+static const char *hex = "0123456789abcdef";
- buff = kzalloc(size, GFP_ATOMIC);
- if (!buff) {
- pr_err("[MIF] <%s> alloc dpram buff failed\n", __func__);
- return -ENOMEM;
- } else {
- dpld->dpram_dump(ld, buff);
- }
+void ts2utc(struct timespec *ts, struct utc_time *utc)
+{
+ struct tm tm;
+
+ time_to_tm((ts->tv_sec - (sys_tz.tz_minuteswest * 60)), 0, &tm);
+ utc->year = 1900 + tm.tm_year;
+ utc->mon = 1 + tm.tm_mon;
+ utc->day = tm.tm_mday;
+ utc->hour = tm.tm_hour;
+ utc->min = tm.tm_min;
+ utc->sec = tm.tm_sec;
+ utc->msec = ns2ms(ts->tv_nsec);
+}
- while (read_len < size) {
- skb = alloc_skb(MAX_IPC_SKB_SIZE, GFP_ATOMIC);
- if (!skb) {
- pr_err("[MIF] <%s> alloc skb failed\n", __func__);
- kfree(buff);
- return -ENOMEM;
- }
- memcpy(skb_put(skb, MAX_IPC_SKB_SIZE),
- buff + read_len, MAX_IPC_SKB_SIZE);
- skb_queue_tail(&iod->sk_rx_q, skb);
- read_len += MAX_IPC_SKB_SIZE;
- wake_up(&iod->wq);
- }
- kfree(buff);
- return 0;
+void get_utc_time(struct utc_time *utc)
+{
+ struct timespec ts;
+ getnstimeofday(&ts);
+ ts2utc(&ts, utc);
}
-#endif
+EXPORT_SYMBOL(get_utc_time);
int mif_dump_log(struct modem_shared *msd, struct io_device *iod)
{
@@ -82,7 +86,7 @@ int mif_dump_log(struct modem_shared *msd, struct io_device *iod)
while (read_len < MAX_MIF_BUFF_SIZE) {
skb = alloc_skb(MAX_IPC_SKB_SIZE, GFP_ATOMIC);
if (!skb) {
- pr_err("[MIF] <%s> alloc skb failed\n", __func__);
+ mif_err("ERR! alloc_skb fail\n");
spin_unlock_irqrestore(&msd->lock, flags);
return -ENOMEM;
}
@@ -164,7 +168,6 @@ void _mif_com_log(enum mif_log_id id,
struct mif_common_block *block;
unsigned long int flags;
va_list args;
- int ret;
spin_lock_irqsave(&msd->lock, flags);
@@ -179,7 +182,7 @@ void _mif_com_log(enum mif_log_id id,
block->time = get_kernel_time();
va_start(args, format);
- ret = vsnprintf(block->buff, MAX_COM_LOG_SIZE, format, args);
+ vsnprintf(block->buff, MAX_COM_LOG_SIZE, format, args);
va_end(args);
}
@@ -209,13 +212,12 @@ void _mif_time_log(enum mif_log_id id, struct modem_shared *msd,
/* dump2hex
* dump data to hex as fast as possible.
- * the length of @buf must be greater than "@len * 3"
+ * the length of @buff must be greater than "@len * 3"
* it need 3 bytes per one data byte to print.
*/
-static inline int dump2hex(char *buf, const char *data, size_t len)
+static inline int dump2hex(char *buff, const char *data, size_t len)
{
- static const char *hex = "0123456789abcdef";
- char *dest = buf;
+ char *dest = buff;
int i;
for (i = 0; i < len; i++) {
@@ -228,24 +230,26 @@ static inline int dump2hex(char *buf, const char *data, size_t len)
*dest = '\0';
- return dest - buf;
+ return dest - buff;
}
-int pr_ipc(const char *str, const char *data, size_t len)
+void pr_ipc(int level, const char *tag, const char *data, size_t len)
{
- struct timeval tv;
- struct tm date;
- unsigned char hexstr[128];
+ struct utc_time utc;
+ unsigned char str[128];
- do_gettimeofday(&tv);
- time_to_tm((tv.tv_sec - sys_tz.tz_minuteswest * 60), 0, &date);
-
- dump2hex(hexstr, data, (len > 40 ? 40 : len));
+ if (level < 0)
+ return;
- return pr_info("mif: %s: [%02d-%02d %02d:%02d:%02d.%03ld] %s\n",
- str, date.tm_mon + 1, date.tm_mday,
- date.tm_hour, date.tm_min, date.tm_sec,
- (tv.tv_usec > 0 ? tv.tv_usec / 1000 : 0), hexstr);
+ get_utc_time(&utc);
+ dump2hex(str, data, (len > 32 ? 32 : len));
+ if (level > 0) {
+ pr_err("%s: [%02d:%02d:%02d.%03d] %s: %s\n", MIF_TAG,
+ utc.hour, utc.min, utc.sec, utc.msec, tag, str);
+ } else {
+ pr_info("%s: [%02d:%02d:%02d.%03d] %s: %s\n", MIF_TAG,
+ utc.hour, utc.min, utc.sec, utc.msec, tag, str);
+ }
}
/* print buffer as hex string */
@@ -253,12 +257,12 @@ int pr_buffer(const char *tag, const char *data, size_t data_len,
size_t max_len)
{
size_t len = min(data_len, max_len);
- unsigned char hexstr[len ? len * 3 : 1]; /* 1 <= sizeof <= max_len*3 */
- dump2hex(hexstr, data, len);
+ unsigned char str[len ? len * 3 : 1]; /* 1 <= sizeof <= max_len*3 */
+ dump2hex(str, data, len);
/* don't change this printk to mif_debug for print this as level7 */
- return printk(KERN_INFO "mif: %s(%u): %s%s\n", tag, data_len, hexstr,
- len == data_len ? "" : " ...");
+ return printk(KERN_INFO "%s: %s(%u): %s%s\n", MIF_TAG, tag, data_len,
+ str, (len == data_len) ? "" : " ...");
}
/* flow control CM from CP, it use in serial devices */
@@ -285,7 +289,7 @@ int link_rx_flowctl_cmd(struct link_device *ld, const char *data, size_t len)
break;
default:
- mif_err("flowctl BACMD: %04X\n", *cmd);
+ mif_err("flowctl BAD CMD: %04X\n", *cmd);
break;
}
}
@@ -411,6 +415,42 @@ void rawdevs_set_tx_link(struct modem_shared *msd, enum modem_link link_type)
iodevs_for_each(msd, iodev_set_tx_link, ld);
}
+void mif_netif_stop(struct link_device *ld)
+{
+ struct io_device *iod;
+
+ if (ld->ipc_version < SIPC_VER_50)
+ iod = link_get_iod_with_channel(ld, 0x20 | RMNET0_CH_ID);
+ else
+ iod = link_get_iod_with_channel(ld, RMNET0_CH_ID);
+
+ if (iod)
+ iodevs_for_each(iod->msd, iodev_netif_stop, 0);
+}
+
+void mif_netif_wake(struct link_device *ld)
+{
+ struct io_device *iod;
+
+ /**
+ * If ld->suspend_netif_tx is true, this means that there was a SUSPEND
+ * flow control command from CP so MIF must wait for a RESUME command
+ * from CP.
+ */
+ if (ld->suspend_netif_tx) {
+ mif_info("%s: waiting for FLOW_CTRL_RESUME\n", ld->name);
+ return;
+ }
+
+ if (ld->ipc_version < SIPC_VER_50)
+ iod = link_get_iod_with_channel(ld, 0x20 | RMNET0_CH_ID);
+ else
+ iod = link_get_iod_with_channel(ld, RMNET0_CH_ID);
+
+ if (iod)
+ iodevs_for_each(iod->msd, iodev_netif_wake, 0);
+}
+
/**
* ipv4str_to_be32 - ipv4 string to be32 (big endian 32bits integer)
* @return: return zero when errors occurred
@@ -447,7 +487,7 @@ void mif_add_timer(struct timer_list *timer, unsigned long expire,
add_timer(timer);
}
-void mif_print_data(char *buf, int len)
+void mif_print_data(const char *buff, int len)
{
int words = len >> 4;
int residue = len - (words << 4);
@@ -458,11 +498,8 @@ void mif_print_data(char *buf, int len)
/* Make the last line, if ((len % 16) > 0) */
if (residue > 0) {
- memset(last, 0, sizeof(last));
- memset(tb, 0, sizeof(tb));
- b = buf + (words << 4);
-
sprintf(last, "%04X: ", (words << 4));
+ b = (char *)buff + (words << 4);
for (i = 0; i < residue; i++) {
sprintf(tb, "%02x ", b[i]);
strcat(last, tb);
@@ -474,7 +511,7 @@ void mif_print_data(char *buf, int len)
}
for (i = 0; i < words; i++) {
- b = buf + (i << 4);
+ b = (char *)buff + (i << 4);
mif_err("%04X: "
"%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -488,13 +525,141 @@ void mif_print_data(char *buf, int len)
mif_err("%s\n", last);
}
+void mif_dump2format16(const char *data, int len, char *buff, char *tag)
+{
+ char *d;
+ int i;
+ int words = len >> 4;
+ int residue = len - (words << 4);
+ char line[LINE_BUFF_SIZE];
+ char tb[8];
+
+ for (i = 0; i < words; i++) {
+ memset(line, 0, LINE_BUFF_SIZE);
+ d = (char *)data + (i << 4);
+
+ if (tag)
+ sprintf(line, "%s%04X| "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n",
+ tag, (i << 4),
+ d[0], d[1], d[2], d[3],
+ d[4], d[5], d[6], d[7],
+ d[8], d[9], d[10], d[11],
+ d[12], d[13], d[14], d[15]);
+ else
+ sprintf(line, "%04X| "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n",
+ (i << 4),
+ d[0], d[1], d[2], d[3],
+ d[4], d[5], d[6], d[7],
+ d[8], d[9], d[10], d[11],
+ d[12], d[13], d[14], d[15]);
+
+ strcat(buff, line);
+ }
+
+ /* Make the last line, if (len % 16) > 0 */
+ if (residue > 0) {
+ memset(line, 0, LINE_BUFF_SIZE);
+ memset(tb, 0, sizeof(tb));
+ d = (char *)data + (words << 4);
+
+ if (tag)
+ sprintf(line, "%s%04X|", tag, (words << 4));
+ else
+ sprintf(line, "%04X|", (words << 4));
+
+ for (i = 0; i < residue; i++) {
+ sprintf(tb, " %02x", d[i]);
+ strcat(line, tb);
+ if ((i & 0x3) == 0x3) {
+ sprintf(tb, " ");
+ strcat(line, tb);
+ }
+ }
+ strcat(line, "\n");
+
+ strcat(buff, line);
+ }
+}
+
+void mif_dump2format4(const char *data, int len, char *buff, char *tag)
+{
+ char *d;
+ int i;
+ int words = len >> 2;
+ int residue = len - (words << 2);
+ char line[LINE_BUFF_SIZE];
+ char tb[8];
+
+ for (i = 0; i < words; i++) {
+ memset(line, 0, LINE_BUFF_SIZE);
+ d = (char *)data + (i << 2);
+
+ if (tag)
+ sprintf(line, "%s%04X| %02x %02x %02x %02x\n",
+ tag, (i << 2), d[0], d[1], d[2], d[3]);
+ else
+ sprintf(line, "%04X| %02x %02x %02x %02x\n",
+ (i << 2), d[0], d[1], d[2], d[3]);
+
+ strcat(buff, line);
+ }
+
+ /* Make the last line, if (len % 4) > 0 */
+ if (residue > 0) {
+ memset(line, 0, LINE_BUFF_SIZE);
+ memset(tb, 0, sizeof(tb));
+ d = (char *)data + (words << 2);
+
+ if (tag)
+ sprintf(line, "%s%04X|", tag, (words << 2));
+ else
+ sprintf(line, "%04X|", (words << 2));
+
+ for (i = 0; i < residue; i++) {
+ sprintf(tb, " %02x", d[i]);
+ strcat(line, tb);
+ }
+ strcat(line, "\n");
+
+ strcat(buff, line);
+ }
+}
+
+void mif_print_dump(const char *data, int len, int width)
+{
+ char *buff;
+
+ buff = kzalloc(len << 3, GFP_ATOMIC);
+ if (!buff) {
+ mif_err("ERR! kzalloc fail\n");
+ return;
+ }
+
+ if (width == 16)
+ mif_dump2format16(data, len, buff, LOG_TAG);
+ else
+ mif_dump2format4(data, len, buff, LOG_TAG);
+
+ pr_info("%s", buff);
+
+ kfree(buff);
+}
+
void print_sipc4_hdlc_fmt_frame(const u8 *psrc)
{
u8 *frm; /* HDLC Frame */
struct fmt_hdr *hh; /* HDLC Header */
struct sipc_fmt_hdr *fh; /* IPC Header */
- u16 hh_len = sizeof(struct fmt_hdr);
- u16 fh_len = sizeof(struct sipc_fmt_hdr);
+ int hh_len = sizeof(struct fmt_hdr);
+ int fh_len = sizeof(struct sipc_fmt_hdr);
u8 *data;
int dlen;
@@ -531,7 +696,7 @@ void print_sipc4_hdlc_fmt_frame(const u8 *psrc)
void print_sipc4_fmt_frame(const u8 *psrc)
{
struct sipc_fmt_hdr *fh = (struct sipc_fmt_hdr *)psrc;
- u16 fh_len = sizeof(struct sipc_fmt_hdr);
+ int fh_len = sizeof(struct sipc_fmt_hdr);
u8 *data;
int dlen;
@@ -558,8 +723,8 @@ void print_sipc5_link_fmt_frame(const u8 *psrc)
u8 *lf; /* Link Frame */
struct sipc5_link_hdr *lh; /* Link Header */
struct sipc_fmt_hdr *fh; /* IPC Header */
- u16 lh_len;
- u16 fh_len;
+ int lh_len;
+ int fh_len;
u8 *data;
int dlen;
@@ -567,10 +732,7 @@ void print_sipc5_link_fmt_frame(const u8 *psrc)
/* Point HDLC header and IPC header */
lh = (struct sipc5_link_hdr *)lf;
- if (lh->cfg & SIPC5_CTL_FIELD_EXIST)
- lh_len = SIPC5_HEADER_SIZE_WITH_CTL_FLD;
- else
- lh_len = SIPC5_MIN_HEADER_SIZE;
+ lh_len = (u16)sipc5_get_hdr_len((u8 *)lh);
fh = (struct sipc_fmt_hdr *)(lf + lh_len);
fh_len = sizeof(struct sipc_fmt_hdr);
@@ -601,8 +763,8 @@ static void strcat_tcp_header(char *buff, u8 *pkt)
{
struct tcphdr *tcph = (struct tcphdr *)pkt;
int eol;
- char line[LINE_BUFF_SIZE];
- char flag_str[32];
+ char line[LINE_BUFF_SIZE] = {0, };
+ char flag_str[32] = {0, };
/*-------------------------------------------------------------------------
@@ -630,21 +792,17 @@ static void strcat_tcp_header(char *buff, u8 *pkt)
-------------------------------------------------------------------------*/
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: TCP:: Src.Port %u, Dst.Port %u\n",
- ntohs(tcph->source), ntohs(tcph->dest));
+ "%s: TCP:: Src.Port %u, Dst.Port %u\n",
+ MIF_TAG, ntohs(tcph->source), ntohs(tcph->dest));
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: TCP:: SEQ 0x%08X(%u), ACK 0x%08X(%u)\n",
- ntohs(tcph->seq), ntohs(tcph->seq),
+ "%s: TCP:: SEQ 0x%08X(%u), ACK 0x%08X(%u)\n",
+ MIF_TAG, ntohs(tcph->seq), ntohs(tcph->seq),
ntohs(tcph->ack_seq), ntohs(tcph->ack_seq));
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
- memset(flag_str, 0, sizeof(flag_str));
if (tcph->cwr)
strcat(flag_str, "CWR ");
if (tcph->ece)
@@ -664,12 +822,12 @@ static void strcat_tcp_header(char *buff, u8 *pkt)
eol = strlen(flag_str) - 1;
if (eol > 0)
flag_str[eol] = 0;
- snprintf(line, LINE_BUFF_SIZE, "mif: TCP:: Flags {%s}\n", flag_str);
+ snprintf(line, LINE_BUFF_SIZE, "%s: TCP:: Flags {%s}\n",
+ MIF_TAG, flag_str);
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: TCP:: Window %u, Checksum 0x%04X, Urg Pointer %u\n",
+ "%s: TCP:: Window %u, Checksum 0x%04X, Urgent %u\n", MIF_TAG,
ntohs(tcph->window), ntohs(tcph->check), ntohs(tcph->urg_ptr));
strcat(buff, line);
}
@@ -677,7 +835,7 @@ static void strcat_tcp_header(char *buff, u8 *pkt)
static void strcat_udp_header(char *buff, u8 *pkt)
{
struct udphdr *udph = (struct udphdr *)pkt;
- char line[LINE_BUFF_SIZE];
+ char line[LINE_BUFF_SIZE] = {0, };
/*-------------------------------------------------------------------------
@@ -693,41 +851,39 @@ static void strcat_udp_header(char *buff, u8 *pkt)
-------------------------------------------------------------------------*/
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: UDP:: Src.Port %u, Dst.Port %u\n",
- ntohs(udph->source), ntohs(udph->dest));
+ "%s: UDP:: Src.Port %u, Dst.Port %u\n",
+ MIF_TAG, ntohs(udph->source), ntohs(udph->dest));
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: UDP:: Length %u, Checksum 0x%04X\n",
- ntohs(udph->len), ntohs(udph->check));
+ "%s: UDP:: Length %u, Checksum 0x%04X\n",
+ MIF_TAG, ntohs(udph->len), ntohs(udph->check));
strcat(buff, line);
if (ntohs(udph->dest) == 53) {
- memset(line, 0, LINE_BUFF_SIZE);
- snprintf(line, LINE_BUFF_SIZE, "mif: UDP:: DNS query!!!\n");
+ snprintf(line, LINE_BUFF_SIZE, "%s: UDP:: DNS query!!!\n",
+ MIF_TAG);
strcat(buff, line);
}
if (ntohs(udph->source) == 53) {
- memset(line, 0, LINE_BUFF_SIZE);
- snprintf(line, LINE_BUFF_SIZE, "mif: UDP:: DNS response!!!\n");
+ snprintf(line, LINE_BUFF_SIZE, "%s: UDP:: DNS response!!!\n",
+ MIF_TAG);
strcat(buff, line);
}
}
-void print_ip4_packet(u8 *ip_pkt, bool tx)
+void print_ip4_packet(const u8 *ip_pkt, bool tx)
{
char *buff;
struct iphdr *iph = (struct iphdr *)ip_pkt;
- u8 *pkt = ip_pkt + (iph->ihl << 2);
+ u8 *pkt = (u8 *)ip_pkt + (iph->ihl << 2);
u16 flags = (ntohs(iph->frag_off) & 0xE000);
u16 frag_off = (ntohs(iph->frag_off) & 0x1FFF);
int eol;
- char line[LINE_BUFF_SIZE];
- char flag_str[16];
+ char line[LINE_BUFF_SIZE] = {0, };
+ char flag_str[16] = {0, };
/*---------------------------------------------------------------------------
IPv4 Header Format
@@ -764,32 +920,25 @@ void print_ip4_packet(u8 *ip_pkt, bool tx)
if (!buff)
return;
-
- memset(line, 0, LINE_BUFF_SIZE);
if (tx)
snprintf(line, LINE_BUFF_SIZE, "\n%s\n", TX_SEPARATOR);
else
snprintf(line, LINE_BUFF_SIZE, "\n%s\n", RX_SEPARATOR);
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE, "%s\n", LINE_SEPARATOR);
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: IP4:: Version %u, Header Length %u, TOS %u, Length %u\n",
- iph->version, (iph->ihl << 2), iph->tos, ntohs(iph->tot_len));
+ "%s: IP4:: Version %u, Header Length %u, TOS %u, Length %u\n",
+ MIF_TAG, iph->version, (iph->ihl << 2), iph->tos,
+ ntohs(iph->tot_len));
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
- snprintf(line, LINE_BUFF_SIZE,
- "mif: IP4:: ID %u, Fragment Offset %u\n",
- ntohs(iph->id), frag_off);
+ snprintf(line, LINE_BUFF_SIZE, "%s: IP4:: ID %u, Fragment Offset %u\n",
+ MIF_TAG, ntohs(iph->id), frag_off);
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
- memset(flag_str, 0, sizeof(flag_str));
if (flags & IP_CE)
strcat(flag_str, "CE ");
if (flags & IP_DF)
@@ -799,19 +948,18 @@ void print_ip4_packet(u8 *ip_pkt, bool tx)
eol = strlen(flag_str) - 1;
if (eol > 0)
flag_str[eol] = 0;
- snprintf(line, LINE_BUFF_SIZE, "mif: IP4:: Flags {%s}\n", flag_str);
+ snprintf(line, LINE_BUFF_SIZE, "%s: IP4:: Flags {%s}\n",
+ MIF_TAG, flag_str);
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: IP4:: TTL %u, Protocol %u, Header Checksum 0x%04X\n",
- iph->ttl, iph->protocol, ntohs(iph->check));
+ "%s: IP4:: TTL %u, Protocol %u, Header Checksum 0x%04X\n",
+ MIF_TAG, iph->ttl, iph->protocol, ntohs(iph->check));
strcat(buff, line);
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE,
- "mif: IP4:: Src.IP %u.%u.%u.%u, Dst.IP %u.%u.%u.%u\n",
- ip_pkt[12], ip_pkt[13], ip_pkt[14], ip_pkt[15],
+ "%s: IP4:: Src.IP %u.%u.%u.%u, Dst.IP %u.%u.%u.%u\n",
+ MIF_TAG, ip_pkt[12], ip_pkt[13], ip_pkt[14], ip_pkt[15],
ip_pkt[16], ip_pkt[17], ip_pkt[18], ip_pkt[19]);
strcat(buff, line);
@@ -828,7 +976,6 @@ void print_ip4_packet(u8 *ip_pkt, bool tx)
break;
}
- memset(line, 0, LINE_BUFF_SIZE);
snprintf(line, LINE_BUFF_SIZE, "%s\n", LINE_SEPARATOR);
strcat(buff, line);
@@ -837,7 +984,7 @@ void print_ip4_packet(u8 *ip_pkt, bool tx)
kfree(buff);
}
-bool is_dns_packet(u8 *ip_pkt)
+bool is_dns_packet(const u8 *ip_pkt)
{
struct iphdr *iph = (struct iphdr *)ip_pkt;
struct udphdr *udph = (struct udphdr *)(ip_pkt + (iph->ihl << 2));
@@ -852,7 +999,7 @@ bool is_dns_packet(u8 *ip_pkt)
return false;
}
-bool is_syn_packet(u8 *ip_pkt)
+bool is_syn_packet(const u8 *ip_pkt)
{
struct iphdr *iph = (struct iphdr *)ip_pkt;
struct tcphdr *tcph = (struct tcphdr *)(ip_pkt + (iph->ihl << 2));
@@ -867,124 +1014,248 @@ bool is_syn_packet(u8 *ip_pkt)
return false;
}
-int memcmp16_to_io(const void __iomem *to, void *from, int size)
+/**
+ * mif_register_isr
+ * @irq: IRQ number for a DPRAM interrupt
+ * @isr: function pointer to an interrupt service routine
+ * @flags: set of interrupt flags
+ * @name: name of the interrupt
+ * @data: pointer to a data for @isr
+ *
+ * Registers the ISR for the IRQ number.
+ */
+int mif_register_isr(unsigned int irq, irq_handler_t isr, unsigned long flags,
+ const char *name, void *data)
{
- u16 *d = (u16 *)to;
- u16 *s = (u16 *)from;
- int count = size >> 1;
- int diff = 0;
- int i;
- u16 d1;
- u16 s1;
-
- for (i = 0; i < count; i++) {
- d1 = ioread16(d);
- s1 = *s;
- if (d1 != s1) {
- diff++;
- mif_err("ERR! [%d] d:0x%04X != s:0x%04X\n", i, d1, s1);
- }
- d++;
- s++;
+ int ret;
+
+ ret = request_irq(irq, isr, flags, name, data);
+ if (ret) {
+ mif_err("%s: ERR! request_irq fail (err %d)\n", name, ret);
+ return ret;
}
- return diff;
+ ret = enable_irq_wake(irq);
+ if (ret)
+ mif_err("%s: ERR! enable_irq_wake fail (err %d)\n", name, ret);
+
+ mif_err("%s (#%d) handler registered\n", name, irq);
+
+ return 0;
}
-int mif_test_dpram(char *dp_name, u8 __iomem *start, u32 size)
+int mif_test_dpram(char *dp_name, void __iomem *start, u16 bytes)
{
- u8 __iomem *dst;
- int i;
+ u16 i;
+ u16 words = bytes >> 1;
+ u16 __iomem *dst = (u16 __iomem *)start;
u16 val;
+ int err_cnt = 0;
- mif_info("%s: start = 0x%p, size = %d\n", dp_name, start, size);
+ mif_err("%s: start 0x%p, bytes %d\n", dp_name, start, bytes);
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
- iowrite16((i & 0xFFFF), dst);
- dst += 2;
+ mif_err("%s: 0/6 stage ...\n", dp_name);
+ for (i = 1; i <= 100; i++) {
+ iowrite16(0x1234, dst);
+ val = ioread16(dst);
+ if (val != 0x1234) {
+ mif_err("%s: [0x0000] read 0x%04X != written 0x1234 "
+ "(try# %d)\n", dp_name, val, i);
+ err_cnt++;
+ }
+ }
+
+ if (err_cnt > 0) {
+ mif_err("%s: FAIL!!!\n", dp_name);
+ return -EINVAL;
+ }
+
+ mif_err("%s: 1/6 stage ...\n", dp_name);
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
+ iowrite16(0, dst);
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
val = ioread16(dst);
- if (val != (i & 0xFFFF)) {
- mif_info("%s: ERR! dst[%d] 0x%04X != 0x%04X\n",
- dp_name, i, val, (i & 0xFFFF));
- return -EINVAL;
+ if (val != 0x0000) {
+ mif_err("%s: ERR! [0x%04X] read 0x%04X != written "
+ "0x0000\n", dp_name, i, val);
+ err_cnt++;
}
- dst += 2;
+ dst++;
+ }
+
+ if (err_cnt > 0) {
+ mif_err("%s: FAIL!!!\n", dp_name);
+ return -EINVAL;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ mif_err("%s: 2/6 stage ...\n", dp_name);
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
+ iowrite16(0xFFFF, dst);
+ dst++;
+ }
+
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
+ val = ioread16(dst);
+ if (val != 0xFFFF) {
+ mif_err("%s: ERR! [0x%04X] read 0x%04X != written "
+ "0xFFFF\n", dp_name, i, val);
+ err_cnt++;
+ }
+ dst++;
+ }
+
+ if (err_cnt > 0) {
+ mif_err("%s: FAIL!!!\n", dp_name);
+ return -EINVAL;
+ }
+
+ mif_err("%s: 3/6 stage ...\n", dp_name);
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
iowrite16(0x00FF, dst);
- dst += 2;
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
val = ioread16(dst);
if (val != 0x00FF) {
- mif_info("%s: ERR! dst[%d] 0x%04X != 0x00FF\n",
- dp_name, i, val);
- return -EINVAL;
+ mif_err("%s: ERR! [0x%04X] read 0x%04X != written "
+ "0x00FF\n", dp_name, i, val);
+ err_cnt++;
}
- dst += 2;
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ if (err_cnt > 0) {
+ mif_err("%s: FAIL!!!\n", dp_name);
+ return -EINVAL;
+ }
+
+ mif_err("%s: 4/6 stage ...\n", dp_name);
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
iowrite16(0x0FF0, dst);
- dst += 2;
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
val = ioread16(dst);
if (val != 0x0FF0) {
- mif_info("%s: ERR! dst[%d] 0x%04X != 0x0FF0\n",
- dp_name, i, val);
- return -EINVAL;
+ mif_err("%s: ERR! [0x%04X] read 0x%04X != written "
+ "0x0FF0\n", dp_name, i, val);
+ err_cnt++;
}
- dst += 2;
+ dst++;
+ }
+
+ if (err_cnt > 0) {
+ mif_err("%s: FAIL!!!\n", dp_name);
+ return -EINVAL;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ mif_err("%s: 5/6 stage ...\n", dp_name);
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
iowrite16(0xFF00, dst);
- dst += 2;
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
val = ioread16(dst);
if (val != 0xFF00) {
- mif_info("%s: ERR! dst[%d] 0x%04X != 0xFF00\n",
- dp_name, i, val);
- return -EINVAL;
+ mif_err("%s: ERR! [0x%04X] read 0x%04X != written "
+ "0xFF00\n", dp_name, i, val);
+ err_cnt++;
}
- dst += 2;
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
- iowrite16(0, dst);
- dst += 2;
+ mif_err("%s: 6/6 stage ...\n", dp_name);
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
+ iowrite16((i & 0xFFFF), dst);
+ dst++;
}
- dst = start;
- for (i = 0; i < (size >> 1); i++) {
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
val = ioread16(dst);
- if (val != 0) {
- mif_info("%s: ERR! dst[%d] 0x%04X != 0\n",
- dp_name, i, val);
- return -EINVAL;
+ if (val != (i & 0xFFFF)) {
+ mif_err("%s: ERR! [0x%04X] read 0x%04X != written "
+ "0x%04X\n", dp_name, i, val, (i & 0xFFFF));
+ err_cnt++;
}
- dst += 2;
+ dst++;
+ }
+
+ if (err_cnt > 0) {
+ mif_err("%s: FAIL!!!\n", dp_name);
+ return -EINVAL;
+ }
+
+ mif_err("%s: PASS!!!\n", dp_name);
+
+ dst = (u16 __iomem *)start;
+ for (i = 0; i < words; i++) {
+ iowrite16(0, dst);
+ dst++;
}
- mif_info("%s: PASS!!!\n", dp_name);
return 0;
}
+struct file *mif_open_file(const char *path)
+{
+ struct file *fp;
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ fp = filp_open(path, O_RDWR|O_CREAT|O_APPEND, 0666);
+
+ set_fs(old_fs);
+
+ if (IS_ERR(fp))
+ return NULL;
+
+ return fp;
+}
+
+void mif_save_file(struct file *fp, const char *buff, size_t size)
+{
+ int ret;
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ ret = fp->f_op->write(fp, buff, size, &fp->f_pos);
+ if (ret < 0)
+ mif_err("ERR! write fail\n");
+
+ set_fs(old_fs);
+}
+
+void mif_close_file(struct file *fp)
+{
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ filp_close(fp, NULL);
+
+ set_fs(old_fs);
+}
+
diff --git a/drivers/misc/modem_if/modem_utils.h b/drivers/misc/modem_if/modem_utils.h
index 7225ec2..15edb43 100644
--- a/drivers/misc/modem_if/modem_utils.h
+++ b/drivers/misc/modem_if/modem_utils.h
@@ -16,6 +16,7 @@
#define __MODEM_UTILS_H__
#include <linux/rbtree.h>
+#include "modem_prj.h"
#define IS_CONNECTED(iod, ld) ((iod)->link_types & LINKTYPE((ld)->link_type))
@@ -26,6 +27,8 @@
#define MAX_IPC_SKB_SIZE 4096
#define MAX_LOG_SIZE 64
+#define MIF_TAG "mif"
+
#define MAX_LOG_CNT (MAX_MIF_BUFF_SIZE / MAX_LOG_SIZE)
#define MIF_ID_SIZE sizeof(enum mif_log_id)
@@ -96,7 +99,19 @@ struct mif_time_block {
char buff[MAX_TIM_LOG_SIZE];
};
-int mif_dump_dpram(struct io_device *);
+static inline int ns2us(long ns)
+{
+ return (ns > 0) ? (ns / 1000) : 0;
+}
+
+static inline int ns2ms(long ns)
+{
+ return (ns > 0) ? (ns / 1000000) : 0;
+}
+
+void ts2utc(struct timespec *ts, struct utc_time *utc);
+void get_utc_time(struct utc_time *utc);
+
int mif_dump_log(struct modem_shared *, struct io_device *);
#define mif_irq_log(msd, map, data, len) \
@@ -141,7 +156,7 @@ static inline unsigned int countbits(unsigned int n)
}
/* print IPC message as hex string with UTC time */
-int pr_ipc(const char *str, const char *data, size_t len);
+void pr_ipc(int level, const char *tag, const char *data, size_t len);
/* print buffer as hex string */
int pr_buffer(const char *tag, const char *data, size_t data_len,
@@ -156,10 +171,13 @@ int pr_buffer(const char *tag, const char *data, size_t data_len,
pr_buffer(tag, (char *)((urb)->transfer_buffer), \
(size_t)((urb)->actual_length), (size_t)16)
+/* Stop/wake all TX queues in network interfaces */
+void mif_netif_stop(struct link_device *ld);
+void mif_netif_wake(struct link_device *ld);
+
/* flow control CMD from CP, it use in serial devices */
int link_rx_flowctl_cmd(struct link_device *ld, const char *data, size_t len);
-
/* get iod from tree functions */
struct io_device *get_iod_with_format(struct modem_shared *msd,
@@ -204,12 +222,14 @@ void mif_add_timer(struct timer_list *timer, unsigned long expire,
void (*function)(unsigned long), unsigned long data);
/* debug helper functions for sipc4, sipc5 */
-void mif_print_data(char *buf, int len);
+void mif_print_data(const char *buff, int len);
+void mif_dump2format16(const char *data, int len, char *buff, char *tag);
+void mif_dump2format4(const char *data, int len, char *buff, char *tag);
+void mif_print_dump(const char *data, int len, int width);
void print_sipc4_hdlc_fmt_frame(const u8 *psrc);
void print_sipc4_fmt_frame(const u8 *psrc);
void print_sipc5_link_fmt_frame(const u8 *psrc);
-
/*---------------------------------------------------------------------------
IPv4 Header Format
@@ -282,23 +302,17 @@ void print_sipc5_link_fmt_frame(const u8 *psrc);
-------------------------------------------------------------------------*/
#define UDP_HDR_SIZE 8
-void print_ip4_packet(u8 *ip_pkt, bool tx);
-bool is_dns_packet(u8 *ip_pkt);
-bool is_syn_packet(u8 *ip_pkt);
+void print_ip4_packet(const u8 *ip_pkt, bool tx);
+bool is_dns_packet(const u8 *ip_pkt);
+bool is_syn_packet(const u8 *ip_pkt);
-int memcmp16_to_io(const void __iomem *to, void *from, int size);
-int mif_test_dpram(char *dp_name, u8 __iomem *start, u32 size);
+int mif_register_isr(unsigned int irq, irq_handler_t isr, unsigned long flags,
+ const char *name, void *data);
+int mif_test_dpram(char *dp_name, void __iomem *start, u16 bytes);
-static const inline char *get_dev_name(int dev)
-{
- if (dev == IPC_FMT)
- return "FMT";
- else if (dev == IPC_RAW)
- return "RAW";
- else if (dev == IPC_RFS)
- return "RFS";
- else
- return "NONE";
-}
+struct file *mif_open_file(const char *path);
+void mif_save_file(struct file *fp, const char *buff, size_t size);
+void mif_close_file(struct file *fp);
#endif/*__MODEM_UTILS_H__*/
+
diff --git a/drivers/misc/modem_if/modem_variation.h b/drivers/misc/modem_if/modem_variation.h
index b5ec61b..b314bb2 100644
--- a/drivers/misc/modem_if/modem_variation.h
+++ b/drivers/misc/modem_if/modem_variation.h
@@ -1,5 +1,4 @@
/*
- * Copyright (C) 2010 Google, Inc.
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -16,7 +15,7 @@
#ifndef __MODEM_VARIATION_H__
#define __MODEM_VARIATION_H__
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#define DECLARE_MODEM_INIT(type) \
int type ## _init_modemctl_device(struct modem_ctl *mc, \
@@ -61,12 +60,30 @@ DECLARE_MODEM_INIT(cbp72);
DECLARE_MODEM_INIT_DUMMY(cbp72)
#endif
+#ifdef CONFIG_CDMA_MODEM_CBP82
+DECLARE_MODEM_INIT(cbp82);
+#else
+DECLARE_MODEM_INIT_DUMMY(cbp82)
+#endif
+
+#ifdef CONFIG_LTE_MODEM_CMC220
+DECLARE_MODEM_INIT(cmc220);
+#else
+DECLARE_MODEM_INIT_DUMMY(cmc220)
+#endif
+
#ifdef CONFIG_LTE_MODEM_CMC221
DECLARE_MODEM_INIT(cmc221);
#else
DECLARE_MODEM_INIT_DUMMY(cmc221)
#endif
+#ifdef CONFIG_UMTS_MODEM_SS222
+DECLARE_MODEM_INIT(ss222);
+#else
+DECLARE_MODEM_INIT_DUMMY(ss222)
+#endif
+
#ifdef CONFIG_CDMA_MODEM_MDM6600
DECLARE_MODEM_INIT(mdm6600);
#else
@@ -79,6 +96,12 @@ DECLARE_MODEM_INIT(esc6270);
DECLARE_MODEM_INIT_DUMMY(esc6270)
#endif
+#ifdef CONFIG_CDMA_MODEM_QSC6085
+DECLARE_MODEM_INIT(qsc6085);
+#else
+DECLARE_MODEM_INIT_DUMMY(qsc6085)
+#endif
+
#ifdef CONFIG_TDSCDMA_MODEM_SPRD8803
DECLARE_MODEM_INIT(sprd8803);
#else
@@ -94,6 +117,18 @@ DECLARE_LINK_INIT(mipi);
DECLARE_LINK_INIT_DUMMY(mipi)
#endif
+#ifdef CONFIG_LINK_DEVICE_USB
+DECLARE_LINK_INIT(usb);
+#else
+DECLARE_LINK_INIT_DUMMY(usb)
+#endif
+
+#ifdef CONFIG_LINK_DEVICE_HSIC
+DECLARE_LINK_INIT(hsic);
+#else
+DECLARE_LINK_INIT_DUMMY(hsic)
+#endif
+
#ifdef CONFIG_LINK_DEVICE_DPRAM
DECLARE_LINK_INIT(dpram);
#else
@@ -106,53 +141,52 @@ DECLARE_LINK_INIT(pld);
DECLARE_LINK_INIT_DUMMY(pld)
#endif
-#ifdef CONFIG_LINK_DEVICE_SPI
-DECLARE_LINK_INIT(spi);
-#else
-DECLARE_LINK_INIT_DUMMY(spi)
-#endif
-
-#ifdef CONFIG_LINK_DEVICE_USB
-DECLARE_LINK_INIT(usb);
+#ifdef CONFIG_LINK_DEVICE_C2C
+DECLARE_LINK_INIT(c2c);
#else
-DECLARE_LINK_INIT_DUMMY(usb)
+DECLARE_LINK_INIT_DUMMY(c2c)
#endif
-#ifdef CONFIG_LINK_DEVICE_HSIC
-DECLARE_LINK_INIT(hsic);
+#ifdef CONFIG_LINK_DEVICE_SHMEM
+DECLARE_LINK_INIT(shmem);
#else
-DECLARE_LINK_INIT_DUMMY(hsic)
+DECLARE_LINK_INIT_DUMMY(shmem)
#endif
-#ifdef CONFIG_LINK_DEVICE_C2C
-DECLARE_LINK_INIT(c2c);
+#ifdef CONFIG_LINK_DEVICE_SPI
+DECLARE_LINK_INIT(spi);
#else
-DECLARE_LINK_INIT_DUMMY(c2c)
+DECLARE_LINK_INIT_DUMMY(spi)
#endif
typedef int (*modem_init_call)(struct modem_ctl *, struct modem_data *);
-static modem_init_call modem_init_func[] = {
- MODEM_INIT_CALL(xmm6260),
- MODEM_INIT_CALL(xmm6262),
- MODEM_INIT_CALL(cbp71),
- MODEM_INIT_CALL(cbp72),
- MODEM_INIT_CALL(cmc221),
- MODEM_INIT_CALL(mdm6600),
- MODEM_INIT_CALL(esc6270),
- MODEM_INIT_CALL(sprd8803),
- MODEM_INIT_CALL(dummy),
+static modem_init_call modem_init_func[MAX_MODEM_TYPE] = {
+ [IMC_XMM6260] = MODEM_INIT_CALL(xmm6260),
+ [IMC_XMM6262] = MODEM_INIT_CALL(xmm6262),
+ [VIA_CBP71] = MODEM_INIT_CALL(cbp71),
+ [VIA_CBP72] = MODEM_INIT_CALL(cbp72),
+ [VIA_CBP82] = MODEM_INIT_CALL(cbp82),
+ [SEC_CMC220] = MODEM_INIT_CALL(cmc220),
+ [SEC_CMC221] = MODEM_INIT_CALL(cmc221),
+ [SEC_SS222] = MODEM_INIT_CALL(ss222),
+ [QC_MDM6600] = MODEM_INIT_CALL(mdm6600),
+ [QC_ESC6270] = MODEM_INIT_CALL(esc6270),
+ [QC_QSC6085] = MODEM_INIT_CALL(qsc6085),
+ [SPRD_SC8803] = MODEM_INIT_CALL(sprd8803),
+ [DUMMY] = MODEM_INIT_CALL(dummy),
};
typedef struct link_device *(*link_init_call)(struct platform_device *);
-static link_init_call link_init_func[] = {
- LINK_INIT_CALL(undefined),
- LINK_INIT_CALL(mipi),
- LINK_INIT_CALL(dpram),
- LINK_INIT_CALL(spi),
- LINK_INIT_CALL(usb),
- LINK_INIT_CALL(hsic),
- LINK_INIT_CALL(c2c),
- LINK_INIT_CALL(pld),
+static link_init_call link_init_func[LINKDEV_MAX] = {
+ [LINKDEV_UNDEFINED] = LINK_INIT_CALL(undefined),
+ [LINKDEV_MIPI] = LINK_INIT_CALL(mipi),
+ [LINKDEV_USB] = LINK_INIT_CALL(usb),
+ [LINKDEV_HSIC] = LINK_INIT_CALL(hsic),
+ [LINKDEV_DPRAM] = LINK_INIT_CALL(dpram),
+ [LINKDEV_PLD] = LINK_INIT_CALL(pld),
+ [LINKDEV_C2C] = LINK_INIT_CALL(c2c),
+ [LINKDEV_SHMEM] = LINK_INIT_CALL(shmem),
+ [LINKDEV_SPI] = LINK_INIT_CALL(spi),
};
static int call_modem_init_func(struct modem_ctl *mc, struct modem_data *pdata)
diff --git a/drivers/misc/modem_if/sipc4_io_device.c b/drivers/misc/modem_if/sipc4_io_device.c
index 28f95f7..da1ea04 100644
--- a/drivers/misc/modem_if/sipc4_io_device.c
+++ b/drivers/misc/modem_if/sipc4_io_device.c
@@ -1,6 +1,4 @@
-/* /linux/drivers/misc/modem_if/modem_io_device.c
- *
- * Copyright (C) 2010 Google, Inc.
+/*
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -26,10 +24,7 @@
#include <linux/etherdevice.h>
#include <linux/device.h>
-#include <linux/platform_data/modem.h>
-#ifdef CONFIG_LINK_DEVICE_C2C
-#include <linux/platform_data/c2c.h>
-#endif
+#include "modem.h"
#include "modem_prj.h"
#include "modem_utils.h"
@@ -40,7 +35,8 @@
* So, give restriction to allocation size below 1 page to prevent
* big pages broken.
*/
-#define MAX_RXDATA_SIZE 0x0E00 /* 4 * 1024 - 512 */
+#define MAX_RXDATA_SIZE (4096 - 512)
+#define MAX_BOOTDATA_SIZE 0x4008 /* EBL package format*/
#define MAX_MULTI_FMT_SIZE 0x4000 /* 16 * 1024 */
static const char hdlc_start[1] = { HDLC_START };
@@ -250,22 +246,6 @@ static int rx_hdlc_head_check(struct io_device *iod, struct link_device *ld,
hdr->start = HDLC_START;
hdr->len = 0;
- /* debug print */
- switch (iod->format) {
- case IPC_FMT:
- case IPC_RAW:
- case IPC_MULTI_RAW:
- case IPC_RFS:
- /* TODO: print buf... */
- break;
-
- case IPC_CMD:
- case IPC_BOOT:
- case IPC_RAMDUMP:
- default:
- break;
- }
-
buf += len;
done_len += len;
rest -= len; /* rest, call by value */
@@ -409,12 +389,6 @@ static int rx_multi_fmt_frame(struct sk_buff *rx_skb)
/* If there has been no multiple frame with this ID */
if (!(fh->control & 0x80)) {
/* It is a single frame because the "more" bit is 0. */
-#if 0
- mif_err("\n<%s> Rx FMT frame (len %d)\n",
- iod->name, rcvd);
- print_sipc4_fmt_frame(data);
- mif_err("\n");
-#endif
skb_queue_tail(&iod->sk_rx_q,
fragdata(iod, ld)->skb_recv);
mif_debug("wake up wq of %s\n", iod->name);
@@ -449,12 +423,6 @@ static int rx_multi_fmt_frame(struct sk_buff *rx_skb)
/* It is the last frame because the "more" bit is 0. */
mif_info("The Last (ID %d, %d bytes received)\n",
id, skb->len);
-#if 0
- mif_err("\n<%s> Rx FMT frame (len %d)\n",
- iod->name, skb->len);
- print_sipc4_fmt_frame(skb->data);
- mif_err("\n");
-#endif
skb_queue_tail(&iod->sk_rx_q, skb);
iod->skb[id] = NULL;
mif_info("wake up wq of %s\n", iod->name);
@@ -491,12 +459,6 @@ static int rx_multi_fmt_frame_sipc42(struct sk_buff *rx_skb)
/* If there has been no multiple frame with this ID */
if (!(fh->control & 0x80)) {
/* It is a single frame because the "more" bit is 0. */
-#if 0
- mif_err("\n<%s> Rx FMT frame (len %d)\n",
- iod->name, rcvd);
- print_sipc4_fmt_frame(data);
- mif_err("\n");
-#endif
skb_queue_tail(&real_iod->sk_rx_q,
fragdata(iod, ld)->skb_recv);
mif_debug("wake up wq of %s\n", iod->name);
@@ -530,12 +492,6 @@ static int rx_multi_fmt_frame_sipc42(struct sk_buff *rx_skb)
/* It is the last frame because the "more" bit is 0. */
mif_err("The Last (ID %d, %d bytes received)\n",
id, skb->len);
-#if 0
- mif_err("\n<%s> Rx FMT frame (len %d)\n",
- iod->name, skb->len);
- print_sipc4_fmt_frame(skb->data);
- mif_err("\n");
-#endif
skb_queue_tail(&real_iod->sk_rx_q, skb);
real_iod->skb[id] = NULL;
mif_info("wake up wq of %s\n", real_iod->name);
@@ -819,55 +775,6 @@ exit:
return err;
}
-static int rx_rfs_packet(struct io_device *iod, struct link_device *ld,
- const char *data, unsigned size)
-{
- int err = 0;
- int pad = 0;
- int rcvd = 0;
- struct sk_buff *skb;
-
- if (data[0] != HDLC_START) {
- mif_err("Dropping RFS packet ... "
- "size = %d, start = %02X %02X %02X %02X\n",
- size,
- data[0], data[1], data[2], data[3]);
- return -EINVAL;
- }
-
- if (data[size-1] != HDLC_END) {
- for (pad = 1; pad < 4; pad++)
- if (data[(size-1)-pad] == HDLC_END)
- break;
-
- if (pad >= 4) {
- char *b = (char *)data;
- unsigned sz = size;
- mif_err("size %d, No END_FLAG!!!\n", size);
- mif_err("end = %02X %02X %02X %02X\n",
- b[sz-4], b[sz-3], b[sz-2], b[sz-1]);
- return -EINVAL;
- } else {
- mif_info("padding = %d\n", pad);
- }
- }
-
- skb = rx_alloc_skb(size, iod, ld);
- if (unlikely(!skb)) {
- mif_err("alloc_skb fail\n");
- return -ENOMEM;
- }
-
- /* copy the RFS haeder to skb->data */
- rcvd = size - sizeof(hdlc_start) - sizeof(hdlc_end) - pad;
- memcpy(skb_put(skb, rcvd), ((char *)data + sizeof(hdlc_start)), rcvd);
-
- fragdata(iod, ld)->skb_recv = skb;
- err = rx_iodev_skb(fragdata(iod, ld)->skb_recv);
-
- return err;
-}
-
/* called from link device when a packet arrives for this io device */
static int io_dev_recv_data_from_link_dev(struct io_device *iod,
struct link_device *ld, const char *data, unsigned int len)
@@ -891,14 +798,9 @@ static int io_dev_recv_data_from_link_dev(struct io_device *iod,
*/
switch (iod->format) {
- case IPC_RFS:
-#ifdef CONFIG_IPC_CMC22x_OLD_RFS
- err = rx_rfs_packet(iod, ld, data, len);
- return err;
-#endif
-
case IPC_FMT:
case IPC_RAW:
+ case IPC_RFS:
case IPC_MULTI_RAW:
if (iod->waketime)
wake_lock_timeout(&iod->wakelock, iod->waketime);
@@ -961,12 +863,17 @@ static int io_dev_recv_data_from_link_dev(struct io_device *iod,
static void io_dev_modem_state_changed(struct io_device *iod,
enum modem_state state)
{
- iod->mc->phone_state = state;
- mif_err("modem state changed. (iod: %s, state: %d)\n",
- iod->name, state);
+ struct modem_ctl *mc = iod->mc;
+ int old_state = mc->phone_state;
- if ((state == STATE_CRASH_RESET) || (state == STATE_CRASH_EXIT)
- || (state == STATE_NV_REBUILDING))
+ if (old_state != state) {
+ mc->phone_state = state;
+ mif_err("%s state changed (%s -> %s)\n", mc->name,
+ get_cp_state_str(old_state), get_cp_state_str(state));
+ }
+
+ if (state == STATE_CRASH_RESET || state == STATE_CRASH_EXIT ||
+ state == STATE_NV_REBUILDING)
wake_up(&iod->wq);
}
@@ -977,10 +884,24 @@ static void io_dev_modem_state_changed(struct io_device *iod,
*/
static void io_dev_sim_state_changed(struct io_device *iod, bool sim_online)
{
+
+#if defined(CONFIG_MACH_KONA) && defined(CONFIG_UMTS_MODEM_XMM6262)
+ mif_err("modem_current_state is %d\n", iod->mc->phone_state);
+#endif
+
if (atomic_read(&iod->opened) == 0) {
- mif_err("iod is not opened: %s\n",
- iod->name);
- } else if (iod->mc->sim_state.online == sim_online) {
+ mif_err("iod is not opened: %s\n", iod->name);
+ /* update latest sim status */
+ iod->mc->sim_state.online = sim_online;
+ }
+#if defined(CONFIG_LINK_DEVICE_HSIC) && defined(CONFIG_UMTS_MODEM_XMM6262) // fixed modem unknown issue (kina 3G)
+ else if (iod->mc->phone_state == STATE_BOOTING) {
+ mif_err("modem_current_state is STATE_BOOTING\n");
+ /* update latest sim status */
+ iod->mc->sim_state.online = sim_online;
+ }
+#endif
+ else if (iod->mc->sim_state.online == sim_online) {
mif_err("sim state not changed.\n");
} else {
iod->mc->sim_state.online = sim_online;
@@ -995,6 +916,7 @@ static void io_dev_sim_state_changed(struct io_device *iod, bool sim_online)
}
}
+
static int misc_open(struct inode *inode, struct file *filp)
{
struct io_device *iod = to_io_device(filp->private_data);
@@ -1078,32 +1000,32 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
switch (cmd) {
case IOCTL_MODEM_ON:
- mif_debug("misc_ioctl : IOCTL_MODEM_ON\n");
+ mif_debug("%s: IOCTL_MODEM_ON\n", iod->name);
return iod->mc->ops.modem_on(iod->mc);
case IOCTL_MODEM_OFF:
- mif_debug("misc_ioctl : IOCTL_MODEM_OFF\n");
+ mif_debug("%s: IOCTL_MODEM_OFF\n", iod->name);
return iod->mc->ops.modem_off(iod->mc);
case IOCTL_MODEM_RESET:
- mif_debug("misc_ioctl : IOCTL_MODEM_RESET\n");
+ mif_debug("%s: IOCTL_MODEM_RESET\n", iod->name);
return iod->mc->ops.modem_reset(iod->mc);
case IOCTL_MODEM_BOOT_ON:
- mif_debug("misc_ioctl : IOCTL_MODEM_BOOT_ON\n");
+ mif_debug("%s: IOCTL_MODEM_BOOT_ON\n", iod->name);
return iod->mc->ops.modem_boot_on(iod->mc);
case IOCTL_MODEM_BOOT_OFF:
- mif_debug("misc_ioctl : IOCTL_MODEM_BOOT_OFF\n");
+ mif_debug("%s: IOCTL_MODEM_BOOT_OFF\n", iod->name);
return iod->mc->ops.modem_boot_off(iod->mc);
/* TODO - will remove this command after ril updated */
case IOCTL_MODEM_BOOT_DONE:
- mif_debug("misc_ioctl : IOCTL_MODEM_BOOT_DONE\n");
+ mif_debug("%s: IOCTL_MODEM_BOOT_DONE\n", iod->name);
return 0;
case IOCTL_MODEM_STATUS:
- mif_debug("misc_ioctl : IOCTL_MODEM_STATUS\n");
+ mif_debug("%s: IOCTL_MODEM_STATUS\n", iod->name);
p_state = iod->mc->phone_state;
if ((p_state == STATE_CRASH_RESET) ||
@@ -1126,7 +1048,7 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return p_state;
case IOCTL_MODEM_PROTOCOL_SUSPEND:
- mif_info("misc_ioctl : IOCTL_MODEM_PROTOCOL_SUSPEND\n");
+ mif_info("%s: IOCTL_MODEM_PROTOCOL_SUSPEND\n", iod->name);
if (iod->format != IPC_MULTI_RAW)
return -EINVAL;
@@ -1134,8 +1056,16 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
iodevs_for_each(iod->msd, iodev_netif_stop, 0);
return 0;
+ case IOCTL_MODEM_DL_START:
+ mif_info("%s: IOCTL_MODEM_DL_START\n", iod->name);
+ return ld->dload_start(ld, iod);
+
+ case IOCTL_MODEM_FW_UPDATE:
+ mif_info("%s: IOCTL_MODEM_FW_UPDATE\n", iod->name);
+ return ld->firm_update(ld, iod, arg);
+
case IOCTL_MODEM_PROTOCOL_RESUME:
- mif_info("misc_ioctl : IOCTL_MODEM_PROTOCOL_RESUME\n");
+ mif_info("%s: IOCTL_MODEM_PROTOCOL_RESUME\n", iod->name);
if (iod->format != IPC_MULTI_RAW)
return -EINVAL;
@@ -1144,21 +1074,29 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return 0;
case IOCTL_MODEM_DUMP_START:
- mif_err("misc_ioctl : IOCTL_MODEM_DUMP_START\n");
+ mif_err("%s: IOCTL_MODEM_DUMP_START\n", iod->name);
+ return ld->dump_start(ld, iod);
+
+ case IOCTL_MODEM_RAMDUMP_START:
+ mif_err("%s: IOCTL_MODEM_RAMDUMP_START\n", iod->name);
return ld->dump_start(ld, iod);
case IOCTL_MODEM_DUMP_UPDATE:
- mif_debug("misc_ioctl : IOCTL_MODEM_DUMP_UPDATE\n");
+ mif_debug("%s: IOCTL_MODEM_DUMP_UPDATE\n", iod->name);
return ld->dump_update(ld, iod, arg);
+ case IOCTL_MODEM_RAMDUMP_STOP:
+ mif_info("%s: IOCTL_MODEM_RAMDUMP_STOP\n", iod->name);
+ return ld->dump_finish(ld, iod, arg);
+
case IOCTL_MODEM_FORCE_CRASH_EXIT:
- mif_debug("misc_ioctl : IOCTL_MODEM_FORCE_CRASH_EXIT\n");
+ mif_debug("%s: IOCTL_MODEM_FORCE_CRASH_EXIT\n", iod->name);
if (iod->mc->ops.modem_force_crash_exit)
return iod->mc->ops.modem_force_crash_exit(iod->mc);
return -EINVAL;
case IOCTL_MODEM_CP_UPLOAD:
- mif_err("misc_ioctl : IOCTL_MODEM_CP_UPLOAD\n");
+ mif_err("%s: IOCTL_MODEM_CP_UPLOAD\n", iod->name);
if (copy_from_user(cpinfo_buf + strlen(cpinfo_buf),
(void __user *)arg, MAX_CPINFO_SIZE) != 0)
panic("CP Crash");
@@ -1167,12 +1105,12 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return 0;
case IOCTL_MODEM_DUMP_RESET:
- mif_err("misc_ioctl : IOCTL_MODEM_DUMP_RESET\n");
+ mif_err("%s: IOCTL_MODEM_DUMP_RESET\n", iod->name);
return iod->mc->ops.modem_dump_reset(iod->mc);
#if defined(CONFIG_SEC_DUAL_MODEM_MODE)
case IOCTL_MODEM_SWITCH_MODEM:
- mif_err("misc_ioctl : IOCTL_MODEM_SWITCH_MODEM\n");
+ mif_err("%s: IOCTL_MODEM_SWITCH_MODEM\n", iod->name);
iod->mc->phone_state = STATE_MODEM_SWITCH;
wake_up(&iod->wq);
return 0;
@@ -1188,20 +1126,6 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
mif_dump_log(iod->mc->msd, iod);
return 0;
- case IOCTL_MIF_DPRAM_DUMP:
-#ifdef CONFIG_LINK_DEVICE_DPRAM
- if (iod->mc->mdm_data->link_types & LINKTYPE(LINKDEV_DPRAM)) {
- size = iod->mc->mdm_data->dpram_ctl->dp_size;
- ret = copy_to_user((void __user *)arg, &size,
- sizeof(unsigned long));
- if (ret < 0)
- return -EFAULT;
- mif_dump_dpram(iod);
- return 0;
- }
-#endif
- return -EINVAL;
-
default:
/* If you need to handle the ioctl for specific link device,
* then assign the link ioctl handler to ld->ioctl
@@ -1209,12 +1133,48 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (ld->ioctl)
return ld->ioctl(ld, iod, cmd, arg);
- mif_err("misc_ioctl : ioctl 0x%X is not defined.\n", cmd);
+ mif_err("%s: ioctl 0x%X is not defined\n", iod->name, cmd);
return -EINVAL;
}
return 0;
}
+static size_t _boot_write(struct io_device *iod, const char __user *buf,
+ size_t count)
+{
+ int rest_len = count, frame_len = 0;
+ char *cur = (char *)buf;
+ struct sk_buff *skb = NULL;
+ struct link_device *ld = get_current_link(iod);
+ int ret;
+
+ while (rest_len) {
+ frame_len = min(rest_len, MAX_BOOTDATA_SIZE);
+ skb = alloc_skb(frame_len, GFP_KERNEL);
+ if (!skb) {
+ mif_err("fail alloc skb (%d)\n", __LINE__);
+ return -ENOMEM;
+ }
+ if (copy_from_user(
+ skb_put(skb, frame_len), cur, frame_len) != 0) {
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
+ }
+ rest_len -= frame_len;
+ cur += frame_len;
+
+ skbpriv(skb)->iod = iod;
+ skbpriv(skb)->ld = ld;
+
+ ret = ld->send(ld, iod, skb);
+ if (ret < 0) {
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+ }
+ return count;
+}
+
static ssize_t misc_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -1237,6 +1197,10 @@ static ssize_t misc_write(struct file *filp, const char __user *buf,
skb = alloc_skb(frame_len, GFP_KERNEL);
if (!skb) {
+ if (frame_len > MAX_BOOTDATA_SIZE && iod->format == IPC_BOOT) {
+ mif_info("large alloc fail\n");
+ return _boot_write(iod, buf, count);
+ }
mif_err("fail alloc skb (%d)\n", __LINE__);
return -ENOMEM;
}
@@ -1278,31 +1242,6 @@ static ssize_t misc_write(struct file *filp, const char __user *buf,
skb_put(skb, calc_padding_size(iod, ld, skb->len));
-#if 0
- if (iod->format == IPC_FMT) {
- mif_err("\n<%s> Tx HDLC FMT frame (len %d)\n",
- iod->name, skb->len);
- print_sipc4_hdlc_fmt_frame(skb->data);
- mif_err("\n");
- }
-#endif
-#if 0
- if (iod->format == IPC_RAW) {
- mif_err("\n<%s> Tx HDLC RAW frame (len %d)\n",
- iod->name, skb->len);
- mif_print_data(skb->data, (skb->len < 64 ? skb->len : 64));
- mif_err("\n");
- }
-#endif
-#if 0
- if (iod->format == IPC_RFS) {
- mif_err("\n<%s> Tx HDLC RFS frame (len %d)\n",
- iod->name, skb->len);
- mif_print_data(skb->data, (skb->len < 64 ? skb->len : 64));
- mif_err("\n");
- }
-#endif
-
/* send data with sk_buff, link device will put sk_buff
* into the specific sk_buff_q and run work-q to send data
*/
@@ -1409,43 +1348,6 @@ static ssize_t misc_read(struct file *filp, char *buf, size_t count,
return pktsize;
}
-#ifdef CONFIG_LINK_DEVICE_C2C
-static int misc_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- int r = 0;
- unsigned long size = 0;
- unsigned long pfn = 0;
- unsigned long offset = 0;
- struct io_device *iod = (struct io_device *)filp->private_data;
-
- if (!vma)
- return -EFAULT;
-
- size = vma->vm_end - vma->vm_start;
- offset = vma->vm_pgoff << PAGE_SHIFT;
- if (offset + size > (C2C_CP_RGN_SIZE + C2C_SH_RGN_SIZE)) {
- mif_err("offset + size > C2C_CP_RGN_SIZE\n");
- return -EINVAL;
- }
-
- /* Set the noncacheable property to the region */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- vma->vm_flags |= VM_RESERVED | VM_IO;
-
- pfn = __phys_to_pfn(C2C_CP_RGN_ADDR + offset);
- r = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
- if (r) {
- mif_err("Failed in remap_pfn_range()!!!\n");
- return -EAGAIN;
- }
-
- mif_err("VA = 0x%08lx, offset = 0x%lx, size = %lu\n",
- vma->vm_start, offset, size);
-
- return 0;
-}
-#endif
-
static const struct file_operations misc_io_fops = {
.owner = THIS_MODULE,
.open = misc_open,
@@ -1454,9 +1356,6 @@ static const struct file_operations misc_io_fops = {
.unlocked_ioctl = misc_ioctl,
.write = misc_write,
.read = misc_read,
-#ifdef CONFIG_LINK_DEVICE_C2C
- .mmap = misc_mmap,
-#endif
};
static int vnet_open(struct net_device *ndev)
diff --git a/drivers/misc/modem_if/sipc4_modem.c b/drivers/misc/modem_if/sipc4_modem.c
index 59e2de9..b4f9c2a 100644
--- a/drivers/misc/modem_if/sipc4_modem.c
+++ b/drivers/misc/modem_if/sipc4_modem.c
@@ -32,7 +32,7 @@
#include <linux/delay.h>
#include <linux/wakelock.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
#include "modem_variation.h"
#include "modem_utils.h"
@@ -328,9 +328,22 @@ static int modem_resume(struct device *pdev)
return 0;
}
+#ifdef CONFIG_FAST_BOOT
+static void modem_complete(struct device *pdev)
+{
+ struct modem_ctl *mc = dev_get_drvdata(pdev);
+
+ if (mc->modem_complete)
+ mc->modem_complete(mc);
+}
+#endif
+
static const struct dev_pm_ops modem_pm_ops = {
.suspend = modem_suspend,
.resume = modem_resume,
+#ifdef CONFIG_FAST_BOOT
+ .complete = modem_complete,
+#endif
};
static struct platform_driver modem_driver = {
diff --git a/drivers/misc/modem_if/sipc5_common.c b/drivers/misc/modem_if/sipc5_common.c
new file mode 100644
index 0000000..e8574c2
--- /dev/null
+++ b/drivers/misc/modem_if/sipc5_common.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/init.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/if_arp.h>
+#include <linux/ip.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
+#include <linux/device.h>
+
+#include "modem.h"
+#include "modem_prj.h"
+#include "modem_utils.h"
+
+/**
+ * sipc5_start_valid
+ * @cfg: configuration field of an SIPC5 link frame
+ *
+ * Returns TRUE if the start (configuration field) of an SIPC5 link frame
+ * is valid or returns FALSE if it is not valid.
+ *
+ */
+bool sipc5_start_valid(u8 *frm)
+{
+ return (*frm & SIPC5_START_MASK) == SIPC5_START_MASK;
+}
+
+bool sipc5_padding_exist(u8 *frm)
+{
+ return (*frm & SIPC5_PADDING_EXIST) ? true : false;
+}
+
+bool sipc5_multi_frame(u8 *frm)
+{
+ return (*frm & SIPC5_EXT_FIELD_MASK) == SIPC5_CTL_FIELD_MASK;
+}
+
+bool sipc5_ext_len(u8 *frm)
+{
+ return (*frm & SIPC5_EXT_FIELD_MASK) == SIPC5_EXT_LENGTH_MASK;
+}
+
+/**
+ * sipc5_get_hdr_len
+ * @cfg: configuration field of an SIPC5 link frame
+ *
+ * Returns the length of SIPC5 link layer header in an SIPC5 link frame
+ *
+ */
+int sipc5_get_hdr_len(u8 *frm)
+{
+ if (*frm & SIPC5_EXT_FIELD_EXIST) {
+ if (*frm & SIPC5_CTL_FIELD_EXIST)
+ return SIPC5_HEADER_SIZE_WITH_CTL_FLD;
+ else
+ return SIPC5_HEADER_SIZE_WITH_EXT_LEN;
+ } else {
+ return SIPC5_MIN_HEADER_SIZE;
+ }
+}
+
+/**
+ * sipc5_get_ch_id
+ * @frm: pointer to an SIPC5 frame
+ *
+ * Returns the channel ID in an SIPC5 link frame
+ *
+ */
+u8 sipc5_get_ch_id(u8 *frm)
+{
+ return *(frm + SIPC5_CH_ID_OFFSET);
+}
+
+/**
+ * sipc5_get_ctrl_field
+ * @frm: pointer to an SIPC5 frame
+ *
+ * Returns the control field in an SIPC5 link frame
+ *
+ */
+u8 sipc5_get_ctrl_field(u8 *frm)
+{
+ return *(frm + SIPC5_CTL_OFFSET);
+}
+
+/**
+ * sipc5_get_frame_len
+ * @frm: pointer to an SIPC5 link frame
+ *
+ * Returns the length of an SIPC5 link frame
+ *
+ */
+int sipc5_get_frame_len(u8 *frm)
+{
+ u8 cfg = frm[0];
+ u16 *sz16 = (u16 *)(frm + SIPC5_LEN_OFFSET);
+ u32 *sz32 = (u32 *)(frm + SIPC5_LEN_OFFSET);
+
+ if (unlikely(cfg & SIPC5_EXT_FIELD_EXIST)) {
+ if (cfg & SIPC5_CTL_FIELD_EXIST)
+ return (int)(*sz16);
+ else
+ return (int)(*sz32);
+ } else {
+ return (int)(*sz16);
+ }
+}
+
+/**
+ * sipc5_calc_padding_size
+ * @len: length of an SIPC5 link frame
+ *
+ * Returns the padding size for an SIPC5 link frame
+ *
+ */
+int sipc5_calc_padding_size(int len)
+{
+ int residue = len & 0x3;
+ return residue ? (4 - residue) : 0;
+}
+
+/**
+ * sipc5_get_total_len
+ * @frm: pointer to an SIPC5 link frame
+ *
+ * Returns the total length of an SIPC5 link frame with padding
+ *
+ */
+int sipc5_get_total_len(u8 *frm)
+{
+ int len = sipc5_get_frame_len(frm);
+ int pad = sipc5_padding_exist(frm) ? sipc5_calc_padding_size(len) : 0;
+ return len + pad;
+}
+
+/**
+ * sipc5_build_config
+ * @iod: pointer to the IO device
+ * @ld: pointer to the link device
+ * @count: length of the data to be transmitted
+ *
+ * Builds a config value for an SIPC5 link frame header
+ *
+ * Returns the config value for the header or 0 for non-SIPC formats
+ */
+u8 sipc5_build_config(struct io_device *iod, struct link_device *ld, u32 count)
+{
+ u8 cfg = SIPC5_START_MASK;
+
+ if (iod->format > IPC_MULTI_RAW && iod->id == 0)
+ return 0;
+
+ if (ld->aligned)
+ cfg |= SIPC5_PADDING_EXIST;
+
+#if 0
+ if ((count + SIPC5_MIN_HEADER_SIZE) > ld->mtu[dev])
+ cfg |= SIPC5_CTL_FIELD_MASK;
+ else
+#endif
+ if ((count + SIPC5_MIN_HEADER_SIZE) > 0xFFFF)
+ cfg |= SIPC5_EXT_LENGTH_MASK;
+
+ return cfg;
+}
+
+/**
+ * sipc5_build_header
+ * @iod: pointer to the IO device
+ * @ld: pointer to the link device
+ * @buff: pointer to a buffer in which an SIPC5 link frame header will be stored
+ * @cfg: value for the config field in the header
+ * @ctrl: value for the control field in the header
+ * @count: length of data in the SIPC5 link frame to be transmitted
+ *
+ * Builds the link layer header of an SIPC5 frame
+ */
+void sipc5_build_header(struct io_device *iod, struct link_device *ld,
+ u8 *buff, u8 cfg, u8 ctrl, u32 count)
+{
+ u16 *sz16 = (u16 *)(buff + SIPC5_LEN_OFFSET);
+ u32 *sz32 = (u32 *)(buff + SIPC5_LEN_OFFSET);
+ u32 hdr_len = sipc5_get_hdr_len(&cfg);
+
+ /* Store the config field and the channel ID field */
+ buff[SIPC5_CONFIG_OFFSET] = cfg;
+ buff[SIPC5_CH_ID_OFFSET] = iod->id;
+
+ /* Store the frame length field */
+ if (sipc5_ext_len(buff))
+ *sz32 = (u32)(hdr_len + count);
+ else
+ *sz16 = (u16)(hdr_len + count);
+
+ /* Store the control field */
+ if (sipc5_multi_frame(buff))
+ buff[SIPC5_CTL_OFFSET] = ctrl;
+}
+
+/**
+ * std_udl_get_cmd
+ * @frm: pointer to an SIPC5 link frame
+ *
+ * Returns the standard BOOT/DUMP (STD_UDL) command in an SIPC5 BOOT/DUMP frame.
+ */
+u32 std_udl_get_cmd(u8 *frm)
+{
+ u8 *cmd = frm + sipc5_get_hdr_len(frm);
+ return *((u32 *)cmd);
+}
+
+/**
+ * std_udl_with_payload
+ * @cmd: standard BOOT/DUMP command
+ *
+ * Returns true if the STD_UDL command has a payload.
+ */
+bool std_udl_with_payload(u32 cmd)
+{
+ u32 mask = cmd & STD_UDL_STEP_MASK;
+ return (mask && mask < STD_UDL_CRC) ? true : false;
+}
+
diff --git a/drivers/misc/modem_if/sipc5_io_device.c b/drivers/misc/modem_if/sipc5_io_device.c
index a9932c1..71596ae 100644
--- a/drivers/misc/modem_if/sipc5_io_device.c
+++ b/drivers/misc/modem_if/sipc5_io_device.c
@@ -1,5 +1,4 @@
-/* /linux/drivers/misc/modem_if/sipc5_io_device.c
- *
+/*
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
@@ -24,11 +23,9 @@
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/device.h>
+#include <linux/module.h>
-#include <linux/platform_data/modem.h>
-#ifdef CONFIG_LINK_DEVICE_C2C
-#include <linux/platform_data/c2c.h>
-#endif
+#include "modem.h"
#include "modem_prj.h"
#include "modem_utils.h"
@@ -104,7 +101,7 @@ static void iodev_showtxlink(struct io_device *iod, void *args)
struct link_device *ld = get_current_link(iod);
if (iod->io_typ == IODEV_NET && IS_CONNECTED(iod, ld))
- *p += sprintf(*p, "%s: %s\n", iod->name, ld->name);
+ *p += sprintf(*p, "%s<->%s\n", iod->name, ld->name);
}
static ssize_t show_txlink(struct device *dev,
@@ -130,181 +127,107 @@ static ssize_t store_txlink(struct device *dev,
static struct device_attribute attr_txlink =
__ATTR(txlink, S_IRUGO | S_IWUSR, show_txlink, store_txlink);
-/**
- * rx_check_frame_cfg
- * @cfg: configuration field of a link layer header
- * @frm: pointer to the sipc5_frame_data buffer
- *
- * 1) Checks whether or not an extended field exists
- * 2) Calculates the length of a link layer header
- *
- * Returns the size of a link layer header
- *
- * Must be invoked only when the configuration field of the link layer header
- * is validated with sipc5_start_valid() function
- */
-static int rx_check_frame_cfg(u8 cfg, struct sipc5_frame_data *frm)
+static int netif_flow_ctrl(struct link_device *ld, struct sk_buff *skb)
{
- frm->config = cfg;
-
- if (likely(cfg & SIPC5_PADDING_EXIST))
- frm->padding = true;
-
- if (unlikely(cfg & SIPC5_EXT_FIELD_EXIST)) {
- if (cfg & SIPC5_CTL_FIELD_EXIST) {
- frm->ctl_fld = true;
- frm->hdr_len = SIPC5_HEADER_SIZE_WITH_CTL_FLD;
- } else {
- frm->ext_len = true;
- frm->hdr_len = SIPC5_HEADER_SIZE_WITH_EXT_LEN;
- }
+ u8 cmd = skb->data[0];
+
+ if (cmd == FLOW_CTRL_SUSPEND) {
+ if (ld->suspend_netif_tx)
+ goto exit;
+ ld->suspend_netif_tx = true;
+ mif_netif_stop(ld);
+ mif_info("%s: FLOW_CTRL_SUSPEND\n", ld->name);
+ } else if (cmd == FLOW_CTRL_RESUME) {
+ if (!ld->suspend_netif_tx)
+ goto exit;
+ ld->suspend_netif_tx = false;
+ mif_netif_wake(ld);
+ mif_info("%s: FLOW_CTRL_RESUME\n", ld->name);
} else {
- frm->hdr_len = SIPC5_MIN_HEADER_SIZE;
+ mif_info("%s: ERR! invalid command %02X\n", ld->name, cmd);
}
- return frm->hdr_len;
-}
-
-/**
- * rx_build_meta_data
- * @ld: pointer to the link device
- * @frm: pointer to the sipc5_frame_data buffer
- *
- * Fills each field of sipc5_frame_data from a link layer header
- * 1) Extracts the channel ID
- * 2) Calculates the length of a link layer frame
- * 3) Extracts a control field if exists
- * 4) Calculates the length of an IPC message packet in the link layer frame
- *
- */
-static void rx_build_meta_data(struct link_device *ld,
- struct sipc5_frame_data *frm)
-{
- u16 *sz16 = (u16 *)(frm->hdr + SIPC5_LEN_OFFSET);
- u32 *sz32 = (u32 *)(frm->hdr + SIPC5_LEN_OFFSET);
-
- frm->ch_id = frm->hdr[SIPC5_CH_ID_OFFSET];
-
- if (unlikely(frm->ext_len))
- frm->len = *sz32;
- else
- frm->len = *sz16;
-
- if (unlikely(frm->ctl_fld))
- frm->control = frm->hdr[SIPC5_CTL_OFFSET];
-
- frm->data_len = frm->len - frm->hdr_len;
-
- mif_debug("%s: FRM ch:%d len:%d ctl:%02X data.len:%d\n",
- ld->name, frm->ch_id, frm->len, frm->control, frm->data_len);
+exit:
+ dev_kfree_skb_any(skb);
+ return 0;
}
-/**
- * tx_build_link_header
- * @frm: pointer to the sipc5_frame_data buffer
- * @iod: pointer to the IO device
- * @ld: pointer to the link device
- * @count: length of the data to be transmitted
- *
- * Builds the meta data for an SIPC5 frame and the link layer header of it
- * Returns the link layer header length for an SIPC5 frame or 0 for other frame
- */
-static unsigned tx_build_link_header(struct sipc5_frame_data *frm,
- struct io_device *iod, struct link_device *ld, ssize_t count)
+static inline int queue_skb_to_iod(struct sk_buff *skb, struct io_device *iod)
{
- u8 *buff = frm->hdr;
- u16 *sz16 = (u16 *)(buff + SIPC5_LEN_OFFSET);
- u32 *sz32 = (u32 *)(buff + SIPC5_LEN_OFFSET);
+ struct sk_buff_head *rxq = &iod->sk_rx_q;
- memset(frm, 0, sizeof(struct sipc5_frame_data));
+ skb_queue_tail(rxq, skb);
- if (iod->format == IPC_CMD ||
- iod->format == IPC_BOOT ||
- iod->format == IPC_RAMDUMP) {
- frm->len = count;
+ if (iod->format < IPC_MULTI_RAW && rxq->qlen > MAX_IOD_RXQ_LEN) {
+ struct sk_buff *victim = skb_dequeue(rxq);
+ mif_err("%s: %s application may be dead (rxq->qlen %d > %d)\n",
+ iod->name, iod->app ? iod->app : "corresponding",
+ rxq->qlen, MAX_IOD_RXQ_LEN);
+ if (victim)
+ dev_kfree_skb_any(victim);
+ return -ENOSPC;
+ } else {
+ mif_debug("%s: rxq->qlen = %d\n", iod->name, rxq->qlen);
return 0;
}
+}
- frm->config = SIPC5_START_MASK;
+static int rx_drain(struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+ return 0;
+}
- if (iod->format == IPC_FMT && count > 2048) {
- frm->ctl_fld = true;
- frm->config |= SIPC5_EXT_FIELD_EXIST;
- frm->config |= SIPC5_CTL_FIELD_EXIST;
- }
+static int rx_loopback(struct sk_buff *skb)
+{
+ struct io_device *iod = skbpriv(skb)->iod;
+ struct link_device *ld = skbpriv(skb)->ld;
+ int ret;
- if (iod->id >= SIPC5_CH_ID_RFS_0 && count > 0xFFFF) {
- frm->ext_len = true;
- frm->config |= SIPC5_EXT_FIELD_EXIST;
+ ret = ld->send(ld, iod, skb);
+ if (ret < 0) {
+ mif_err("%s->%s: ERR! ld->send fail (err %d)\n",
+ iod->name, ld->name, ret);
}
- if (ld->aligned)
- frm->config |= SIPC5_PADDING_EXIST;
-
- frm->ch_id = iod->id;
-
- frm->hdr_len = sipc5_get_hdr_len(frm->config);
- frm->data_len = count;
- frm->len = frm->hdr_len + frm->data_len;
-
- buff[SIPC5_CONFIG_OFFSET] = frm->config;
- buff[SIPC5_CH_ID_OFFSET] = frm->ch_id;
-
- if (unlikely(frm->ext_len))
- *sz32 = (u32)frm->len;
- else
- *sz16 = (u16)frm->len;
-
- if (unlikely(frm->ctl_fld))
- buff[SIPC5_CTL_OFFSET] = frm->control;
-
- return frm->hdr_len;
+ return ret;
}
static int rx_fmt_frame(struct sk_buff *skb)
{
- struct io_device *iod = skbpriv(skb)->iod;
struct link_device *ld = skbpriv(skb)->ld;
- struct sk_buff_head *rxq = &iod->sk_rx_q;
- struct sipc_fmt_hdr *fh;
+ struct io_device *iod = skbpriv(skb)->iod;
struct sk_buff *rx_skb;
- u8 ctrl = skbpriv(skb)->control;
- unsigned id = ctrl & 0x7F;
+ int hdr_len = sipc5_get_hdr_len(skb->data);
+ u8 ctrl;
+ u8 id;
- if (iod->skb[id] == NULL) {
- /*
- ** There has been no multiple frame with this ID.
- */
- if ((ctrl & 0x80) == 0) {
- /*
- ** It is a single frame because the "more" bit is 0.
- */
- skb_queue_tail(rxq, skb);
- if (unlikely(rxq->qlen > 2048)) {
- struct sk_buff *victim;
- mif_info("%s: WARNING! rxq->qlen %d > 2048\n",
- iod->name, rxq->qlen);
- victim = skb_dequeue(rxq);
- dev_kfree_skb_any(victim);
- } else {
- mif_debug("%s: rxq->qlen = %d\n",
- iod->name, rxq->qlen);
- }
+ if (!sipc5_multi_frame(skb->data)) {
+ skb_pull(skb, hdr_len);
+ queue_skb_to_iod(skb, iod);
+ wake_up(&iod->wq);
+ return 0;
+ }
- wake_up(&iod->wq);
- return 0;
- }
+ /* Get the control field */
+ ctrl = sipc5_get_ctrl_field(skb->data);
- /*
- ** The start of multiple frames
- */
- fh = (struct sipc_fmt_hdr *)skb->data;
- mif_debug("%s: start multi-frame (ID:%d len:%d)\n",
- iod->name, id, fh->len);
+ /* Extract the control ID from the control field */
+ id = ctrl & 0x7F;
+
+ /* Remove SIPC5 link header */
+ skb_pull(skb, hdr_len);
+
+ /* If there has been no multiple frame with this ID, ... */
+ if (iod->skb[id] == NULL) {
+ struct sipc_fmt_hdr *fh = (struct sipc_fmt_hdr *)skb->data;
+
+ mif_err("%s->%s: start of multi-frame (ID:%d len:%d)\n",
+ ld->name, iod->name, id, fh->len);
rx_skb = rx_alloc_skb(fh->len, iod, ld);
if (!rx_skb) {
- mif_info("%s: ERR! rx_alloc_skb fail\n", iod->name);
+ mif_err("%s: ERR! rx_alloc_skb fail\n", iod->name);
return -ENOMEM;
}
@@ -313,31 +236,19 @@ static int rx_fmt_frame(struct sk_buff *skb)
rx_skb = iod->skb[id];
}
- /*
- ** Start multi-frame processing
- */
+ /* Perform multi-frame processing */
memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);
dev_kfree_skb_any(skb);
if (ctrl & 0x80) {
/* The last frame has not arrived yet. */
- mif_debug("%s: recv multi-frame (ID:%d rcvd:%d)\n",
- iod->name, id, rx_skb->len);
+ mif_info("%s->%s: recv multi-frame (ID:%d rcvd:%d)\n",
+ ld->name, iod->name, id, rx_skb->len);
} else {
/* It is the last frame because the "more" bit is 0. */
- mif_debug("%s: end multi-frame (ID:%d rcvd:%d)\n",
- iod->name, id, rx_skb->len);
- skb_queue_tail(rxq, rx_skb);
- if (unlikely(rxq->qlen > 2048)) {
- struct sk_buff *victim;
- mif_info("%s: WARNING! rxq->qlen %d > 2048\n",
- iod->name, rxq->qlen);
- victim = skb_dequeue(rxq);
- dev_kfree_skb_any(victim);
- } else {
- mif_debug("%s: rxq->qlen = %d\n", iod->name, rxq->qlen);
- }
-
+ mif_err("%s->%s: end of multi-frame (ID:%d rcvd:%d)\n",
+ ld->name, iod->name, id, rx_skb->len);
+ queue_skb_to_iod(rx_skb, iod);
iod->skb[id] = NULL;
wake_up(&iod->wq);
}
@@ -345,76 +256,14 @@ static int rx_fmt_frame(struct sk_buff *skb)
return 0;
}
-static int rx_rfs_frame(struct sk_buff *skb)
-{
- struct io_device *iod = skbpriv(skb)->iod;
- struct sk_buff_head *rxq = &iod->sk_rx_q;
-
- skb_queue_tail(rxq, skb);
- if (unlikely(rxq->qlen > 2048)) {
- struct sk_buff *victim;
- mif_debug("%s: rxq->qlen %d > 2048\n", iod->name, rxq->qlen);
- victim = skb_dequeue(rxq);
- dev_kfree_skb_any(victim);
- } else {
- mif_debug("%s: rxq->qlen %d\n", iod->name, rxq->qlen);
- }
-
- wake_up(&iod->wq);
-
- return 0;
-}
-
-static int rx_loopback(struct sk_buff *skb)
-{
- struct io_device *iod = skbpriv(skb)->iod;
- struct link_device *ld = get_current_link(iod);
- struct sipc5_frame_data frm;
- unsigned headroom;
- unsigned tailroom = 0;
- int ret;
-
- headroom = tx_build_link_header(&frm, iod, ld, skb->len);
-
- if (ld->aligned)
- tailroom = sipc5_calc_padding_size(headroom + skb->len);
-
- /* We need not to expand skb in here. dev_alloc_skb (in rx_alloc_skb)
- * already alloc 32bytes padding in headroom. 32bytes are enough.
- */
-
- /* store IPC link header to start of skb
- * this is skb_push not skb_put. different with misc_write.
- */
- memcpy(skb_push(skb, headroom), frm.hdr, headroom);
-
- /* store padding */
- if (tailroom)
- skb_put(skb, tailroom);
-
- /* forward */
- ret = ld->send(ld, iod, skb);
- if (ret < 0)
- mif_err("%s->%s: ld->send fail: %d\n", iod->name,
- ld->name, ret);
- return ret;
-}
-
static int rx_raw_misc(struct sk_buff *skb)
{
- struct io_device *iod = skbpriv(skb)->iod; /* same with real_iod */
- struct sk_buff_head *rxq = &iod->sk_rx_q;
+ struct io_device *iod = skbpriv(skb)->iod;
- skb_queue_tail(rxq, skb);
- if (unlikely(rxq->qlen > 2048)) {
- struct sk_buff *victim;
- mif_debug("%s: rxq->qlen %d > 2048\n", iod->name, rxq->qlen);
- victim = skb_dequeue(rxq);
- dev_kfree_skb_any(victim);
- } else {
- mif_debug("%s: rxq->qlen %d\n", iod->name, rxq->qlen);
- }
+ /* Remove the SIPC5 link header */
+ skb_pull(skb, sipc5_get_hdr_len(skb->data));
+ queue_skb_to_iod(skb, iod);
wake_up(&iod->wq);
return 0;
@@ -422,12 +271,11 @@ static int rx_raw_misc(struct sk_buff *skb)
static int rx_multi_pdp(struct sk_buff *skb)
{
- struct io_device *iod = skbpriv(skb)->iod; /* same with real_iod */
+ struct link_device *ld = skbpriv(skb)->ld;
+ struct io_device *iod = skbpriv(skb)->iod;
struct net_device *ndev;
struct iphdr *iphdr;
- struct ethhdr *ehdr;
int ret;
- const char source[ETH_ALEN] = SOURCE_MAC_ADDR;
ndev = iod->ndev;
if (!ndev) {
@@ -435,6 +283,9 @@ static int rx_multi_pdp(struct sk_buff *skb)
return -ENODEV;
}
+ /* Remove the SIPC5 link header */
+ skb_pull(skb, sipc5_get_hdr_len(skb->data));
+
skb->dev = ndev;
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += skb->len;
@@ -447,14 +298,15 @@ static int rx_multi_pdp(struct sk_buff *skb)
skb->protocol = htons(ETH_P_IP);
if (iod->use_handover) {
- skb_push(skb, sizeof(struct ethhdr));
- ehdr = (void *)skb->data;
+ struct ethhdr *ehdr;
+ const char source[ETH_ALEN] = SOURCE_MAC_ADDR;
+
+ ehdr = (struct ethhdr *)skb_push(skb, sizeof(struct ethhdr));
memcpy(ehdr->h_dest, ndev->dev_addr, ETH_ALEN);
memcpy(ehdr->h_source, source, ETH_ALEN);
ehdr->h_proto = skb->protocol;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_reset_mac_header(skb);
-
skb_pull(skb, sizeof(struct ethhdr));
}
@@ -463,48 +315,82 @@ static int rx_multi_pdp(struct sk_buff *skb)
else
ret = netif_rx_ni(skb);
- if (ret != NET_RX_SUCCESS)
- mif_info("%s: ERR! netif_rx fail (err %d)\n", iod->name, ret);
+ if (ret != NET_RX_SUCCESS) {
+ mif_err("%s->%s: ERR! netif_rx fail (err %d)\n",
+ ld->name, iod->name, ret);
+ }
return ret;
}
static int rx_demux(struct link_device *ld, struct sk_buff *skb)
{
- struct io_device *iod = NULL;
- char *link = ld->name;
- u8 ch = skbpriv(skb)->ch_id;
+ struct io_device *iod;
+ u8 ch = sipc5_get_ch_id(skb->data);
+#ifdef DEBUG_MODEM_IF
+ struct modem_ctl *mc = ld->mc;
+ size_t len = (skb->len > 20) ? 20 : skb->len;
+ char tag[MIF_MAX_STR_LEN];
+#endif
- if (unlikely(ch == SIPC5_CH_ID_MAX || ch == 0)) {
- mif_info("%s: ERR! invalid ch# %d\n", link, ch);
+ if (unlikely(ch == 0)) {
+ mif_err("%s: ERR! invalid ch# %d\n", ld->name, ch);
return -ENODEV;
}
+ if (unlikely(ch == SIPC5_CH_ID_FLOW_CTRL))
+ return netif_flow_ctrl(ld, skb);
+
/* IP loopback */
if (ch == DATA_LOOPBACK_CHANNEL && ld->msd->loopback_ipaddr)
ch = RMNET0_CH_ID;
iod = link_get_iod_with_channel(ld, ch);
if (unlikely(!iod)) {
- mif_info("%s: ERR! no iod for ch# %d\n", link, ch);
+ mif_err("%s: ERR! no iod with ch# %d\n", ld->name, ch);
return -ENODEV;
}
skbpriv(skb)->ld = ld;
skbpriv(skb)->iod = iod;
- skbpriv(skb)->real_iod = iod;
- /* don't care about CP2AP_LOOPBACK_CHANNEL is opened */
- if (unlikely(iod->id == CP2AP_LOOPBACK_CHANNEL))
+ /* Don't care whether or not DATA_DRAIN_CHANNEL is opened */
+ if (iod->id == DATA_DRAIN_CHANNEL)
+ return rx_drain(skb);
+
+ /* Don't care whether or not DATA_LOOPBACK_CHANNEL is opened */
+ if (iod->id == DATA_LOOPBACK_CHANNEL)
return rx_loopback(skb);
+#ifdef DEBUG_MODEM_IF
+ snprintf(tag, MIF_MAX_STR_LEN, "LNK: %s->%s", mc->name, iod->name);
+ if (unlikely(iod->format == IPC_FMT))
+ pr_ipc(1, tag, skb->data, len);
+#if 0
+ if (iod->format == IPC_RAW)
+ pr_ipc(0, tag, skb->data, len);
+#endif
+#if 0
+ if (iod->format == IPC_BOOT)
+ pr_ipc(0, tag, skb->data, len);
+#endif
+#if 0
+ if (iod->format == IPC_RAMDUMP)
+ pr_ipc(0, tag, skb->data, len);
+#endif
+#if 0
+ if (ch == 28)
+ pr_ipc(0, tag, skb->data, len);
+#endif
+#endif /*DEBUG_MODEM_IF*/
+
if (atomic_read(&iod->opened) <= 0) {
- mif_info("%s: ERR! %s is not opened\n", link, iod->name);
+ mif_err("%s: ERR! %s is not opened\n", ld->name, iod->name);
return -ENODEV;
}
if (ch >= SIPC5_CH_ID_RFS_0)
- return rx_rfs_frame(skb);
+ return rx_raw_misc(skb);
else if (ch >= SIPC5_CH_ID_FMT_0)
return rx_fmt_frame(skb);
else if (iod->io_typ == IODEV_MISC)
@@ -513,342 +399,337 @@ static int rx_demux(struct link_device *ld, struct sk_buff *skb)
return rx_multi_pdp(skb);
}
-/* Check and store link layer header, then alloc an skb */
-static int rx_header_from_serial(struct io_device *iod, struct link_device *ld,
- u8 *buff, unsigned size, struct sipc5_frame_data *frm)
+/**
+ * rx_frame_config
+ * @iod: pointer to an instance of io_device structure
+ * @ld: pointer to an instance of link_device structure
+ * @buff: pointer to a buffer in which incoming data is stored
+ * @size: size of data in the buffer
+ * @frm: pointer to an instance of sipc5_frame_data structure
+ *
+ * 1) Checks a config field
+ * 2) Calculates the length of link layer header in an incoming frame and stores
+ * the value to "frm->hdr_len"
+ * 3) Stores the config field to "frm->hdr" and add the size of config field to
+ * "frm->hdr_rcvd"
+ *
+ * Returns the length of a config field that was copied to "frm"
+ */
+static int rx_frame_config(struct io_device *iod, struct link_device *ld,
+ u8 *buff, int size, struct sipc5_frame_data *frm)
{
- char *link = ld->name;
- struct sk_buff *skb;
- int len;
- u8 cfg = buff[0];
-
- mif_debug("%s: size %d\n", link, size);
-
- if (!frm->config) {
- if (unlikely(!sipc5_start_valid(cfg))) {
- mif_info("%s: ERR! wrong start (0x%02x)\n", link, cfg);
- return -EBADMSG;
- }
- rx_check_frame_cfg(cfg, frm);
-
- /* Copy the link layer header to the header buffer */
- len = min(frm->hdr_len, size);
- memcpy(frm->hdr, buff, len);
- } else {
- /* Copy the link layer header to the header buffer */
- len = min((frm->hdr_len - frm->hdr_rcvd), size);
- memcpy((frm->hdr + frm->hdr_rcvd), buff, len);
- }
+ int rest;
+ int rcvd;
- frm->hdr_rcvd += len;
-
- mif_debug("%s: FRM hdr_len:%d, hdr_rcvd:%d\n",
- link, frm->hdr_len, frm->hdr_rcvd);
-
- if (frm->hdr_rcvd >= frm->hdr_len) {
- rx_build_meta_data(ld, frm);
- skb = rx_alloc_skb(frm->data_len, iod, ld);
- fragdata(iod, ld)->skb_recv = skb;
- skbpriv(skb)->ch_id = frm->ch_id;
- skbpriv(skb)->control = frm->control;
+ if (unlikely(!sipc5_start_valid(buff))) {
+ mif_err("%s->%s: ERR! INVALID config 0x%02x\n",
+ ld->name, iod->name, buff[0]);
+ return -EBADMSG;
}
- return len;
-}
-
-/* copy data to skb */
-static int rx_payload_from_serial(struct io_device *iod, struct link_device *ld,
- u8 *buff, unsigned size, struct sipc5_frame_data *frm)
-{
- struct sk_buff *skb = fragdata(iod, ld)->skb_recv;
- char *link = ld->name;
- unsigned rest = frm->data_len - frm->data_rcvd;
- unsigned len;
-
- /* rest == (frm->data_len - frm->data_rcvd) == tailroom of skb */
- rest = frm->data_len - frm->data_rcvd;
- mif_debug("%s: FRM data.len:%d data.rcvd:%d rest:%d size:%d\n",
- link, frm->data_len, frm->data_rcvd, rest, size);
-
- /* If there is no skb, data must be dropped. */
- len = min(rest, size);
- if (skb)
- memcpy(skb_put(skb, len), buff, len);
+ frm->hdr_len = sipc5_get_hdr_len(buff);
- frm->data_rcvd += len;
+ /* Calculate the size of a segment that will be copied */
+ rest = frm->hdr_len;
+ rcvd = SIPC5_CONFIG_SIZE;
+ mif_debug("%s->%s: hdr_len:%d hdr_rcvd:%d rest:%d size:%d rcvd:%d\n",
+ ld->name, iod->name, frm->hdr_len, frm->hdr_rcvd, rest, size,
+ rcvd);
- mif_debug("%s: FRM data_len:%d, data_rcvd:%d\n",
- link, frm->data_len, frm->data_rcvd);
+ /* Copy the config field of an SIPC5 link header to the header buffer */
+ memcpy(frm->hdr, buff, rcvd);
+ frm->hdr_rcvd += rcvd;
- return len;
+ return rcvd;
}
-static int rx_frame_from_serial(struct io_device *iod, struct link_device *ld,
- const char *data, unsigned size)
+/**
+ * rx_frame_prepare_skb
+ * @iod: pointer to an instance of io_device structure
+ * @ld: pointer to an instance of link_device structure
+ * @frm: pointer to an instance of sipc5_frame_data structure
+ *
+ * 1) Extracts the length of a link frame from the link header in "frm->hdr"
+ * 2) Allocates an skb
+ * 3) Calculates the payload size in the link frame
+ * 4) Calculates the padding size in the link frame
+ *
+ * Returns the pointer to an skb
+ */
+static struct sk_buff *rx_frame_prepare_skb(struct io_device *iod,
+ struct link_device *ld, struct sipc5_frame_data *frm)
{
- struct sipc5_frame_data *frm = &fragdata(iod, ld)->f_data;
struct sk_buff *skb;
- char *link = ld->name;
- u8 *buff = (u8 *)data;
- int rest = (int)size;
- int err = 0;
- int done = 0;
- mif_debug("%s: size = %d\n", link, size);
+ /* Get the frame length */
+ frm->len = sipc5_get_frame_len(frm->hdr);
- if (frm->hdr_rcvd >= frm->hdr_len && frm->data_rcvd < frm->data_len) {
- /*
- ** There is an skb that is waiting for more SIPC5 data.
- ** In this case, rx_header_from_serial() must be skipped.
- */
- mif_debug("%s: FRM data.len:%d data.rcvd:%d -> recv_data\n",
- link, frm->data_len, frm->data_rcvd);
- goto recv_data;
+ /* Allocate an skb */
+ skb = rx_alloc_skb(frm->len, iod, ld);
+ if (!skb) {
+ mif_err("%s->%s: ERR! rx_alloc_skb fail (size %d)\n",
+ ld->name, iod->name, frm->len);
+ return NULL;
}
-next_frame:
- /* Receive and analyze header, then prepare an akb */
- err = done = rx_header_from_serial(iod, ld, buff, rest, frm);
- if (err < 0)
- goto err_exit;
-
- buff += done;
- rest -= done;
- mif_debug("%s: rx_header() -> done:%d rest:%d\n", link, done, rest);
- if (rest < 0)
- goto err_range;
+ /* Calculates the payload size */
+ frm->pay_len = frm->len - frm->hdr_len;
- if (rest == 0)
- return size;
+ /* Calculates the padding size */
+ if (sipc5_padding_exist(frm->hdr))
+ frm->pad_len = sipc5_calc_padding_size(frm->len);
-recv_data:
- err = 0;
+ mif_debug("%s->%s: size %d (header:%d payload:%d padding:%d)\n",
+ ld->name, iod->name, frm->len, frm->hdr_len, frm->pay_len,
+ frm->pad_len);
- mif_debug("%s: done:%d rest:%d -> rx_payload()\n", link, done, rest);
-
- done = rx_payload_from_serial(iod, ld, buff, rest, frm);
- buff += done;
- rest -= done;
+ return skb;
+}
- mif_debug("%s: rx_payload() -> done:%d rest:%d\n", link, done, rest);
+/**
+ * rx_frame_header
+ * @iod: pointer to an instance of io_device structure
+ * @ld: pointer to an instance of link_device structure
+ * @buff: pointer to a buffer in which incoming data is stored
+ * @size: size of data in the buffer
+ * @frm: pointer to an instance of sipc5_frame_data structure
+ *
+ * 1) Stores a link layer header to "frm->hdr" temporarily while "frm->hdr_rcvd"
+ * is less than "frm->hdr_len"
+ * 2) Then,
+ * Allocates an skb
+ * Copies the link header from "frm" to "skb"
+ * Register the skb to receive payload
+ *
+ * Returns the size of a segment that was copied to "frm"
+ */
+static int rx_frame_header(struct io_device *iod, struct link_device *ld,
+ u8 *buff, int size, struct sipc5_frame_data *frm)
+{
+ struct sk_buff *skb;
+ int rest;
+ int rcvd;
- if (rest == 0 && frm->data_rcvd < frm->data_len) {
- /*
- Data is being received and more data will come within the next
- frame from the link device.
- */
- return size;
- }
+ /* Calculate the size of a segment that will be copied */
+ rest = frm->hdr_len - frm->hdr_rcvd;
+ rcvd = min(rest, size);
+ mif_debug("%s->%s: hdr_len:%d hdr_rcvd:%d rest:%d size:%d rcvd:%d\n",
+ ld->name, iod->name, frm->hdr_len, frm->hdr_rcvd, rest, size,
+ rcvd);
- /* At this point, one complete link layer frame has been received. */
+ /* Copy a segment of an SIPC5 link header to "frm" */
+ memcpy((frm->hdr + frm->hdr_rcvd), buff, rcvd);
+ frm->hdr_rcvd += rcvd;
- /* A padding size is applied to access the next IPC frame. */
- if (frm->padding) {
- done = sipc5_calc_padding_size(frm->len);
- if (done > rest) {
- mif_info("%s: ERR! padding %d > rest %d\n",
- link, done, rest);
- goto err_exit;
+ if (frm->hdr_rcvd >= frm->hdr_len) {
+ /* Prepare an skb with the information in {iod, ld, frm} */
+ skb = rx_frame_prepare_skb(iod, ld, frm);
+ if (!skb) {
+ mif_err("%s->%s: ERR! rx_frame_prepare_skb fail\n",
+ ld->name, iod->name);
+ return -ENOMEM;
}
- buff += done;
- rest -= done;
-
- mif_debug("%s: padding:%d -> rest:%d\n", link, done, rest);
-
- if (rest < 0)
- goto err_range;
-
- }
-
- skb = fragdata(iod, ld)->skb_recv;
- if (likely(skb)) {
- mif_debug("%s: len:%d -> rx_demux()\n", link, skb->len);
- err = rx_demux(ld, skb);
- if (err < 0)
- dev_kfree_skb_any(skb);
- } else {
- mif_debug("%s: len:%d -> drop\n", link, skb->len);
- }
-
- /* initialize the skb_recv and the frame_data buffer */
- fragdata(iod, ld)->skb_recv = NULL;
- memset(frm, 0, sizeof(struct sipc5_frame_data));
+ /* Copy an SIPC5 link header from "frm" to "skb" */
+ memcpy(skb_put(skb, frm->hdr_len), frm->hdr, frm->hdr_len);
- if (rest > 0)
- goto next_frame;
-
- if (rest <= 0)
- return size;
-
-err_exit:
- if (fragdata(iod, ld)->skb_recv &&
- frm->hdr_rcvd >= frm->hdr_len && frm->data_rcvd >= frm->data_len) {
- dev_kfree_skb_any(fragdata(iod, ld)->skb_recv);
- memset(frm, 0, sizeof(struct sipc5_frame_data));
- fragdata(iod, ld)->skb_recv = NULL;
- mif_info("%s: ERR! clear frag\n", link);
+ /* Register the skb to receive payload */
+ fragdata(iod, ld)->skb_recv = skb;
}
- return err;
-err_range:
- mif_info("%s: ERR! size:%d vs. rest:%d\n", link, size, rest);
- return size;
+ return rcvd;
}
/**
- * rx_header_from_mem
- * @ld: pointer to the link device
- * @buff: pointer to the frame
- * @rest: size of the frame
- * @frm: pointer to the sipc5_frame_data buffer
+ * rx_frame_payload
+ * @iod: pointer to an instance of io_device structure
+ * @ld: pointer to an instance of link_device structure
+ * @buff: pointer to a buffer in which incoming data is stored
+ * @size: size of data in the buffer
+ * @frm: pointer to an instance of sipc5_frame_data structure
*
- * 1) Verifies a link layer header configuration of a frame
- * 2) Stores the link layer header to the header buffer
- * 3) Builds and stores the meta data of the frame into a meta data buffer
- * 4) Verifies the length of the frame
+ * Stores a link layer payload to "skb"
*
- * Returns SIPC5 header length
+ * Returns the size of a segment that was copied to "skb"
*/
-static int rx_header_from_mem(struct link_device *ld, u8 *buff, unsigned rest,
- struct sipc5_frame_data *frm)
+static int rx_frame_payload(struct io_device *iod, struct link_device *ld,
+ u8 *buff, int size, struct sipc5_frame_data *frm)
{
- char *link = ld->name;
- u8 cfg = buff[0];
+ struct sk_buff *skb = fragdata(iod, ld)->skb_recv;
+ int rest;
+ int rcvd;
- /* Verify link layer header configuration */
- if (unlikely(!sipc5_start_valid(cfg))) {
- mif_info("%s: ERR! wrong start (0x%02x)\n", link, cfg);
- return -EBADMSG;
- }
- rx_check_frame_cfg(cfg, frm);
+ /* Calculate the size of a segment that will be copied */
+ rest = frm->pay_len - frm->pay_rcvd;
+ rcvd = min(rest, size);
+ mif_debug("%s->%s: pay_len:%d pay_rcvd:%d rest:%d size:%d rcvd:%d\n",
+ ld->name, iod->name, frm->pay_len, frm->pay_rcvd, rest, size,
+ rcvd);
- /* Store the link layer header to the header buffer */
- memcpy(frm->hdr, buff, frm->hdr_len);
- frm->hdr_rcvd = frm->hdr_len;
+ /* Copy an SIPC5 link payload to "skb" */
+ memcpy(skb_put(skb, rcvd), buff, rcvd);
+ frm->pay_rcvd += rcvd;
- /* Build and store the meta data of this frame */
- rx_build_meta_data(ld, frm);
+ return rcvd;
+}
- /* Verify frame length */
- if (unlikely(frm->len > rest)) {
- mif_info("%s: ERR! frame length %d > rest %d\n",
- link, frm->len, rest);
- return -EBADMSG;
- }
+static int rx_frame_padding(struct io_device *iod, struct link_device *ld,
+ u8 *buff, int size, struct sipc5_frame_data *frm)
+{
+ struct sk_buff *skb = fragdata(iod, ld)->skb_recv;
+ int rest;
+ int rcvd;
+
+ /* Calculate the size of a segment that will be dropped as padding */
+ rest = frm->pad_len - frm->pad_rcvd;
+ rcvd = min(rest, size);
+ mif_debug("%s->%s: pad_len:%d pad_rcvd:%d rest:%d size:%d rcvd:%d\n",
+ ld->name, iod->name, frm->pad_len, frm->pad_rcvd, rest, size,
+ rcvd);
- return frm->hdr_rcvd;
+ /* Copy an SIPC5 link padding to "skb" */
+ memcpy(skb_put(skb, rcvd), buff, rcvd);
+ frm->pad_rcvd += rcvd;
+
+ return rcvd;
}
-/* copy data to skb */
-static int rx_payload_from_mem(struct sk_buff *skb, u8 *buff, unsigned len)
+static int rx_frame_done(struct io_device *iod, struct link_device *ld,
+ struct sk_buff *skb)
{
- /* If there is no skb, data must be dropped. */
- if (skb)
- memcpy(skb_put(skb, len), buff, len);
- return len;
+ /* Cut off the padding of the current frame */
+ skb_trim(skb, sipc5_get_frame_len(skb->data));
+ mif_debug("%s->%s: frame length = %d\n", ld->name, iod->name, skb->len);
+
+ return rx_demux(ld, skb);
}
-static int rx_frame_from_mem(struct io_device *iod, struct link_device *ld,
+static int recv_frame_from_buff(struct io_device *iod, struct link_device *ld,
const char *data, unsigned size)
{
struct sipc5_frame_data *frm = &fragdata(iod, ld)->f_data;
struct sk_buff *skb;
- char *link = ld->name;
u8 *buff = (u8 *)data;
int rest = (int)size;
- int len;
- int done;
+ int done = 0;
+ int err = 0;
- mif_debug("%s: size = %d\n", link, size);
+ mif_debug("%s->%s: size %d (RX state = %s)\n", ld->name, iod->name,
+ size, get_rx_state_str(iod->curr_rx_state));
while (rest > 0) {
- /* Initialize the frame data buffer */
- memset(frm, 0, sizeof(struct sipc5_frame_data));
- skb = NULL;
+ switch (iod->curr_rx_state) {
+ case IOD_RX_ON_STANDBY:
+ fragdata(iod, ld)->skb_recv = NULL;
+ memset(frm, 0, sizeof(struct sipc5_frame_data));
+
+ done = rx_frame_config(iod, ld, buff, rest, frm);
+ if (done < 0) {
+ err = done;
+ goto err_exit;
+ }
- /* Receive and analyze link layer header */
- done = rx_header_from_mem(ld, buff, rest, frm);
- if (unlikely(done < 0))
- return -EBADMSG;
+ iod->next_rx_state = IOD_RX_HEADER;
- /* Verify rest size */
- rest -= done;
- if (rest < 0) {
- mif_info("%s: ERR! rx_header -> rest %d\n", link, rest);
- return -ERANGE;
- }
+ break;
- /* Move buff pointer to the payload */
- buff += done;
+ case IOD_RX_HEADER:
+ done = rx_frame_header(iod, ld, buff, rest, frm);
+ if (done < 0) {
+ err = done;
+ goto err_exit;
+ }
- /* Prepare an akb */
- len = frm->data_len;
- skb = rx_alloc_skb(len, iod, ld);
+ if (frm->hdr_rcvd >= frm->hdr_len)
+ iod->next_rx_state = IOD_RX_PAYLOAD;
+ else
+ iod->next_rx_state = IOD_RX_HEADER;
- /* Store channel ID and control fields to the CB of the skb */
- skbpriv(skb)->ch_id = frm->ch_id;
- skbpriv(skb)->control = frm->control;
+ break;
- /* Receive payload */
- mif_debug("%s: done:%d rest:%d len:%d -> rx_payload()\n",
- link, done, rest, len);
- done = rx_payload_from_mem(skb, buff, len);
- rest -= done;
- if (rest < 0) {
- mif_info("%s: ERR! rx_payload() -> rest %d\n",
- link, rest);
- if (skb)
- dev_kfree_skb_any(skb);
- return -ERANGE;
- }
- buff += done;
+ case IOD_RX_PAYLOAD:
+ done = rx_frame_payload(iod, ld, buff, rest, frm);
+ if (done < 0) {
+ err = done;
+ goto err_exit;
+ }
- /* A padding size is applied to access the next IPC frame. */
- if (frm->padding) {
- done = sipc5_calc_padding_size(frm->len);
- if (done > rest) {
- mif_info("%s: ERR! padding %d > rest %d\n",
- link, done, rest);
- if (skb)
- dev_kfree_skb_any(skb);
- return -ERANGE;
+ if (frm->pay_rcvd >= frm->pay_len) {
+ if (frm->pad_len > 0)
+ iod->next_rx_state = IOD_RX_PADDING;
+ else
+ iod->next_rx_state = IOD_RX_ON_STANDBY;
+ } else {
+ iod->next_rx_state = IOD_RX_PAYLOAD;
}
- buff += done;
- rest -= done;
+
+ break;
+
+ case IOD_RX_PADDING:
+ done = rx_frame_padding(iod, ld, buff, rest, frm);
+ if (done < 0) {
+ err = done;
+ goto err_exit;
+ }
+
+ if (frm->pad_rcvd >= frm->pad_len)
+ iod->next_rx_state = IOD_RX_ON_STANDBY;
+ else
+ iod->next_rx_state = IOD_RX_PADDING;
+
+ break;
+
+ default:
+ mif_err("%s->%s: ERR! INVALID RX state %d\n",
+ ld->name, iod->name, iod->curr_rx_state);
+ err = -EINVAL;
+ goto err_exit;
}
- if (likely(skb)) {
- mif_debug("%s: len:%d -> rx_demux()\n", link, skb->len);
- if (rx_demux(ld, skb) < 0)
- dev_kfree_skb_any(skb);
- } else {
- mif_debug("%s: len:%d -> drop\n", link, skb->len);
+ if (iod->next_rx_state == IOD_RX_ON_STANDBY) {
+ /*
+ ** A complete frame is in fragdata(iod, ld)->skb_recv.
+ */
+ skb = fragdata(iod, ld)->skb_recv;
+ err = rx_frame_done(iod, ld, skb);
+ if (err < 0)
+ goto err_exit;
}
+
+ buff += done;
+ rest -= done;
+ if (rest < 0)
+ goto err_range;
+
+ iod->curr_rx_state = iod->next_rx_state;
}
- return 0;
+ return size;
+
+err_exit:
+ if (fragdata(iod, ld)->skb_recv) {
+ mif_err("%s->%s: ERR! clear frag (size:%d done:%d rest:%d)\n",
+ ld->name, iod->name, size, done, rest);
+ dev_kfree_skb_any(fragdata(iod, ld)->skb_recv);
+ fragdata(iod, ld)->skb_recv = NULL;
+ }
+ iod->curr_rx_state = IOD_RX_ON_STANDBY;
+ return err;
+
+err_range:
+ mif_err("%s->%s: ERR! size:%d done:%d rest:%d\n",
+ ld->name, iod->name, size, done, rest);
+ iod->curr_rx_state = IOD_RX_ON_STANDBY;
+ return size;
}
/* called from link device when a packet arrives for this io device */
static int io_dev_recv_data_from_link_dev(struct io_device *iod,
struct link_device *ld, const char *data, unsigned int len)
{
- struct sk_buff_head *rxq = &iod->sk_rx_q;
struct sk_buff *skb;
- char *link = ld->name;
int err;
- if (!data) {
- mif_info("%s: ERR! !data\n", link);
- return -EINVAL;
- }
-
- if (len <= 0) {
- mif_info("%s: ERR! len %d <= 0\n", link, len);
- return -EINVAL;
- }
-
switch (iod->format) {
case IPC_FMT:
case IPC_RAW:
@@ -857,97 +738,151 @@ static int io_dev_recv_data_from_link_dev(struct io_device *iod,
if (iod->waketime)
wake_lock_timeout(&iod->wakelock, iod->waketime);
- if (ld->link_type == LINKDEV_DPRAM && ld->aligned)
- err = rx_frame_from_mem(iod, ld, data, len);
- else
- err = rx_frame_from_serial(iod, ld, data, len);
-
- if (err < 0)
- mif_info("%s: ERR! rx_frame_from_link fail (err %d)\n",
- link, err);
+ err = recv_frame_from_buff(iod, ld, data, len);
+ if (err < 0) {
+ mif_err("%s->%s: ERR! recv_frame_from_buff fail "
+ "(err %d)\n", ld->name, iod->name, err);
+ }
return err;
- case IPC_CMD:
- case IPC_BOOT:
- case IPC_RAMDUMP:
+ default:
+ mif_debug("%s->%s: len %d\n", ld->name, iod->name, len);
+
/* save packet to sk_buff */
skb = rx_alloc_skb(len, iod, ld);
if (!skb) {
- mif_info("%s: ERR! rx_alloc_skb fail\n", link);
+ mif_info("%s->%s: ERR! rx_alloc_skb fail\n",
+ ld->name, iod->name);
return -ENOMEM;
}
- mif_debug("%s: len:%d -> iod:%s\n", link, len, iod->name);
-
memcpy(skb_put(skb, len), data, len);
- skb_queue_tail(rxq, skb);
- if (unlikely(rxq->qlen > 2048)) {
- struct sk_buff *victim;
- mif_info("%s: ERR! rxq->qlen %d > 2048\n",
- iod->name, rxq->qlen);
- victim = skb_dequeue(rxq);
- dev_kfree_skb_any(victim);
- }
+
+ queue_skb_to_iod(skb, iod);
+
wake_up(&iod->wq);
return len;
-
- default:
- mif_info("%s: ERR! unknown format %d\n", link, iod->format);
- return -EINVAL;
}
}
-static int rx_frame_from_skb(struct io_device *iod, struct link_device *ld,
+static int recv_frame_from_skb(struct io_device *iod, struct link_device *ld,
struct sk_buff *skb)
{
- struct sipc5_frame_data *frm = &fragdata(iod, ld)->f_data;
- u8 cfg = skb->data[0];
+ struct sk_buff *clone;
+ unsigned int rest;
+ unsigned int rcvd;
+ int tot; /* total length including padding */
+ int err = 0;
- /* Initialize the frame data buffer */
- memset(frm, 0, sizeof(struct sipc5_frame_data));
+ /*
+ ** If there is only one SIPC5 frame in @skb, receive the SIPC5 frame and
+ ** return immediately. In this case, the frame verification must already
+ ** have been done at the link device.
+ */
+ if (skbpriv(skb)->single_frame) {
+ err = rx_frame_done(iod, ld, skb);
+ if (err < 0)
+ goto exit;
+ return 0;
+ }
/*
- ** The start of a link layer header has already been checked in the
- ** link device.
+ ** The routine from here is used only if there may be multiple SIPC5
+ ** frames in @skb.
*/
- /* Analyze the configuration of the link layer header */
- rx_check_frame_cfg(cfg, frm);
+ /* Check the config field of the first frame in @skb */
+ if (!sipc5_start_valid(skb->data)) {
+ mif_err("%s->%s: ERR! INVALID config 0x%02X\n",
+ ld->name, iod->name, skb->data[0]);
+ err = -EINVAL;
+ goto exit;
+ }
+
+ /* Get the total length of the frame with a padding */
+ tot = sipc5_get_total_len(skb->data);
- /* Store the link layer header to the header buffer */
- memcpy(frm->hdr, skb->data, frm->hdr_len);
- frm->hdr_rcvd = frm->hdr_len;
+ /* Verify the total length of the first frame */
+ rest = skb->len;
+ if (unlikely(tot > rest)) {
+ mif_err("%s->%s: ERR! tot %d > skb->len %d)\n",
+ ld->name, iod->name, tot, rest);
+ err = -EINVAL;
+ goto exit;
+ }
- /* Build and store the meta data of this frame */
- rx_build_meta_data(ld, frm);
+ /* If there is only one SIPC5 frame in @skb, */
+ if (likely(tot == rest)) {
+ /* Receive the SIPC5 frame and return immediately */
+ err = rx_frame_done(iod, ld, skb);
+ if (err < 0)
+ goto exit;
+ return 0;
+ }
/*
- ** The length of the frame has already been checked in the link device.
+ ** This routine is used only if there are multiple SIPC5 frames in @skb.
*/
+ rcvd = 0;
+ while (rest > 0) {
+ clone = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!clone)) {
+ mif_err("%s->%s: ERR! skb_clone fail\n",
+ ld->name, iod->name);
+ err = -ENOMEM;
+ goto exit;
+ }
- /* Trim the link layer header off the frame */
- skb_pull(skb, frm->hdr_len);
+ /* Get the start of an SIPC5 frame */
+ skb_pull(clone, rcvd);
+ if (!sipc5_start_valid(clone->data)) {
+ mif_err("%s->%s: ERR! INVALID config 0x%02X\n",
+ ld->name, iod->name, clone->data[0]);
+ dev_kfree_skb_any(clone);
+ err = -EINVAL;
+ goto exit;
+ }
- /* Store channel ID and control fields to the CB of the skb */
- skbpriv(skb)->ch_id = frm->ch_id;
- skbpriv(skb)->control = frm->control;
+ /* Get the total length of the current frame with a padding */
+ tot = sipc5_get_total_len(clone->data);
+ if (unlikely(tot > rest)) {
+ mif_err("%s->%s: ERR! dirty frame (tot %d > rest %d)\n",
+ ld->name, iod->name, tot, rest);
+ dev_kfree_skb_any(clone);
+ err = -EINVAL;
+ goto exit;
+ }
- /* Demux the frame */
- if (rx_demux(ld, skb) < 0) {
- mif_err("%s: ERR! rx_demux fail\n", ld->name);
- return -EINVAL;
+ /* Cut off the padding of the current frame */
+ skb_trim(clone, sipc5_get_frame_len(clone->data));
+
+ /* Demux the frame */
+ err = rx_demux(ld, clone);
+ if (err < 0) {
+ mif_err("%s->%s: ERR! rx_demux fail (err %d)\n",
+ ld->name, iod->name, err);
+ dev_kfree_skb_any(clone);
+ goto exit;
+ }
+
+ /* Calculate the start of the next frame */
+ rcvd += tot;
+
+ /* Calculate the rest size of data in @skb */
+ rest -= tot;
}
- return 0;
+exit:
+ dev_kfree_skb_any(skb);
+ return err;
}
/* called from link device when a packet arrives for this io device */
static int io_dev_recv_skb_from_link_dev(struct io_device *iod,
struct link_device *ld, struct sk_buff *skb)
{
- char *link = ld->name;
enum dev_format dev = iod->format;
int err;
@@ -959,17 +894,35 @@ static int io_dev_recv_skb_from_link_dev(struct io_device *iod,
if (iod->waketime)
wake_lock_timeout(&iod->wakelock, iod->waketime);
- err = rx_frame_from_skb(iod, ld, skb);
+ err = recv_frame_from_skb(iod, ld, skb);
if (err < 0) {
- dev_kfree_skb_any(skb);
- mif_info("%s: ERR! rx_frame_from_skb fail (err %d)\n",
- link, err);
+ mif_err("%s->%s: ERR! recv_frame_from_skb fail "
+ "(err %d)\n", ld->name, iod->name, err);
+ }
+
+ return err;
+
+ case IPC_BOOT:
+ case IPC_RAMDUMP:
+ if (!iod->id) {
+ mif_err("%s->%s: ERR! invalid iod\n",
+ ld->name, iod->name);
+ return -ENODEV;
+ }
+
+ if (iod->waketime)
+ wake_lock_timeout(&iod->wakelock, iod->waketime);
+
+ err = recv_frame_from_skb(iod, ld, skb);
+ if (err < 0) {
+ mif_err("%s->%s: ERR! recv_frame_from_skb fail "
+ "(err %d)\n", ld->name, iod->name, err);
}
return err;
default:
- mif_info("%s: ERR! unknown device %d\n", link, dev);
+ mif_err("%s->%s: ERR! invalid iod\n", ld->name, iod->name);
return -EINVAL;
}
}
@@ -980,10 +933,14 @@ static int io_dev_recv_skb_from_link_dev(struct io_device *iod,
static void io_dev_modem_state_changed(struct io_device *iod,
enum modem_state state)
{
- mif_info("%s: %s state changed (state %d)\n",
- iod->name, iod->mc->name, state);
+ struct modem_ctl *mc = iod->mc;
+ int old_state = mc->phone_state;
- iod->mc->phone_state = state;
+ if (old_state != state) {
+ mc->phone_state = state;
+ mif_err("%s state changed (%s -> %s)\n", mc->name,
+ get_cp_state_str(old_state), get_cp_state_str(state));
+ }
if (state == STATE_CRASH_RESET || state == STATE_CRASH_EXIT ||
state == STATE_NV_REBUILDING)
@@ -1024,23 +981,27 @@ static int misc_open(struct inode *inode, struct file *filp)
struct io_device *iod = to_io_device(filp->private_data);
struct modem_shared *msd = iod->msd;
struct link_device *ld;
+ int ref_cnt;
int ret;
filp->private_data = (void *)iod;
- atomic_inc(&iod->opened);
-
list_for_each_entry(ld, &msd->link_dev_list, list) {
if (IS_CONNECTED(iod, ld) && ld->init_comm) {
ret = ld->init_comm(ld, iod);
if (ret < 0) {
- mif_info("%s: init_comm fail(%d)\n",
- ld->name, ret);
+ mif_err("%s<->%s: ERR! init_comm fail(%d)\n",
+ iod->name, ld->name, ret);
return ret;
}
}
}
- mif_err("%s (opened %d)\n", iod->name, atomic_read(&iod->opened));
+ ref_cnt = atomic_inc_return(&iod->opened);
+
+ if (iod->format == IPC_BOOT || iod->format == IPC_RAMDUMP)
+ mif_err("%s (opened %d)\n", iod->name, ref_cnt);
+ else
+ mif_info("%s (opened %d)\n", iod->name, ref_cnt);
return 0;
}
@@ -1050,8 +1011,8 @@ static int misc_release(struct inode *inode, struct file *filp)
struct io_device *iod = (struct io_device *)filp->private_data;
struct modem_shared *msd = iod->msd;
struct link_device *ld;
+ int ref_cnt;
- atomic_dec(&iod->opened);
skb_queue_purge(&iod->sk_rx_q);
list_for_each_entry(ld, &msd->link_dev_list, list) {
@@ -1059,7 +1020,12 @@ static int misc_release(struct inode *inode, struct file *filp)
ld->terminate_comm(ld, iod);
}
- mif_err("%s (opened %d)\n", iod->name, atomic_read(&iod->opened));
+ ref_cnt = atomic_dec_return(&iod->opened);
+
+ if (iod->format == IPC_BOOT || iod->format == IPC_RAMDUMP)
+ mif_err("%s (opened %d)\n", iod->name, ref_cnt);
+ else
+ mif_info("%s (opened %d)\n", iod->name, ref_cnt);
return 0;
}
@@ -1067,20 +1033,23 @@ static int misc_release(struct inode *inode, struct file *filp)
static unsigned int misc_poll(struct file *filp, struct poll_table_struct *wait)
{
struct io_device *iod = (struct io_device *)filp->private_data;
+ struct modem_ctl *mc = iod->mc;
poll_wait(filp, &iod->wq, wait);
- if (!skb_queue_empty(&iod->sk_rx_q) &&
- iod->mc->phone_state != STATE_OFFLINE) {
+ if (!skb_queue_empty(&iod->sk_rx_q) && mc->phone_state != STATE_OFFLINE)
return POLLIN | POLLRDNORM;
- } else if ((iod->mc->phone_state == STATE_CRASH_RESET) ||
- (iod->mc->phone_state == STATE_CRASH_EXIT) ||
- (iod->mc->phone_state == STATE_NV_REBUILDING) ||
- (iod->mc->sim_state.changed)) {
+
+ if (mc->phone_state == STATE_CRASH_RESET
+ || mc->phone_state == STATE_CRASH_EXIT
+ || mc->phone_state == STATE_NV_REBUILDING
+ || mc->sim_state.changed) {
if (iod->format == IPC_RAW) {
msleep(20);
return 0;
}
+ if (iod->format == IPC_RAMDUMP)
+ return 0;
return POLLHUP;
} else {
return 0;
@@ -1089,132 +1058,191 @@ static unsigned int misc_poll(struct file *filp, struct poll_table_struct *wait)
static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- int p_state;
struct io_device *iod = (struct io_device *)filp->private_data;
struct link_device *ld = get_current_link(iod);
- char cpinfo_buf[530] = "CP Crash ";
+ struct modem_ctl *mc = iod->mc;
+ int p_state;
+ char *buff;
+ void __user *user_buff;
unsigned long size;
- int ret;
switch (cmd) {
case IOCTL_MODEM_ON:
- mif_info("%s: IOCTL_MODEM_ON\n", iod->name);
- return iod->mc->ops.modem_on(iod->mc);
+ if (mc->ops.modem_on) {
+ mif_err("%s: IOCTL_MODEM_ON\n", iod->name);
+ return mc->ops.modem_on(mc);
+ }
+ mif_err("%s: !mc->ops.modem_on\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_OFF:
- mif_info("%s: IOCTL_MODEM_OFF\n", iod->name);
- return iod->mc->ops.modem_off(iod->mc);
+ if (mc->ops.modem_off) {
+ mif_err("%s: IOCTL_MODEM_OFF\n", iod->name);
+ return mc->ops.modem_off(mc);
+ }
+ mif_err("%s: !mc->ops.modem_off\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_RESET:
- mif_info("%s: IOCTL_MODEM_RESET\n", iod->name);
- return iod->mc->ops.modem_reset(iod->mc);
+ if (mc->ops.modem_reset) {
+ mif_err("%s: IOCTL_MODEM_RESET\n", iod->name);
+ return mc->ops.modem_reset(mc);
+ }
+ mif_err("%s: !mc->ops.modem_reset\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_BOOT_ON:
- mif_info("%s: IOCTL_MODEM_BOOT_ON\n", iod->name);
- return iod->mc->ops.modem_boot_on(iod->mc);
+ if (mc->ops.modem_boot_on) {
+ mif_err("%s: IOCTL_MODEM_BOOT_ON\n", iod->name);
+ return mc->ops.modem_boot_on(mc);
+ }
+ mif_err("%s: !mc->ops.modem_boot_on\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_BOOT_OFF:
- mif_info("%s: IOCTL_MODEM_BOOT_OFF\n", iod->name);
- return iod->mc->ops.modem_boot_off(iod->mc);
+ if (mc->ops.modem_boot_off) {
+ mif_err("%s: IOCTL_MODEM_BOOT_OFF\n", iod->name);
+ return mc->ops.modem_boot_off(mc);
+ }
+ mif_err("%s: !mc->ops.modem_boot_off\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_BOOT_DONE:
mif_err("%s: IOCTL_MODEM_BOOT_DONE\n", iod->name);
- if (iod->mc->ops.modem_boot_done)
- return iod->mc->ops.modem_boot_done(iod->mc);
- else
- return 0;
+ if (mc->ops.modem_boot_done)
+ return mc->ops.modem_boot_done(mc);
+ return 0;
case IOCTL_MODEM_STATUS:
mif_debug("%s: IOCTL_MODEM_STATUS\n", iod->name);
- p_state = iod->mc->phone_state;
+ p_state = mc->phone_state;
if ((p_state == STATE_CRASH_RESET) ||
(p_state == STATE_CRASH_EXIT)) {
- mif_info("%s: IOCTL_MODEM_STATUS (state %d)\n",
- iod->name, p_state);
- } else if (iod->mc->sim_state.changed) {
- int s_state = iod->mc->sim_state.online ?
+ mif_info("%s: IOCTL_MODEM_STATUS (state %s)\n",
+ iod->name, get_cp_state_str(p_state));
+ } else if (mc->sim_state.changed) {
+ int s_state = mc->sim_state.online ?
STATE_SIM_ATTACH : STATE_SIM_DETACH;
- iod->mc->sim_state.changed = false;
+ mc->sim_state.changed = false;
return s_state;
} else if (p_state == STATE_NV_REBUILDING) {
- mif_info("%s: IOCTL_MODEM_STATUS (state %d)\n",
- iod->name, p_state);
- iod->mc->phone_state = STATE_ONLINE;
+ mif_info("%s: IOCTL_MODEM_STATUS (state %s)\n",
+ iod->name, get_cp_state_str(p_state));
+ mc->phone_state = STATE_ONLINE;
}
return p_state;
- case IOCTL_MODEM_PROTOCOL_SUSPEND:
- mif_debug("%s: IOCTL_MODEM_PROTOCOL_SUSPEND\n",
- iod->name);
-
- if (iod->format != IPC_MULTI_RAW)
- return -EINVAL;
+ case IOCTL_MODEM_XMIT_BOOT:
+ if (ld->xmit_boot) {
+ mif_info("%s: IOCTL_MODEM_XMIT_BOOT\n", iod->name);
+ return ld->xmit_boot(ld, iod, arg);
+ }
+ mif_err("%s: !ld->xmit_boot\n", iod->name);
+ return -EINVAL;
- iodevs_for_each(iod->msd, iodev_netif_stop, 0);
- return 0;
+ case IOCTL_MODEM_DL_START:
+ if (ld->dload_start) {
+ mif_info("%s: IOCTL_MODEM_DL_START\n", iod->name);
+ return ld->dload_start(ld, iod);
+ }
+ mif_err("%s: !ld->dload_start\n", iod->name);
+ return -EINVAL;
- case IOCTL_MODEM_PROTOCOL_RESUME:
- mif_info("%s: IOCTL_MODEM_PROTOCOL_RESUME\n",
- iod->name);
+ case IOCTL_MODEM_FW_UPDATE:
+ if (ld->firm_update) {
+ mif_info("%s: IOCTL_MODEM_FW_UPDATE\n", iod->name);
+ return ld->firm_update(ld, iod, arg);
+ }
+ mif_err("%s: !ld->firm_update\n", iod->name);
+ return -EINVAL;
- if (iod->format != IPC_MULTI_RAW)
- return -EINVAL;
+ case IOCTL_MODEM_FORCE_CRASH_EXIT:
+ if (mc->ops.modem_force_crash_exit) {
+ mif_err("%s: IOCTL_MODEM_FORCE_CRASH_EXIT\n",
+ iod->name);
+ return mc->ops.modem_force_crash_exit(mc);
+ }
+ mif_err("%s: !mc->ops.modem_force_crash_exit\n", iod->name);
+ return -EINVAL;
- iodevs_for_each(iod->msd, iodev_netif_wake, 0);
- return 0;
+ case IOCTL_MODEM_DUMP_RESET:
+ if (mc->ops.modem_dump_reset) {
+ mif_info("%s: IOCTL_MODEM_DUMP_RESET\n", iod->name);
+ return mc->ops.modem_dump_reset(mc);
+ }
+ mif_err("%s: !mc->ops.modem_dump_reset\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_DUMP_START:
- mif_info("%s: IOCTL_MODEM_DUMP_START\n", iod->name);
- return ld->dump_start(ld, iod);
+ if (ld->dump_start) {
+ mif_err("%s: IOCTL_MODEM_DUMP_START\n", iod->name);
+ return ld->dump_start(ld, iod);
+ }
+ mif_err("%s: !ld->dump_start\n", iod->name);
+ return -EINVAL;
+
+ case IOCTL_MODEM_RAMDUMP_START:
+ if (ld->dump_start) {
+ mif_info("%s: IOCTL_MODEM_RAMDUMP_START\n", iod->name);
+ return ld->dump_start(ld, iod);
+ }
+ mif_err("%s: !ld->dump_start\n", iod->name);
+ return -EINVAL;
case IOCTL_MODEM_DUMP_UPDATE:
- mif_debug("%s: IOCTL_MODEM_DUMP_UPDATE\n", iod->name);
- return ld->dump_update(ld, iod, arg);
+ if (ld->dump_update) {
+ mif_info("%s: IOCTL_MODEM_DUMP_UPDATE\n", iod->name);
+ return ld->dump_update(ld, iod, arg);
+ }
+ mif_err("%s: !ld->dump_update\n", iod->name);
+ return -EINVAL;
- case IOCTL_MODEM_FORCE_CRASH_EXIT:
- mif_info("%s: IOCTL_MODEM_FORCE_CRASH_EXIT\n", iod->name);
- if (iod->mc->ops.modem_force_crash_exit)
- return iod->mc->ops.modem_force_crash_exit(iod->mc);
+ case IOCTL_MODEM_RAMDUMP_STOP:
+ if (ld->dump_finish) {
+ mif_info("%s: IOCTL_MODEM_RAMDUMP_STOP\n", iod->name);
+ return ld->dump_finish(ld, iod, arg);
+ }
+ mif_err("%s: !ld->dump_finish\n", iod->name);
return -EINVAL;
case IOCTL_MODEM_CP_UPLOAD:
mif_info("%s: IOCTL_MODEM_CP_UPLOAD\n", iod->name);
- if (copy_from_user(cpinfo_buf + strlen(cpinfo_buf),
- (void __user *)arg, MAX_CPINFO_SIZE) != 0)
- return -EFAULT;
- panic(cpinfo_buf);
+ strcpy(iod->msd->cp_crash_info, CP_CRASH_TAG);
+ if (arg) {
+ buff = iod->msd->cp_crash_info + strlen(CP_CRASH_TAG);
+ user_buff = (void __user *)arg;
+ if (copy_from_user(buff, user_buff, MAX_CPINFO_SIZE))
+ return -EFAULT;
+ }
+ panic(iod->msd->cp_crash_info);
return 0;
- case IOCTL_MODEM_DUMP_RESET:
- mif_info("%s: IOCTL_MODEM_DUMP_RESET\n", iod->name);
- return iod->mc->ops.modem_dump_reset(iod->mc);
+ case IOCTL_MODEM_PROTOCOL_SUSPEND:
+ mif_info("%s: IOCTL_MODEM_PROTOCOL_SUSPEND\n", iod->name);
+ if (iod->format == IPC_MULTI_RAW) {
+ iodevs_for_each(iod->msd, iodev_netif_stop, 0);
+ return 0;
+ }
+ return -EINVAL;
+
+ case IOCTL_MODEM_PROTOCOL_RESUME:
+ mif_info("%s: IOCTL_MODEM_PROTOCOL_RESUME\n", iod->name);
+ if (iod->format != IPC_MULTI_RAW) {
+ iodevs_for_each(iod->msd, iodev_netif_wake, 0);
+ return 0;
+ }
+ return -EINVAL;
case IOCTL_MIF_LOG_DUMP:
iodevs_for_each(iod->msd, iodev_dump_status, 0);
+ user_buff = (void __user *)arg;
size = MAX_MIF_BUFF_SIZE;
- ret = copy_to_user((void __user *)arg, &size,
- sizeof(unsigned long));
- if (ret < 0)
+ if (copy_to_user(user_buff, &size, sizeof(unsigned long)))
return -EFAULT;
-
- mif_dump_log(iod->mc->msd, iod);
+ mif_dump_log(mc->msd, iod);
return 0;
- case IOCTL_MIF_DPRAM_DUMP:
-#ifdef CONFIG_LINK_DEVICE_DPRAM
- if (iod->mc->mdm_data->link_types & LINKTYPE(LINKDEV_DPRAM)) {
- size = iod->mc->mdm_data->dpram_ctl->dp_size;
- ret = copy_to_user((void __user *)arg, &size,
- sizeof(unsigned long));
- if (ret < 0)
- return -EFAULT;
- mif_dump_dpram(iod);
- return 0;
- }
-#endif
- return -EINVAL;
-
default:
/* If you need to handle the ioctl for specific link device,
* then assign the link ioctl handler to ld->ioctl
@@ -1222,9 +1250,10 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (ld->ioctl)
return ld->ioctl(ld, iod, cmd, arg);
- mif_info("%s: ERR! cmd 0x%X not defined.\n", iod->name, cmd);
+ mif_info("%s: ERR! undefined cmd 0x%X\n", iod->name, cmd);
return -EINVAL;
}
+
return 0;
}
@@ -1234,49 +1263,76 @@ static ssize_t misc_write(struct file *filp, const char __user *data,
struct io_device *iod = (struct io_device *)filp->private_data;
struct link_device *ld = get_current_link(iod);
struct sk_buff *skb;
+ u8 *buff;
int ret;
- unsigned headroom = 0;
- unsigned tailroom = 0;
- size_t tx_size;
- struct sipc5_frame_data frm;
- struct timespec epoch;
+ size_t headroom;
+ size_t tailroom;
+ size_t tx_bytes;
+ u8 cfg;
if (iod->format <= IPC_RFS && iod->id == 0)
return -EINVAL;
- headroom = tx_build_link_header(&frm, iod, ld, count);
+ cfg = sipc5_build_config(iod, ld, count);
+
+ if (cfg)
+ headroom = sipc5_get_hdr_len(&cfg);
+ else
+ headroom = 0;
if (ld->aligned)
tailroom = sipc5_calc_padding_size(headroom + count);
+ else
+ tailroom = 0;
- tx_size = headroom + count + tailroom;
+ tx_bytes = headroom + count + tailroom;
- skb = alloc_skb(tx_size, GFP_KERNEL);
+ skb = alloc_skb(tx_bytes, GFP_KERNEL);
if (!skb) {
- mif_info("%s: ERR! alloc_skb fail (tx_size:%d)\n",
- iod->name, tx_size);
+ mif_info("%s: ERR! alloc_skb fail (tx_bytes:%d)\n",
+ iod->name, tx_bytes);
return -ENOMEM;
}
- /* store IPC link header*/
- memcpy(skb_put(skb, headroom), frm.hdr, headroom);
+ /* Build SIPC5 link header*/
+ if (cfg) {
+ buff = skb_put(skb, headroom);
+ sipc5_build_header(iod, ld, buff, cfg, 0, count);
+ }
- /* store IPC message */
- if (copy_from_user(skb_put(skb, count), data, count) != 0) {
- if (skb)
- dev_kfree_skb_any(skb);
+ /* Store IPC message */
+ buff = skb_put(skb, count);
+ if (copy_from_user(buff, data, count)) {
+ mif_err("%s->%s: ERR! copy_from_user fail (count %d)\n",
+ iod->name, ld->name, count);
+ dev_kfree_skb_any(skb);
return -EFAULT;
}
- if (iod->id == SIPC5_CH_ID_FMT_0) {
+ /* Apply padding */
+ if (tailroom)
+ skb_put(skb, tailroom);
+
+ if (iod->format == IPC_FMT) {
+ struct timespec epoch;
+ u8 *msg = (skb->data + headroom);
+#if 0
+ char tag[MIF_MAX_STR_LEN];
+ snprintf(tag, MIF_MAX_STR_LEN, "%s: RIL2MIF", iod->mc->name);
+ pr_ipc(1, tag, msg, (count > 20 ? 20 : count));
+#endif
getnstimeofday(&epoch);
mif_time_log(iod->mc->msd, epoch, NULL, 0);
- mif_ipc_log(MIF_IPC_RL2AP, iod->mc->msd, skb->data, skb->len);
+ mif_ipc_log(MIF_IPC_RL2AP, iod->mc->msd, msg, count);
}
- /* store padding */
- if (tailroom)
- skb_put(skb, tailroom);
+#if 0
+ if (iod->format == IPC_RAMDUMP) {
+ char tag[MIF_MAX_STR_LEN];
+ snprintf(tag, MIF_MAX_STR_LEN, "%s: DUMP2MIF", iod->name);
+ pr_ipc(1, tag, skb->data, (skb->len > 20 ? 20 : skb->len));
+ }
+#endif
/* send data with sk_buff, link device will put sk_buff
* into the specific sk_buff_q and run work-q to send data
@@ -1286,13 +1342,15 @@ static ssize_t misc_write(struct file *filp, const char __user *data,
ret = ld->send(ld, iod, skb);
if (ret < 0) {
- mif_info("%s: ERR! ld->send fail (err %d)\n", iod->name, ret);
+ mif_info("%s->%s: ERR! ld->send fail (err %d, tx_bytes %d)\n",
+ iod->name, ld->name, ret, tx_bytes);
return ret;
}
- if (ret != tx_size)
- mif_info("%s: wrong tx size (count:%d tx_size:%d ret:%d)\n",
- iod->name, count, tx_size, ret);
+ if (ret != tx_bytes) {
+ mif_info("%s->%s: WARNING! ret %d != tx_bytes %d (count %d)\n",
+ iod->name, ld->name, ret, tx_bytes, count);
+ }
return count;
}
@@ -1304,24 +1362,38 @@ static ssize_t misc_read(struct file *filp, char *buf, size_t count,
struct sk_buff_head *rxq = &iod->sk_rx_q;
struct sk_buff *skb;
int copied = 0;
- struct timespec epoch;
- skb = skb_dequeue(rxq);
- if (!skb) {
+ if (skb_queue_empty(rxq)) {
mif_info("%s: ERR! no data in rxq\n", iod->name);
return 0;
}
- if (iod->id == SIPC5_CH_ID_FMT_0) {
+ skb = skb_dequeue(rxq);
+
+ if (iod->format == IPC_FMT) {
+ struct timespec epoch;
+#if 0
+ char tag[MIF_MAX_STR_LEN];
+ snprintf(tag, MIF_MAX_STR_LEN, "%s: MIF2RIL", iod->mc->name);
+ pr_ipc(0, tag, skb->data, (skb->len > 20 ? 20 : skb->len));
+#endif
getnstimeofday(&epoch);
mif_time_log(iod->mc->msd, epoch, NULL, 0);
mif_ipc_log(MIF_IPC_AP2RL, iod->mc->msd, skb->data, skb->len);
}
+#if 0
+ if (iod->format == IPC_RAMDUMP) {
+ char tag[MIF_MAX_STR_LEN];
+ snprintf(tag, MIF_MAX_STR_LEN, "%s: MIF2DUMP", iod->name);
+ pr_ipc(1, tag, skb->data, (skb->len > 20 ? 20 : skb->len));
+ }
+#endif
+
copied = skb->len > count ? count : skb->len;
if (copy_to_user(buf, skb->data, copied)) {
- mif_info("%s: ERR! copy_to_user fail\n", iod->name);
+ mif_err("%s: ERR! copy_to_user fail\n", iod->name);
dev_kfree_skb_any(skb);
return -EFAULT;
}
@@ -1339,43 +1411,6 @@ static ssize_t misc_read(struct file *filp, char *buf, size_t count,
return copied;
}
-#ifdef CONFIG_LINK_DEVICE_C2C
-static int misc_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- int r = 0;
- unsigned long size = 0;
- unsigned long pfn = 0;
- unsigned long offset = 0;
- struct io_device *iod = (struct io_device *)filp->private_data;
-
- if (!vma)
- return -EFAULT;
-
- size = vma->vm_end - vma->vm_start;
- offset = vma->vm_pgoff << PAGE_SHIFT;
- if (offset + size > (C2C_CP_RGN_SIZE + C2C_SH_RGN_SIZE)) {
- mif_info("ERR: offset + size > C2C_CP_RGN_SIZE\n");
- return -EINVAL;
- }
-
- /* Set the noncacheable property to the region */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- vma->vm_flags |= VM_RESERVED | VM_IO;
-
- pfn = __phys_to_pfn(C2C_CP_RGN_ADDR + offset);
- r = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
- if (r) {
- mif_info("ERR: Failed in remap_pfn_range()!!!\n");
- return -EAGAIN;
- }
-
- mif_info("%s: VA = 0x%08lx, offset = 0x%lx, size = %lu\n",
- iod->name, vma->vm_start, offset, size);
-
- return 0;
-}
-#endif
-
static const struct file_operations misc_io_fops = {
.owner = THIS_MODULE,
.open = misc_open,
@@ -1384,9 +1419,6 @@ static const struct file_operations misc_io_fops = {
.unlocked_ioctl = misc_ioctl,
.write = misc_write,
.read = misc_read,
-#ifdef CONFIG_LINK_DEVICE_C2C
- .mmap = misc_mmap,
-#endif
};
static int vnet_open(struct net_device *ndev)
@@ -1419,11 +1451,13 @@ static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev)
struct link_device *ld = get_current_link(iod);
struct sk_buff *skb_new;
int ret;
- unsigned headroom = 0;
- unsigned tailroom = 0;
- unsigned long tx_bytes = skb->len;
+ unsigned headroom;
+ unsigned tailroom;
+ size_t count;
+ size_t tx_bytes;
struct iphdr *ip_header = NULL;
- struct sipc5_frame_data frm;
+ u8 *buff;
+ u8 cfg;
/* When use `handover' with Network Bridge,
* user -> bridge device(rmnet0) -> real rmnet(xxxx_rmnet0) -> here.
@@ -1436,19 +1470,18 @@ static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev)
skb_pull(skb, sizeof(struct ethhdr));
}
- headroom = tx_build_link_header(&frm, iod, ld, skb->len);
+ count = skb->len;
- /* ip loop-back */
- ip_header = (struct iphdr *)skb->data;
- if (iod->msd->loopback_ipaddr &&
- ip_header->daddr == iod->msd->loopback_ipaddr) {
- swap(ip_header->saddr, ip_header->daddr);
- frm.ch_id = DATA_LOOPBACK_CHANNEL;
- frm.hdr[SIPC5_CH_ID_OFFSET] = DATA_LOOPBACK_CHANNEL;
- }
+ cfg = sipc5_build_config(iod, ld, count);
+
+ headroom = sipc5_get_hdr_len(&cfg);
if (ld->aligned)
- tailroom = sipc5_calc_padding_size(frm.len);
+ tailroom = sipc5_calc_padding_size(headroom + count);
+ else
+ tailroom = 0;
+
+ tx_bytes = headroom + count + tailroom;
if (skb_headroom(skb) < headroom || skb_tailroom(skb) < tailroom) {
mif_debug("%s: skb_copy_expand needed\n", iod->name);
@@ -1463,7 +1496,18 @@ static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev)
skb_new = skb;
}
- memcpy(skb_push(skb_new, headroom), frm.hdr, headroom);
+ /* Build SIPC5 link header*/
+ buff = skb_push(skb_new, headroom);
+ sipc5_build_header(iod, ld, buff, cfg, 0, count);
+
+ /* IP loop-back */
+ ip_header = (struct iphdr *)skb->data;
+ if (iod->msd->loopback_ipaddr &&
+ ip_header->daddr == iod->msd->loopback_ipaddr) {
+ swap(ip_header->saddr, ip_header->daddr);
+ buff[SIPC5_CH_ID_OFFSET] = DATA_LOOPBACK_CHANNEL;
+ }
+
if (tailroom)
skb_put(skb_new, tailroom);
@@ -1473,12 +1517,18 @@ static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev)
ret = ld->send(ld, iod, skb_new);
if (ret < 0) {
netif_stop_queue(ndev);
- mif_info("%s: ERR! ld->send fail (err %d)\n", iod->name, ret);
+ mif_info("%s->%s: ERR! ld->send fail (err %d, tx_bytes %d)\n",
+ iod->name, ld->name, ret, tx_bytes);
return NETDEV_TX_BUSY;
}
+ if (ret != tx_bytes) {
+ mif_info("%s->%s: WARNING! ret %d != tx_bytes %d (count %d)\n",
+ iod->name, ld->name, ret, tx_bytes, count);
+ }
+
ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += tx_bytes;
+ ndev->stats.tx_bytes += count;
return NETDEV_TX_OK;
}
@@ -1581,16 +1631,19 @@ int sipc5_init_io_device(struct io_device *iod)
ret = misc_register(&iod->miscdev);
if (ret)
mif_info("%s: ERR! misc_register fail\n", iod->name);
+
ret = device_create_file(iod->miscdev.this_device,
&attr_waketime);
if (ret)
mif_info("%s: ERR! device_create_file fail\n",
iod->name);
+
ret = device_create_file(iod->miscdev.this_device,
&attr_loopback);
if (ret)
mif_err("failed to create `loopback file' : %s\n",
iod->name);
+
ret = device_create_file(iod->miscdev.this_device,
&attr_txlink);
if (ret)
diff --git a/drivers/misc/modem_if/sipc5_modem.c b/drivers/misc/modem_if/sipc5_modem.c
index f5e33d3..8a173d4 100644
--- a/drivers/misc/modem_if/sipc5_modem.c
+++ b/drivers/misc/modem_if/sipc5_modem.c
@@ -33,7 +33,8 @@
#include <linux/delay.h>
#include <linux/wakelock.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
+#include <mach/c2c.h>
#include "modem_prj.h"
#include "modem_variation.h"
#include "modem_utils.h"
@@ -77,27 +78,31 @@ static struct modem_shared *create_modem_shared_data(void)
static struct modem_ctl *create_modemctl_device(struct platform_device *pdev,
struct modem_shared *msd)
{
- int ret = 0;
- struct modem_data *pdata;
+ struct modem_data *pdata = pdev->dev.platform_data;
struct modem_ctl *modemctl;
- struct device *dev = &pdev->dev;
+ int ret;
/* create modem control device */
modemctl = kzalloc(sizeof(struct modem_ctl), GFP_KERNEL);
- if (!modemctl)
+ if (!modemctl) {
+ mif_err("%s: modemctl kzalloc fail\n", pdata->name);
+ mif_err("%s: xxx\n", pdata->name);
return NULL;
+ }
modemctl->msd = msd;
- modemctl->dev = dev;
+ modemctl->dev = &pdev->dev;
modemctl->phone_state = STATE_OFFLINE;
- pdata = pdev->dev.platform_data;
modemctl->mdm_data = pdata;
modemctl->name = pdata->name;
/* init modemctl device for getting modemctl operations */
ret = call_modem_init_func(modemctl, pdata);
if (ret) {
+ mif_err("%s: call_modem_init_func fail (err %d)\n",
+ pdata->name, ret);
+ mif_err("%s: xxx\n", pdata->name);
kfree(modemctl);
return NULL;
}
@@ -111,8 +116,8 @@ static struct io_device *create_io_device(struct modem_io_t *io_t,
struct modem_shared *msd, struct modem_ctl *modemctl,
struct modem_data *pdata)
{
- int ret = 0;
- struct io_device *iod = NULL;
+ int ret;
+ struct io_device *iod;
iod = kzalloc(sizeof(struct io_device), GFP_KERNEL);
if (!iod) {
@@ -128,6 +133,7 @@ static struct io_device *create_io_device(struct modem_io_t *io_t,
iod->format = io_t->format;
iod->io_typ = io_t->io_type;
iod->link_types = io_t->links;
+ iod->app = io_t->app;
iod->net_typ = pdata->modem_net;
iod->use_handover = pdata->use_handover;
iod->ipc_version = pdata->ipc_version;
@@ -139,7 +145,7 @@ static struct io_device *create_io_device(struct modem_io_t *io_t,
modemctl->iod = iod;
if (iod->format == IPC_BOOT) {
modemctl->bootd = iod;
- mif_info("Bood device = %s\n", iod->name);
+ mif_err("BOOT device = %s\n", iod->name);
}
/* link between io device and modem shared */
@@ -160,7 +166,7 @@ static struct io_device *create_io_device(struct modem_io_t *io_t,
return NULL;
}
- mif_debug("%s is created!!!\n", iod->name);
+ mif_info("%s created\n", iod->name);
return iod;
}
@@ -168,7 +174,6 @@ static int attach_devices(struct io_device *iod, enum modem_link tx_link)
{
struct modem_shared *msd = iod->msd;
struct link_device *ld;
- unsigned ch;
/* find link type for this io device */
list_for_each_entry(ld, &msd->link_dev_list, list) {
@@ -232,36 +237,36 @@ static int __devinit modem_probe(struct platform_device *pdev)
{
int i;
struct modem_data *pdata = pdev->dev.platform_data;
- struct modem_shared *msd = NULL;
- struct modem_ctl *modemctl = NULL;
+ struct modem_shared *msd;
+ struct modem_ctl *modemctl;
struct io_device *iod[pdata->num_iodevs];
struct link_device *ld;
-
- mif_err("%s\n", pdev->name);
- memset(iod, 0, sizeof(iod));
+ mif_err("%s: +++\n", pdata->name);
msd = create_modem_shared_data();
if (!msd) {
- mif_err("msd == NULL\n");
- goto err_free_modemctl;
+ mif_err("%s: msd == NULL\n", pdata->name);
+ return -ENOMEM;
}
modemctl = create_modemctl_device(pdev, msd);
if (!modemctl) {
- mif_err("modemctl == NULL\n");
- goto err_free_modemctl;
+ mif_err("%s: modemctl == NULL\n", pdata->name);
+ kfree(msd);
+ return -ENOMEM;
}
/* create link device */
/* support multi-link device */
+ memset(iod, 0, sizeof(iod));
for (i = 0; i < LINKDEV_MAX ; i++) {
/* find matching link type */
if (pdata->link_types & LINKTYPE(i)) {
ld = call_link_init_func(pdev, i);
if (!ld)
- goto err_free_modemctl;
+ goto free_mc;
- mif_err("link created: %s\n", ld->name);
+ mif_err("%s: %s link created\n", pdata->name, ld->name);
ld->link_type = i;
ld->mc = modemctl;
ld->msd = msd;
@@ -274,8 +279,8 @@ static int __devinit modem_probe(struct platform_device *pdev)
iod[i] = create_io_device(&pdata->iodevs[i], msd, modemctl,
pdata);
if (!iod[i]) {
- mif_err("iod[%d] == NULL\n", i);
- goto err_free_modemctl;
+ mif_err("%s: iod[%d] == NULL\n", pdata->name, i);
+ goto free_iod;
}
attach_devices(iod[i], pdata->iodevs[i].tx_link);
@@ -283,21 +288,23 @@ static int __devinit modem_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, modemctl);
- mif_err("Complete!!!\n");
-
+ mif_err("%s: ---\n", pdata->name);
return 0;
-err_free_modemctl:
- for (i = 0; i < pdata->num_iodevs; i++)
- if (iod[i] != NULL)
+free_iod:
+ for (i = 0; i < pdata->num_iodevs; i++) {
+ if (iod[i])
kfree(iod[i]);
+ }
- if (modemctl != NULL)
+free_mc:
+ if (modemctl)
kfree(modemctl);
- if (msd != NULL)
+ if (msd)
kfree(msd);
+ mif_err("%s: xxx\n", pdata->name);
return -ENOMEM;
}
@@ -305,13 +312,19 @@ static void modem_shutdown(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct modem_ctl *mc = dev_get_drvdata(dev);
+ struct utc_time utc;
+
mc->ops.modem_off(mc);
mc->phone_state = STATE_OFFLINE;
+
+ get_utc_time(&utc);
+ mif_info("%s: at [%02d:%02d:%02d.%03d]\n",
+ mc->name, utc.hour, utc.min, utc.sec, utc.msec);
}
static int modem_suspend(struct device *pdev)
{
-#ifndef CONFIG_LINK_DEVICE_HSIC
+#if !defined(CONFIG_LINK_DEVICE_HSIC)
struct modem_ctl *mc = dev_get_drvdata(pdev);
if (mc->gpio_pda_active)
@@ -323,7 +336,7 @@ static int modem_suspend(struct device *pdev)
static int modem_resume(struct device *pdev)
{
-#ifndef CONFIG_LINK_DEVICE_HSIC
+#if !defined(CONFIG_LINK_DEVICE_HSIC)
struct modem_ctl *mc = dev_get_drvdata(pdev);
if (mc->gpio_pda_active)
@@ -334,8 +347,8 @@ static int modem_resume(struct device *pdev)
}
static const struct dev_pm_ops modem_pm_ops = {
- .suspend = modem_suspend,
- .resume = modem_resume,
+ .suspend = modem_suspend,
+ .resume = modem_resume,
};
static struct platform_driver modem_driver = {
@@ -343,7 +356,7 @@ static struct platform_driver modem_driver = {
.shutdown = modem_shutdown,
.driver = {
.name = "mif_sipc5",
- .pm = &modem_pm_ops,
+ .pm = &modem_pm_ops,
},
};
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
deleted file mode 100644
index c7c9179..0000000
--- a/drivers/misc/pmem.c
+++ /dev/null
@@ -1,1386 +0,0 @@
-/* drivers/android/pmem.c
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/debugfs.h>
-#include <linux/android_pmem.h>
-#include <linux/mempolicy.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/cacheflush.h>
-#if defined(CONFIG_S5P_MEM_CMA)
-#include <linux/cma.h>
-#endif
-
-#define PMEM_MAX_DEVICES 10
-#define PMEM_MAX_ORDER 128
-#define PMEM_MIN_ALLOC PAGE_SIZE
-
-#define PMEM_DEBUG 1
-
-/* indicates that a refernce to this file has been taken via get_pmem_file,
- * the file should not be released until put_pmem_file is called */
-#define PMEM_FLAGS_BUSY 0x1
-/* indicates that this is a suballocation of a larger master range */
-#define PMEM_FLAGS_CONNECTED 0x1 << 1
-/* indicates this is a master and not a sub allocation and that it is mmaped */
-#define PMEM_FLAGS_MASTERMAP 0x1 << 2
-/* submap and unsubmap flags indicate:
- * 00: subregion has never been mmaped
- * 10: subregion has been mmaped, reference to the mm was taken
- * 11: subretion has ben released, refernece to the mm still held
- * 01: subretion has been released, reference to the mm has been released
- */
-#define PMEM_FLAGS_SUBMAP 0x1 << 3
-#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
-
-
-struct pmem_data {
- /* in alloc mode: an index into the bitmap
- * in no_alloc mode: the size of the allocation */
- int index;
- /* see flags above for descriptions */
- unsigned int flags;
- /* protects this data field, if the mm_mmap sem will be held at the
- * same time as this sem, the mm sem must be taken first (as this is
- * the order for vma_open and vma_close ops */
- struct rw_semaphore sem;
- /* info about the mmaping process */
- struct vm_area_struct *vma;
- /* task struct of the mapping process */
- struct task_struct *task;
- /* process id of teh mapping process */
- pid_t pid;
- /* file descriptor of the master */
- int master_fd;
- /* file struct of the master */
- struct file *master_file;
- /* a list of currently available regions if this is a suballocation */
- struct list_head region_list;
- /* a linked list of data so we can access them for debugging */
- struct list_head list;
-#if PMEM_DEBUG
- int ref;
-#endif
-};
-
-struct pmem_bits {
- unsigned allocated:1; /* 1 if allocated, 0 if free */
- unsigned order:7; /* size of the region in pmem space */
-};
-
-struct pmem_region_node {
- struct pmem_region region;
- struct list_head list;
-};
-
-#define PMEM_DEBUG_MSGS 0
-#if PMEM_DEBUG_MSGS
-#define DLOG(fmt,args...) \
- do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
- ##args); } \
- while (0)
-#else
-#define DLOG(x...) do {} while (0)
-#endif
-
-struct pmem_info {
- struct miscdevice dev;
- /* physical start address of the remaped pmem space */
- unsigned long base;
- /* vitual start address of the remaped pmem space */
- unsigned char __iomem *vbase;
- /* total size of the pmem space */
- unsigned long size;
- /* number of entries in the pmem space */
- unsigned long num_entries;
- /* pfn of the garbage page in memory */
- unsigned long garbage_pfn;
- /* index of the garbage page in the pmem space */
- int garbage_index;
- /* the bitmap for the region indicating which entries are allocated
- * and which are free */
- struct pmem_bits *bitmap;
- /* indicates the region should not be managed with an allocator */
- unsigned no_allocator;
- /* indicates maps of this region should be cached, if a mix of
- * cached and uncached is desired, set this and open the device with
- * O_SYNC to get an uncached region */
- unsigned cached;
- unsigned buffered;
- /* in no_allocator mode the first mapper gets the whole space and sets
- * this flag */
- unsigned allocated;
- /* for debugging, creates a list of pmem file structs, the
- * data_list_lock should be taken before pmem_data->sem if both are
- * needed */
- struct mutex data_list_lock;
- struct list_head data_list;
- /* pmem_sem protects the bitmap array
- * a write lock should be held when modifying entries in bitmap
- * a read lock should be held when reading data from bits or
- * dereferencing a pointer into bitmap
- *
- * pmem_data->sem protects the pmem data of a particular file
- * Many of the function that require the pmem_data->sem have a non-
- * locking version for when the caller is already holding that sem.
- *
- * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER:
- * down(pmem_data->sem) => down(bitmap_sem)
- */
- struct rw_semaphore bitmap_sem;
-
- long (*ioctl)(struct file *, unsigned int, unsigned long);
- int (*release)(struct inode *, struct file *);
-};
-
-static struct pmem_info pmem[PMEM_MAX_DEVICES];
-static int id_count;
-
-#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated)
-#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
-#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
-#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
-#define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC)
-#define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base)
-#define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC)
-#define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \
- PMEM_LEN(id, index))
-#define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase)
-#define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \
- PMEM_LEN(id, index))
-#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED)
-#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
-#define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \
- (!(data->flags & PMEM_FLAGS_UNSUBMAP)))
-
-static int pmem_release(struct inode *, struct file *);
-static int pmem_mmap(struct file *, struct vm_area_struct *);
-static int pmem_open(struct inode *, struct file *);
-static long pmem_ioctl(struct file *, unsigned int, unsigned long);
-
-struct file_operations pmem_fops = {
- .release = pmem_release,
- .mmap = pmem_mmap,
- .open = pmem_open,
- .unlocked_ioctl = pmem_ioctl,
-};
-
-static int get_id(struct file *file)
-{
- return MINOR(file->f_dentry->d_inode->i_rdev);
-}
-
-int is_pmem_file(struct file *file)
-{
- int id;
-
- if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))
- return 0;
- id = get_id(file);
- if (unlikely(id >= PMEM_MAX_DEVICES))
- return 0;
- if (unlikely(file->f_dentry->d_inode->i_rdev !=
- MKDEV(MISC_MAJOR, pmem[id].dev.minor)))
- return 0;
- return 1;
-}
-
-static int has_allocation(struct file *file)
-{
- struct pmem_data *data;
- /* check is_pmem_file first if not accessed via pmem_file_ops */
-
- if (unlikely(!file->private_data))
- return 0;
- data = (struct pmem_data *)file->private_data;
- if (unlikely(data->index < 0))
- return 0;
- return 1;
-}
-
-static int is_master_owner(struct file *file)
-{
- struct file *master_file;
- struct pmem_data *data;
- int put_needed, ret = 0;
-
- if (!is_pmem_file(file) || !has_allocation(file))
- return 0;
- data = (struct pmem_data *)file->private_data;
- if (PMEM_FLAGS_MASTERMAP & data->flags)
- return 1;
- master_file = fget_light(data->master_fd, &put_needed);
- if (master_file && data->master_file == master_file)
- ret = 1;
- fput_light(master_file, put_needed);
- return ret;
-}
-
-static int pmem_free(int id, int index)
-{
- /* caller should hold the write lock on pmem_sem! */
- int buddy, curr = index;
- DLOG("index %d\n", index);
-
- if (pmem[id].no_allocator) {
- pmem[id].allocated = 0;
- return 0;
- }
- /* clean up the bitmap, merging any buddies */
- pmem[id].bitmap[curr].allocated = 0;
- /* find a slots buddy Buddy# = Slot# ^ (1 << order)
- * if the buddy is also free merge them
- * repeat until the buddy is not free or end of the bitmap is reached
- */
- do {
- buddy = PMEM_BUDDY_INDEX(id, curr);
- if (PMEM_IS_FREE(id, buddy) &&
- PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) {
- PMEM_ORDER(id, buddy)++;
- PMEM_ORDER(id, curr)++;
- curr = min(buddy, curr);
- } else {
- break;
- }
- } while (curr < pmem[id].num_entries);
-
- return 0;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data);
-
-static int pmem_release(struct inode *inode, struct file *file)
-{
- struct pmem_data *data = (struct pmem_data *)file->private_data;
- struct pmem_region_node *region_node;
- struct list_head *elt, *elt2;
- int id = get_id(file), ret = 0;
-
-
- mutex_lock(&pmem[id].data_list_lock);
- /* if this file is a master, revoke all the memory in the connected
- * files */
- if (PMEM_FLAGS_MASTERMAP & data->flags) {
- struct pmem_data *sub_data;
- list_for_each(elt, &pmem[id].data_list) {
- sub_data = list_entry(elt, struct pmem_data, list);
- down_read(&sub_data->sem);
- if (PMEM_IS_SUBMAP(sub_data) &&
- file == sub_data->master_file) {
- up_read(&sub_data->sem);
- pmem_revoke(file, sub_data);
- } else
- up_read(&sub_data->sem);
- }
- }
- list_del(&data->list);
- mutex_unlock(&pmem[id].data_list_lock);
-
-
- down_write(&data->sem);
-
- /* if its not a conencted file and it has an allocation, free it */
- if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) {
- down_write(&pmem[id].bitmap_sem);
- ret = pmem_free(id, data->index);
- up_write(&pmem[id].bitmap_sem);
- }
-
- /* if this file is a submap (mapped, connected file), downref the
- * task struct */
- if (PMEM_FLAGS_SUBMAP & data->flags)
- if (data->task) {
- put_task_struct(data->task);
- data->task = NULL;
- }
-
- file->private_data = NULL;
-
- list_for_each_safe(elt, elt2, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node, list);
- list_del(elt);
- kfree(region_node);
- }
- BUG_ON(!list_empty(&data->region_list));
-
- up_write(&data->sem);
- kfree(data);
- if (pmem[id].release)
- ret = pmem[id].release(inode, file);
-
- return ret;
-}
-
-static int pmem_open(struct inode *inode, struct file *file)
-{
- struct pmem_data *data;
- int id = get_id(file);
- int ret = 0;
-
- DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file));
- /* setup file->private_data to indicate its unmapped */
- /* you can only open a pmem device one time */
- if (file->private_data != NULL && file_count(file) != 1)
- return -1;
- data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL);
- if (!data) {
- printk("pmem: unable to allocate memory for pmem metadata.");
- return -1;
- }
- data->flags = 0;
- data->index = -1;
- data->task = NULL;
- data->vma = NULL;
- data->pid = 0;
- data->master_file = NULL;
-#if PMEM_DEBUG
- data->ref = 0;
-#endif
- INIT_LIST_HEAD(&data->region_list);
- init_rwsem(&data->sem);
-
- file->private_data = data;
- INIT_LIST_HEAD(&data->list);
-
- mutex_lock(&pmem[id].data_list_lock);
- list_add(&data->list, &pmem[id].data_list);
- mutex_unlock(&pmem[id].data_list_lock);
- return ret;
-}
-
-static unsigned long pmem_order(unsigned long len)
-{
- int i;
-
- len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC;
- len--;
- for (i = 0; i < sizeof(len)*8; i++)
- if (len >> i == 0)
- break;
- return i;
-}
-
-static int pmem_allocate(int id, unsigned long len)
-{
- /* caller should hold the write lock on pmem_sem! */
- /* return the corresponding pdata[] entry */
- int curr = 0;
- int end = pmem[id].num_entries;
- int best_fit = -1;
- unsigned long order = pmem_order(len);
-
- if (pmem[id].no_allocator) {
- DLOG("no allocator");
- if ((len > pmem[id].size) || pmem[id].allocated)
- return -1;
- pmem[id].allocated = 1;
- return len;
- }
-
- if (order > PMEM_MAX_ORDER)
- return -1;
- DLOG("order %lx\n", order);
-
- /* look through the bitmap:
- * if you find a free slot of the correct order use it
- * otherwise, use the best fit (smallest with size > order) slot
- */
- while (curr < end) {
- if (PMEM_IS_FREE(id, curr)) {
- if (PMEM_ORDER(id, curr) == (unsigned char)order) {
- /* set the not free bit and clear others */
- best_fit = curr;
- break;
- }
- if (PMEM_ORDER(id, curr) > (unsigned char)order &&
- (best_fit < 0 ||
- PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit)))
- best_fit = curr;
- }
- curr = PMEM_NEXT_INDEX(id, curr);
- }
-
- /* if best_fit < 0, there are no suitable slots,
- * return an error
- */
- if (best_fit < 0) {
- printk("pmem: no space left to allocate!\n");
- return -1;
- }
-
- /* now partition the best fit:
- * split the slot into 2 buddies of order - 1
- * repeat until the slot is of the correct order
- */
- while (PMEM_ORDER(id, best_fit) > (unsigned char)order) {
- int buddy;
- PMEM_ORDER(id, best_fit) -= 1;
- buddy = PMEM_BUDDY_INDEX(id, best_fit);
- PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit);
- }
- pmem[id].bitmap[best_fit].allocated = 1;
- return best_fit;
-}
-
-static pgprot_t pmem_access_prot(struct file *file, pgprot_t vma_prot)
-{
- int id = get_id(file);
-#ifdef pgprot_noncached
- if (pmem[id].cached == 0 || file->f_flags & O_SYNC)
- return pgprot_noncached(vma_prot);
-#endif
-#ifdef pgprot_ext_buffered
- else if (pmem[id].buffered)
- return pgprot_ext_buffered(vma_prot);
-#endif
- return vma_prot;
-}
-
-static unsigned long pmem_start_addr(int id, struct pmem_data *data)
-{
- if (pmem[id].no_allocator)
- return PMEM_START_ADDR(id, 0);
- else
- return PMEM_START_ADDR(id, data->index);
-
-}
-
-static void *pmem_start_vaddr(int id, struct pmem_data *data)
-{
- return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase;
-}
-
-static unsigned long pmem_len(int id, struct pmem_data *data)
-{
- if (pmem[id].no_allocator)
- return data->index;
- else
- return PMEM_LEN(id, data->index);
-}
-
-static int pmem_map_garbage(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- int i, garbage_pages = len >> PAGE_SHIFT;
-
- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE;
- for (i = 0; i < garbage_pages; i++) {
- if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE),
- pmem[id].garbage_pfn))
- return -EAGAIN;
- }
- return 0;
-}
-
-static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- int garbage_pages;
- DLOG("unmap offset %lx len %lx\n", offset, len);
-
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
-
- garbage_pages = len >> PAGE_SHIFT;
- zap_page_range(vma, vma->vm_start + offset, len, NULL);
- pmem_map_garbage(id, vma, data, offset, len);
- return 0;
-}
-
-static int pmem_map_pfn_range(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- DLOG("map offset %lx len %lx\n", offset, len);
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start));
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end));
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset));
-
- if (io_remap_pfn_range(vma, vma->vm_start + offset,
- (pmem_start_addr(id, data) + offset) >> PAGE_SHIFT,
- len, vma->vm_page_prot)) {
- return -EAGAIN;
- }
- return 0;
-}
-
-static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- /* hold the mm semp for the vma you are modifying when you call this */
- BUG_ON(!vma);
- zap_page_range(vma, vma->vm_start + offset, len, NULL);
- return pmem_map_pfn_range(id, vma, data, offset, len);
-}
-
-static void pmem_vma_open(struct vm_area_struct *vma)
-{
- struct file *file = vma->vm_file;
- struct pmem_data *data = file->private_data;
- int id = get_id(file);
- /* this should never be called as we don't support copying pmem
- * ranges via fork */
- BUG_ON(!has_allocation(file));
- down_write(&data->sem);
- /* remap the garbage pages, forkers don't get access to the data */
- pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end);
- up_write(&data->sem);
-}
-
-static void pmem_vma_close(struct vm_area_struct *vma)
-{
- struct file *file = vma->vm_file;
- struct pmem_data *data = file->private_data;
-
- DLOG("current %u ppid %u file %p count %d\n", current->pid,
- current->parent->pid, file, file_count(file));
- if (unlikely(!is_pmem_file(file) || !has_allocation(file))) {
- printk(KERN_WARNING "pmem: something is very wrong, you are "
- "closing a vm backing an allocation that doesn't "
- "exist!\n");
- return;
- }
- down_write(&data->sem);
- if (data->vma == vma) {
- data->vma = NULL;
- if ((data->flags & PMEM_FLAGS_CONNECTED) &&
- (data->flags & PMEM_FLAGS_SUBMAP))
- data->flags |= PMEM_FLAGS_UNSUBMAP;
- }
- /* the kernel is going to free this vma now anyway */
- up_write(&data->sem);
-}
-
-static struct vm_operations_struct vm_ops = {
- .open = pmem_vma_open,
- .close = pmem_vma_close,
-};
-
-static int pmem_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct pmem_data *data;
- int index;
- unsigned long vma_size = vma->vm_end - vma->vm_start;
- int ret = 0, id = get_id(file);
-
- if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) {
-#if PMEM_DEBUG
- printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned"
- " and a multiple of pages_size.\n");
-#endif
- return -EINVAL;
- }
-
- data = (struct pmem_data *)file->private_data;
- down_write(&data->sem);
- /* check this file isn't already mmaped, for submaps check this file
- * has never been mmaped */
- if ((data->flags & PMEM_FLAGS_SUBMAP) ||
- (data->flags & PMEM_FLAGS_UNSUBMAP)) {
-#if PMEM_DEBUG
- printk(KERN_ERR "pmem: you can only mmap a pmem file once, "
- "this file is already mmaped. %x\n", data->flags);
-#endif
- ret = -EINVAL;
- goto error;
- }
- /* if file->private_data == unalloced, alloc*/
- if (data && data->index == -1) {
- down_write(&pmem[id].bitmap_sem);
- index = pmem_allocate(id, vma->vm_end - vma->vm_start);
- up_write(&pmem[id].bitmap_sem);
- data->index = index;
- }
- /* either no space was available or an error occured */
- if (!has_allocation(file)) {
- ret = -EINVAL;
- printk("pmem: could not find allocation for map.\n");
- goto error;
- }
-
- if (pmem_len(id, data) < vma_size) {
-#if PMEM_DEBUG
- printk(KERN_WARNING "pmem: mmap size [%lu] does not match"
- "size of backing region [%lu].\n", vma_size,
- pmem_len(id, data));
-#endif
- ret = -EINVAL;
- goto error;
- }
-
- vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT;
- vma->vm_page_prot = pmem_access_prot(file, vma->vm_page_prot);
-
- if (data->flags & PMEM_FLAGS_CONNECTED) {
- struct pmem_region_node *region_node;
- struct list_head *elt;
- if (pmem_map_garbage(id, vma, data, 0, vma_size)) {
- printk("pmem: mmap failed in kernel!\n");
- ret = -EAGAIN;
- goto error;
- }
- list_for_each(elt, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node,
- list);
- DLOG("remapping file: %p %lx %lx\n", file,
- region_node->region.offset,
- region_node->region.len);
- if (pmem_remap_pfn_range(id, vma, data,
- region_node->region.offset,
- region_node->region.len)) {
- ret = -EAGAIN;
- goto error;
- }
- }
- data->flags |= PMEM_FLAGS_SUBMAP;
- get_task_struct(current->group_leader);
- data->task = current->group_leader;
- data->vma = vma;
-#if PMEM_DEBUG
- data->pid = current->pid;
-#endif
- DLOG("submmapped file %p vma %p pid %u\n", file, vma,
- current->pid);
- } else {
- if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) {
- printk(KERN_INFO "pmem: mmap failed in kernel!\n");
- ret = -EAGAIN;
- goto error;
- }
- data->flags |= PMEM_FLAGS_MASTERMAP;
- data->pid = current->pid;
- }
- vma->vm_ops = &vm_ops;
-error:
- up_write(&data->sem);
- return ret;
-}
-
-/* the following are the api for accessing pmem regions by other drivers
- * from inside the kernel */
-int get_pmem_user_addr(struct file *file, unsigned long *start,
- unsigned long *len)
-{
- struct pmem_data *data;
- if (!is_pmem_file(file) || !has_allocation(file)) {
-#if PMEM_DEBUG
- printk(KERN_INFO "pmem: requested pmem data from invalid"
- "file.\n");
-#endif
- return -1;
- }
- data = (struct pmem_data *)file->private_data;
- down_read(&data->sem);
- if (data->vma) {
- *start = data->vma->vm_start;
- *len = data->vma->vm_end - data->vma->vm_start;
- } else {
- *start = 0;
- *len = 0;
- }
- up_read(&data->sem);
- return 0;
-}
-
-int get_pmem_addr(struct file *file, unsigned long *start,
- unsigned long *vstart, unsigned long *len)
-{
- struct pmem_data *data;
- int id;
-
- if (!is_pmem_file(file) || !has_allocation(file)) {
- return -1;
- }
-
- data = (struct pmem_data *)file->private_data;
- if (data->index == -1) {
-#if PMEM_DEBUG
- printk(KERN_INFO "pmem: requested pmem data from file with no "
- "allocation.\n");
- return -1;
-#endif
- }
- id = get_id(file);
-
- down_read(&data->sem);
- *start = pmem_start_addr(id, data);
- *len = pmem_len(id, data);
- *vstart = (unsigned long)pmem_start_vaddr(id, data);
- up_read(&data->sem);
-#if PMEM_DEBUG
- down_write(&data->sem);
- data->ref++;
- up_write(&data->sem);
-#endif
- return 0;
-}
-
-int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
- unsigned long *len, struct file **filp)
-{
- struct file *file;
-
- file = fget(fd);
- if (unlikely(file == NULL)) {
- printk(KERN_INFO "pmem: requested data from file descriptor "
- "that doesn't exist.");
- return -1;
- }
-
- if (get_pmem_addr(file, start, vstart, len))
- goto end;
-
- if (filp)
- *filp = file;
- return 0;
-end:
- fput(file);
- return -1;
-}
-
-void put_pmem_file(struct file *file)
-{
- struct pmem_data *data;
- int id;
-
- if (!is_pmem_file(file))
- return;
- id = get_id(file);
- data = (struct pmem_data *)file->private_data;
-#if PMEM_DEBUG
- down_write(&data->sem);
- if (data->ref == 0) {
- printk("pmem: pmem_put > pmem_get %s (pid %d)\n",
- pmem[id].dev.name, data->pid);
- BUG();
- }
- data->ref--;
- up_write(&data->sem);
-#endif
- fput(file);
-}
-
-void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
-{
- struct pmem_data *data;
- int id;
- void *vaddr;
- struct pmem_region_node *region_node;
- struct list_head *elt;
- void *flush_start, *flush_end;
-
- if (!is_pmem_file(file) || !has_allocation(file)) {
- return;
- }
-
- id = get_id(file);
- data = (struct pmem_data *)file->private_data;
- if (!pmem[id].cached || file->f_flags & O_SYNC)
- return;
-
- down_read(&data->sem);
- vaddr = pmem_start_vaddr(id, data);
- /* if this isn't a submmapped file, flush the whole thing */
- if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) {
- if (pmem_len(id, data) >= SZ_1M) {
- flush_all_cpu_caches();
- outer_flush_all();
- } else if (pmem_len(id, data) >= SZ_64K) {
- flush_all_cpu_caches();
- outer_flush_range(virt_to_phys(vaddr), virt_to_phys(vaddr + pmem_len(id, data)));
- } else {
- dmac_flush_range(vaddr, vaddr + pmem_len(id, data));
- outer_flush_range(virt_to_phys(vaddr), virt_to_phys(vaddr + pmem_len(id, data)));
- }
- goto end;
- }
- /* otherwise, flush the region of the file we are drawing */
- list_for_each(elt, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node, list);
- if ((offset >= region_node->region.offset) &&
- ((offset + len) <= (region_node->region.offset +
- region_node->region.len))) {
- flush_start = vaddr + region_node->region.offset;
- flush_end = flush_start + region_node->region.len;
-
- if (pmem_len(id, data) >= SZ_1M) {
- flush_all_cpu_caches();
- outer_flush_all();
- } else if (pmem_len(id, data) >= SZ_64K) {
- flush_all_cpu_caches();
- outer_flush_range(virt_to_phys(flush_start), virt_to_phys(flush_end));
- } else {
- dmac_flush_range(flush_start, flush_end);
- outer_flush_range(virt_to_phys(flush_start), virt_to_phys(flush_end));
- }
- break;
- }
- }
-end:
- up_read(&data->sem);
-}
-
-static int pmem_connect(unsigned long connect, struct file *file)
-{
- struct pmem_data *data = (struct pmem_data *)file->private_data;
- struct pmem_data *src_data;
- struct file *src_file;
- int ret = 0, put_needed;
-
- down_write(&data->sem);
- /* retrieve the src file and check it is a pmem file with an alloc */
- src_file = fget_light(connect, &put_needed);
- DLOG("connect %p to %p\n", file, src_file);
- if (!src_file) {
- printk("pmem: src file not found!\n");
- ret = -EINVAL;
- goto err_no_file;
- }
- if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) {
- printk(KERN_INFO "pmem: src file is not a pmem file or has no "
- "alloc!\n");
- ret = -EINVAL;
- goto err_bad_file;
- }
- src_data = (struct pmem_data *)src_file->private_data;
-
- if (has_allocation(file) && (data->index != src_data->index)) {
- printk("pmem: file is already mapped but doesn't match this"
- " src_file!\n");
- ret = -EINVAL;
- goto err_bad_file;
- }
- data->index = src_data->index;
- data->flags |= PMEM_FLAGS_CONNECTED;
- data->master_fd = connect;
- data->master_file = src_file;
-
-err_bad_file:
- fput_light(src_file, put_needed);
-err_no_file:
- up_write(&data->sem);
- return ret;
-}
-
-static void pmem_unlock_data_and_mm(struct pmem_data *data,
- struct mm_struct *mm)
-{
- up_write(&data->sem);
- if (mm != NULL) {
- up_write(&mm->mmap_sem);
- mmput(mm);
- }
-}
-
-static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data,
- struct mm_struct **locked_mm)
-{
- int ret = 0;
- struct mm_struct *mm = NULL;
- *locked_mm = NULL;
-lock_mm:
- down_read(&data->sem);
- if (PMEM_IS_SUBMAP(data)) {
- mm = get_task_mm(data->task);
- if (!mm) {
-#if PMEM_DEBUG
- printk("pmem: can't remap task is gone!\n");
-#endif
- up_read(&data->sem);
- return -1;
- }
- }
- up_read(&data->sem);
-
- if (mm)
- down_write(&mm->mmap_sem);
-
- down_write(&data->sem);
- /* check that the file didn't get mmaped before we could take the
- * data sem, this should be safe b/c you can only submap each file
- * once */
- if (PMEM_IS_SUBMAP(data) && !mm) {
- pmem_unlock_data_and_mm(data, mm);
- goto lock_mm;
- }
- /* now check that vma.mm is still there, it could have been
- * deleted by vma_close before we could get the data->sem */
- if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) {
- /* might as well release this */
- if (data->flags & PMEM_FLAGS_SUBMAP) {
- put_task_struct(data->task);
- data->task = NULL;
- /* lower the submap flag to show the mm is gone */
- data->flags &= ~(PMEM_FLAGS_SUBMAP);
- }
- pmem_unlock_data_and_mm(data, mm);
- return -1;
- }
- *locked_mm = mm;
- return ret;
-}
-
-int pmem_remap(struct pmem_region *region, struct file *file,
- unsigned operation)
-{
- int ret;
- struct pmem_region_node *region_node;
- struct mm_struct *mm = NULL;
- struct list_head *elt, *elt2;
- int id = get_id(file);
- struct pmem_data *data = (struct pmem_data *)file->private_data;
-
- /* pmem region must be aligned on a page boundry */
- if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
- !PMEM_IS_PAGE_ALIGNED(region->len))) {
-#if PMEM_DEBUG
- printk("pmem: request for unaligned pmem suballocation "
- "%lx %lx\n", region->offset, region->len);
-#endif
- return -EINVAL;
- }
-
- /* if userspace requests a region of len 0, there's nothing to do */
- if (region->len == 0)
- return 0;
-
- /* lock the mm and data */
- ret = pmem_lock_data_and_mm(file, data, &mm);
- if (ret)
- return 0;
-
- /* only the owner of the master file can remap the client fds
- * that back in it */
- if (!is_master_owner(file)) {
-#if PMEM_DEBUG
- printk("pmem: remap requested from non-master process\n");
-#endif
- ret = -EINVAL;
- goto err;
- }
-
- /* check that the requested range is within the src allocation */
- if (unlikely((region->offset > pmem_len(id, data)) ||
- (region->len > pmem_len(id, data)) ||
- (region->offset + region->len > pmem_len(id, data)))) {
-#if PMEM_DEBUG
- printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n");
-#endif
- ret = -EINVAL;
- goto err;
- }
-
- if (operation == PMEM_MAP) {
- region_node = kmalloc(sizeof(struct pmem_region_node),
- GFP_KERNEL);
- if (!region_node) {
- ret = -ENOMEM;
-#if PMEM_DEBUG
- printk(KERN_INFO "No space to allocate metadata!");
-#endif
- goto err;
- }
- region_node->region = *region;
- list_add(&region_node->list, &data->region_list);
- } else if (operation == PMEM_UNMAP) {
- int found = 0;
- list_for_each_safe(elt, elt2, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node,
- list);
- if (region->len == 0 ||
- (region_node->region.offset == region->offset &&
- region_node->region.len == region->len)) {
- list_del(elt);
- kfree(region_node);
- found = 1;
- }
- }
- if (!found) {
-#if PMEM_DEBUG
- printk("pmem: Unmap region does not map any mapped "
- "region!");
-#endif
- ret = -EINVAL;
- goto err;
- }
- }
-
- if (data->vma && PMEM_IS_SUBMAP(data)) {
- if (operation == PMEM_MAP)
- ret = pmem_remap_pfn_range(id, data->vma, data,
- region->offset, region->len);
- else if (operation == PMEM_UNMAP)
- ret = pmem_unmap_pfn_range(id, data->vma, data,
- region->offset, region->len);
- }
-
-err:
- pmem_unlock_data_and_mm(data, mm);
- return ret;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data)
-{
- struct pmem_region_node *region_node;
- struct list_head *elt, *elt2;
- struct mm_struct *mm = NULL;
- int id = get_id(file);
- int ret = 0;
-
- data->master_file = NULL;
- ret = pmem_lock_data_and_mm(file, data, &mm);
- /* if lock_data_and_mm fails either the task that mapped the fd, or
- * the vma that mapped it have already gone away, nothing more
- * needs to be done */
- if (ret)
- return;
- /* unmap everything */
- /* delete the regions and region list nothing is mapped any more */
- if (data->vma)
- list_for_each_safe(elt, elt2, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node,
- list);
- pmem_unmap_pfn_range(id, data->vma, data,
- region_node->region.offset,
- region_node->region.len);
- list_del(elt);
- kfree(region_node);
- }
- /* delete the master file */
- pmem_unlock_data_and_mm(data, mm);
-}
-
-static void pmem_get_size(struct pmem_region *region, struct file *file)
-{
- struct pmem_data *data = (struct pmem_data *)file->private_data;
- int id = get_id(file);
-
- if (!has_allocation(file)) {
- region->offset = 0;
- region->len = 0;
- return;
- } else {
- region->offset = pmem_start_addr(id, data);
- region->len = pmem_len(id, data);
- }
- DLOG("offset %lx len %lx\n", region->offset, region->len);
-}
-
-
-static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct pmem_data *data;
- int id = get_id(file);
-
- switch (cmd) {
- case PMEM_GET_PHYS:
- {
- struct pmem_region region;
- DLOG("get_phys\n");
- if (!has_allocation(file)) {
- region.offset = 0;
- region.len = 0;
- } else {
- data = (struct pmem_data *)file->private_data;
- region.offset = pmem_start_addr(id, data);
- region.len = pmem_len(id, data);
- }
- printk(KERN_DEBUG "pmem: request for physical address of pmem region "
- "from process %d.\n", current->pid);
- if (copy_to_user((void __user *)arg, &region,
- sizeof(struct pmem_region)))
- return -EFAULT;
- break;
- }
- case PMEM_MAP:
- {
- struct pmem_region region;
- if (copy_from_user(&region, (void __user *)arg,
- sizeof(struct pmem_region)))
- return -EFAULT;
- data = (struct pmem_data *)file->private_data;
- return pmem_remap(&region, file, PMEM_MAP);
- }
- break;
- case PMEM_UNMAP:
- {
- struct pmem_region region;
- if (copy_from_user(&region, (void __user *)arg,
- sizeof(struct pmem_region)))
- return -EFAULT;
- data = (struct pmem_data *)file->private_data;
- return pmem_remap(&region, file, PMEM_UNMAP);
- break;
- }
- case PMEM_GET_SIZE:
- {
- struct pmem_region region;
- DLOG("get_size\n");
- pmem_get_size(&region, file);
- if (copy_to_user((void __user *)arg, &region,
- sizeof(struct pmem_region)))
- return -EFAULT;
- break;
- }
- case PMEM_GET_TOTAL_SIZE:
- {
- struct pmem_region region;
- DLOG("get total size\n");
- region.offset = 0;
- get_id(file);
- region.len = pmem[id].size;
- if (copy_to_user((void __user *)arg, &region,
- sizeof(struct pmem_region)))
- return -EFAULT;
- break;
- }
- case PMEM_ALLOCATE:
- {
- if (has_allocation(file))
- return -EINVAL;
- data = (struct pmem_data *)file->private_data;
- data->index = pmem_allocate(id, arg);
- break;
- }
- case PMEM_CONNECT:
- DLOG("connect\n");
- return pmem_connect(arg, file);
- break;
- case PMEM_CACHE_FLUSH:
- {
- struct pmem_region region;
- DLOG("flush\n");
- if (copy_from_user(&region, (void __user *)arg,
- sizeof(struct pmem_region)))
- return -EFAULT;
- flush_pmem_file(file, region.offset, region.len);
- break;
- }
- default:
- if (pmem[id].ioctl)
- return pmem[id].ioctl(file, cmd, arg);
- return -EINVAL;
- }
- return 0;
-}
-
-#if PMEM_DEBUG
-static ssize_t debug_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- struct list_head *elt, *elt2;
- struct pmem_data *data;
- struct pmem_region_node *region_node;
- int id = (int)file->private_data;
- const int debug_bufmax = 4096;
- static char buffer[4096];
- int n = 0;
-
- DLOG("debug open\n");
- n = scnprintf(buffer, debug_bufmax,
- "pid #: mapped regions (offset, len) (offset,len)...\n");
-
- mutex_lock(&pmem[id].data_list_lock);
- list_for_each(elt, &pmem[id].data_list) {
- data = list_entry(elt, struct pmem_data, list);
- down_read(&data->sem);
- n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:",
- data->pid);
- list_for_each(elt2, &data->region_list) {
- region_node = list_entry(elt2, struct pmem_region_node,
- list);
- n += scnprintf(buffer + n, debug_bufmax - n,
- "(%lx,%lx) ",
- region_node->region.offset,
- region_node->region.len);
- }
- n += scnprintf(buffer + n, debug_bufmax - n, "\n");
- up_read(&data->sem);
- }
- mutex_unlock(&pmem[id].data_list_lock);
-
- n++;
- buffer[n] = 0;
- return simple_read_from_buffer(buf, count, ppos, buffer, n);
-}
-
-static struct file_operations debug_fops = {
- .read = debug_read,
- .open = debug_open,
-};
-#endif
-
-#if 0
-static struct miscdevice pmem_dev = {
- .name = "pmem",
- .fops = &pmem_fops,
-};
-#endif
-
-int pmem_setup(struct android_pmem_platform_data *pdata,
- long (*ioctl)(struct file *, unsigned int, unsigned long),
- int (*release)(struct inode *, struct file *))
-{
- int err = 0;
- int i, index = 0;
- int id = id_count;
- struct page **pages;
- int nr_pages;
- int prot;
- id_count++;
-
-#if defined(CONFIG_S5P_MEM_CMA)
- pdata->start = cma_alloc_from(pdata->name, pdata->size, 0);
-#endif
-
- pmem[id].no_allocator = pdata->no_allocator;
- pmem[id].cached = pdata->cached;
- pmem[id].buffered = pdata->buffered;
- pmem[id].base = pdata->start;
- pmem[id].size = pdata->size;
- pmem[id].ioctl = ioctl;
- pmem[id].release = release;
- init_rwsem(&pmem[id].bitmap_sem);
- mutex_init(&pmem[id].data_list_lock);
- INIT_LIST_HEAD(&pmem[id].data_list);
- pmem[id].dev.name = pdata->name;
- pmem[id].dev.minor = id;
- pmem[id].dev.fops = &pmem_fops;
- printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached);
-
- err = misc_register(&pmem[id].dev);
- if (err) {
- printk(KERN_ALERT "Unable to register pmem driver!\n");
- goto err_cant_register_device;
- }
- pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC;
-
- pmem[id].bitmap = kmalloc(pmem[id].num_entries *
- sizeof(struct pmem_bits), GFP_KERNEL);
- if (!pmem[id].bitmap)
- goto err_no_mem_for_metadata;
-
- memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) *
- pmem[id].num_entries);
-
- for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) {
- if ((pmem[id].num_entries) & 1<<i) {
- PMEM_ORDER(id, index) = i;
- index = PMEM_NEXT_INDEX(id, index);
- }
- }
-
- nr_pages = pmem[id].size >> PAGE_SHIFT;
- pages = kmalloc(nr_pages * sizeof(*pages), GFP_KERNEL);
- if (!pages)
- goto err_no_mem_for_pages;
-
- for (i = 0; i < nr_pages; i++)
- pages[i] = phys_to_page(pmem[id].base + i * PAGE_SIZE);
-
- if (pmem[id].cached)
- prot = PAGE_KERNEL;
- else if (pmem[id].buffered)
- prot = pgprot_writecombine(PAGE_KERNEL);
- else
- prot = pgprot_noncached(PAGE_KERNEL);
-
- pmem[id].vbase = vmap(pages, nr_pages, VM_MAP, prot);
-
- kfree(pages);
-
- if (pmem[id].vbase == 0)
- goto error_cant_remap;
-
- pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
- if (pmem[id].no_allocator)
- pmem[id].allocated = 0;
-
-#if PMEM_DEBUG
- debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)id,
- &debug_fops);
-#endif
- return 0;
-error_cant_remap:
-err_no_mem_for_pages:
- kfree(pmem[id].bitmap);
-err_no_mem_for_metadata:
- misc_deregister(&pmem[id].dev);
-err_cant_register_device:
- return -1;
-}
-
-static int pmem_probe(struct platform_device *pdev)
-{
- struct android_pmem_platform_data *pdata;
-
- if (!pdev || !pdev->dev.platform_data) {
- printk(KERN_ALERT "Unable to probe pmem!\n");
- return -1;
- }
- pdata = pdev->dev.platform_data;
- return pmem_setup(pdata, NULL, NULL);
-}
-
-
-static int pmem_remove(struct platform_device *pdev)
-{
- int id = pdev->id;
- __free_page(pfn_to_page(pmem[id].garbage_pfn));
-#if defined(CONFIG_S5P_MEM_CMA)
- cma_free(((struct android_pmem_platform_data *)(pdev->dev.platform_data))->start);
-#endif
- misc_deregister(&pmem[id].dev);
- return 0;
-}
-
-static struct platform_driver pmem_driver = {
- .probe = pmem_probe,
- .remove = pmem_remove,
- .driver = { .name = "android_pmem" }
-};
-
-
-static int __init pmem_init(void)
-{
- return platform_driver_register(&pmem_driver);
-}
-
-static void __exit pmem_exit(void)
-{
- platform_driver_unregister(&pmem_driver);
-}
-
-module_init(pmem_init);
-module_exit(pmem_exit);
-
diff --git a/drivers/misc/tzic.c b/drivers/misc/tzic.c
index 6a5e3ba..643e078 100644
--- a/drivers/misc/tzic.c
+++ b/drivers/misc/tzic.c
@@ -23,7 +23,6 @@
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/mutex.h>
-#include <linux/android_pmem.h>
#include <linux/io.h>
#include <linux/types.h>
#include <asm/smc.h>
diff --git a/drivers/motor/max77693_haptic.c b/drivers/motor/max77693_haptic.c
index beb7f2a..9c83c25 100644
--- a/drivers/motor/max77693_haptic.c
+++ b/drivers/motor/max77693_haptic.c
@@ -24,6 +24,11 @@
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-private.h>
+#define PWM_MIN 0
+#define PWM_DEFAULT 50
+#define PWM_THRESH 75
+#define PWM_MAX 100
+
static unsigned long pwm_val = 50; /* duty in percent */
static int pwm_duty = 27787; /* duty value, 37050=100%, 27787=50%, 18525=0% */
@@ -301,6 +306,42 @@ ssize_t pwm_value_store(struct device *dev,
static DEVICE_ATTR(pwm_value, S_IRUGO | S_IWUSR,
pwm_value_show, pwm_value_store);
+static ssize_t pwm_default_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", PWM_DEFAULT);
+}
+
+static DEVICE_ATTR(pwm_default, S_IRUGO,
+ pwm_default_show, NULL);
+
+static ssize_t pwm_max_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", PWM_MAX);
+}
+
+static DEVICE_ATTR(pwm_max, S_IRUGO,
+ pwm_max_show, NULL);
+
+static ssize_t pwm_min_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", PWM_MIN);
+}
+
+static DEVICE_ATTR(pwm_min, S_IRUGO,
+ pwm_min_show, NULL);
+
+static ssize_t pwm_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", PWM_THRESH);
+}
+
+static DEVICE_ATTR(pwm_threshold, S_IRUGO,
+ pwm_threshold_show, NULL);
+
static int max77693_haptic_probe(struct platform_device *pdev)
{
int error = 0;
@@ -378,6 +419,23 @@ static int max77693_haptic_probe(struct platform_device *pdev)
if (error < 0) {
pr_err("[VIB] create sysfs fail: pwm_value\n");
}
+ error = device_create_file(hap_data->tout_dev.dev, &dev_attr_pwm_max);
+ if (error < 0) {
+ pr_err("[VIB] create sysfs fail: pwm_max\n");
+ }
+ error = device_create_file(hap_data->tout_dev.dev, &dev_attr_pwm_min);
+ if (error < 0) {
+ pr_err("[VIB] create sysfs fail: pwm_min\n");
+ }
+ error = device_create_file(hap_data->tout_dev.dev, &dev_attr_pwm_default);
+ if (error < 0) {
+ pr_err("[VIB] create sysfs fail: pwm_default\n");
+ }
+ error = device_create_file(hap_data->tout_dev.dev, &dev_attr_pwm_threshold);
+ if (error < 0) {
+ pr_err("[VIB] create sysfs fail: pwm_threshold\n");
+ }
+
#endif
pr_debug("[VIB] -- %s\n", __func__);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index b890401..3253731 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -2172,7 +2172,7 @@ int ppp_register_net_channel(struct net *net, struct ppp_channel *chan)
pch->ppp = NULL;
pch->chan = chan;
- pch->chan_net = net;
+ pch->chan_net = get_net(net);
chan->ppp = pch;
init_ppp_file(&pch->file, CHANNEL);
pch->file.hdrlen = chan->hdrlen;
@@ -2269,6 +2269,8 @@ ppp_unregister_channel(struct ppp_channel *chan)
spin_lock_bh(&pn->all_channels_lock);
list_del(&pch->list);
spin_unlock_bh(&pn->all_channels_lock);
+ put_net(pch->chan_net);
+ pch->chan_net = NULL;
pch->file.dead = 1;
wake_up_interruptible(&pch->file.rwait);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index bc2e489..460979d 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1523,6 +1523,13 @@ out3:
if (info->unbind)
info->unbind (dev, udev);
out1:
+ /* subdrivers must undo all they did in bind() if they
+ * fail it, but we may fail later and a deferred kevent
+ * may trigger an error resubmitting itself and, worse,
+ * schedule a timer. So we kill it all just in case.
+ */
+ cancel_work_sync(&dev->kevent);
+ del_timer_sync(&dev->delay);
free_netdev(net);
out:
usb_put_dev(xdev);
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig
index d148725..f4f5b96 100644
--- a/drivers/net/wireless/bcmdhd/Kconfig
+++ b/drivers/net/wireless/bcmdhd/Kconfig
@@ -89,6 +89,12 @@ config BROADCOM_WIFI_RESERVED_MEM
---help---
This is a configuration for broadcom WLAN driver.
+config WIFI_BROADCOM_COB
+ bool "BROADCOM WIFI COB"
+ depends on (BCM4334)
+ ---help---
+ This is a configuration for broadcom WIFI COB Type.
+
config BCM4335BT
bool "BROADCOM BTLOCK Enable"
depends on BCM4335
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 7ac8f56..12f7b1d 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -2906,6 +2906,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
ret = -EINVAL;
goto exit;
}
+ if (!capable(CAP_NET_ADMIN)) {
+ ret = -EPERM;
+ goto exit;
+ }
if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
ret = -EFAULT;
goto exit;
diff --git a/drivers/power/max17042_fuelgauge_u1.c b/drivers/power/max17042_fuelgauge_u1.c
index 39b931c..378dafe 100644
--- a/drivers/power/max17042_fuelgauge_u1.c
+++ b/drivers/power/max17042_fuelgauge_u1.c
@@ -884,7 +884,7 @@ static int __devinit max17042_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->battery.name = "fuelgauge";
- chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+ chip->battery.type = POWER_SUPPLY_TYPE_UNKNOWN;
chip->battery.get_property = max17042_get_property;
chip->battery.set_property = max17042_set_property;
chip->battery.properties = max17042_battery_props;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 909ed9e..4172f89 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -739,8 +739,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return k; /* probably out of space --> ENOMEM */
}
if (sdp->detached) {
- if (srp->bio)
+ if (srp->bio) {
+ if (srp->rq->cmd != srp->rq->__cmd)
+ kfree(srp->rq->cmd);
+
blk_end_request_all(srp->rq, -EIO);
+ srp->rq = NULL;
+ }
+
sg_finish_rem_req(srp);
return -ENODEV;
}
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 11a4b5b..d0f6718 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -104,8 +104,6 @@ source "drivers/staging/iio/Kconfig"
source "drivers/staging/cs5535_gpio/Kconfig"
-source "drivers/staging/zram/Kconfig"
-
source "drivers/staging/zcache/Kconfig"
source "drivers/staging/wlags49_h2/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ae62e92..9400eb7 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -43,8 +43,6 @@ obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio/
-obj-$(CONFIG_ZRAM) += zram/
-obj-$(CONFIG_XVMALLOC) += zram/
obj-$(CONFIG_ZCACHE) += zcache/
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 2471949..30ad4d2 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -90,6 +90,23 @@ config ANDROID_LOW_MEMORY_KILLER
---help---
Register processes to be killed when memory is low
+config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+ bool "Android Low Memory Killer: detect oom_adj values"
+ depends on ANDROID_LOW_MEMORY_KILLER
+ default y
+ ---help---
+ Detect oom_adj values written to
+ /sys/module/lowmemorykiller/parameters/adj and convert them
+ to oom_score_adj values.
+
+config ANDROID_LMK_ADJ_RBTREE
+ bool "Use RBTREE for Android Low Memory Killer"
+ depends on ANDROID_LOW_MEMORY_KILLER
+ default y
+ ---help---
+ Use oom_score_adj rbtree to select the best proecss to kill
+ when system in low memory status.
+
endif # if ANDROID
endmenu
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index e2b69f2..72db295 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -3346,7 +3346,7 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
static void print_binder_ref(struct seq_file *m, struct binder_ref *ref)
{
- seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n",
+ seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n",
ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
ref->node->debug_id, ref->strong, ref->weak, ref->death);
}
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 15bbcd3..5a9835b 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -1,16 +1,17 @@
/* drivers/misc/lowmemorykiller.c
*
* The lowmemorykiller driver lets user-space specify a set of memory thresholds
- * where processes with a range of oom_adj values will get killed. Specify the
- * minimum oom_adj values in /sys/module/lowmemorykiller/parameters/adj and the
- * number of free pages in /sys/module/lowmemorykiller/parameters/minfree. Both
- * files take a comma separated list of numbers in ascending order.
+ * where processes with a range of oom_score_adj values will get killed. Specify
+ * the minimum oom_score_adj values in
+ * /sys/module/lowmemorykiller/parameters/adj and the number of free pages in
+ * /sys/module/lowmemorykiller/parameters/minfree. Both files take a comma
+ * separated list of numbers in ascending order.
*
* For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
- * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill processes
- * with a oom_adj value of 8 or higher when the free memory drops below 4096 pages
- * and kill processes with a oom_adj value of 0 or higher when the free memory
- * drops below 1024 pages.
+ * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill
+ * processes with a oom_score_adj value of 8 or higher when the free memory
+ * drops below 4096 pages and kill processes with a oom_score_adj value of 0 or
+ * higher when the free memory drops below 1024 pages.
*
* The driver considers memory used for caches to be free, but if a large
* percentage of the cached memory is locked this can be very inaccurate
@@ -29,25 +30,18 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/oom.h>
#include <linux/sched.h>
-#include <linux/notifier.h>
-#ifdef CONFIG_ZRAM_FOR_ANDROID
#include <linux/swap.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/mm_inline.h>
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-#define ENHANCED_LMK_ROUTINE
-
-#ifdef ENHANCED_LMK_ROUTINE
-#define LOWMEM_DEATHPENDING_DEPTH 3
-#endif
+#include <linux/rcupdate.h>
+#include <linux/notifier.h>
-static uint32_t lowmem_debug_level = 2;
+static uint32_t lowmem_debug_level = 1;
static int lowmem_adj[6] = {
0,
1,
@@ -55,54 +49,20 @@ static int lowmem_adj[6] = {
12,
};
static int lowmem_adj_size = 4;
-static size_t lowmem_minfree[6] = {
+static int lowmem_minfree[6] = {
3 * 512, /* 6MB */
2 * 1024, /* 8MB */
4 * 1024, /* 16MB */
16 * 1024, /* 64MB */
};
static int lowmem_minfree_size = 4;
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-static struct class *lmk_class;
-static struct device *lmk_dev;
-static int lmk_kill_pid = 0;
-static int lmk_kill_ok = 0;
-
-extern atomic_t optimize_comp_on;
-
-extern int isolate_lru_page_compcache(struct page *page);
-extern void putback_lru_page(struct page *page);
-extern unsigned int zone_id_shrink_pagelist(struct zone *zone_id,struct list_head *page_list);
-
-#define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
-
-#define SWAP_PROCESS_DEBUG_LOG 0
-/* free RAM 8M(2048 pages) */
-#define CHECK_FREE_MEMORY 2048
-/* free swap (10240 pages) */
-#define CHECK_FREE_SWAPSPACE 10240
-
-static unsigned int check_free_memory = 0;
-
-enum pageout_io {
- PAGEOUT_IO_ASYNC,
- PAGEOUT_IO_SYNC,
-};
-
-
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
-#ifdef ENHANCED_LMK_ROUTINE
-static struct task_struct *lowmem_deathpending[LOWMEM_DEATHPENDING_DEPTH] = {NULL,};
-#else
static struct task_struct *lowmem_deathpending;
-#endif
static unsigned long lowmem_deathpending_timeout;
#define lowmem_print(level, x...) \
do { \
if (lowmem_debug_level >= (level)) \
- printk(x); \
+ pr_info(x); \
} while (0)
static int
@@ -117,44 +77,31 @@ task_notify_func(struct notifier_block *self, unsigned long val, void *data)
{
struct task_struct *task = data;
-#ifdef ENHANCED_LMK_ROUTINE
- int i = 0;
- for (i = 0; i < LOWMEM_DEATHPENDING_DEPTH; i++)
- if (task == lowmem_deathpending[i]) {
- lowmem_deathpending[i] = NULL;
- break;
- }
-#else
if (task == lowmem_deathpending)
lowmem_deathpending = NULL;
-#endif
return NOTIFY_OK;
}
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+static struct task_struct *pick_next_from_adj_tree(struct task_struct *task);
+static struct task_struct *pick_first_task(void);
+static struct task_struct *pick_last_task(void);
+#endif
+
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
- struct task_struct *p;
-#ifdef ENHANCED_LMK_ROUTINE
- struct task_struct *selected[LOWMEM_DEATHPENDING_DEPTH] = {NULL,};
-#else
+ struct task_struct *tsk;
struct task_struct *selected = NULL;
-#endif
int rem = 0;
int tasksize;
int i;
- int min_adj = OOM_ADJUST_MAX + 1;
-#ifdef ENHANCED_LMK_ROUTINE
- int selected_tasksize[LOWMEM_DEATHPENDING_DEPTH] = {0,};
- int selected_oom_adj[LOWMEM_DEATHPENDING_DEPTH] = {OOM_ADJUST_MAX,};
- int all_selected_oom = 0;
- int max_selected_oom_idx = 0;
-#else
+ int min_score_adj = OOM_SCORE_ADJ_MAX + 1;
+ int minfree = 0;
int selected_tasksize = 0;
- int selected_oom_adj;
-#endif
+ int selected_oom_score_adj;
int array_size = ARRAY_SIZE(lowmem_adj);
#ifndef CONFIG_DMA_CMA
- int other_free = global_page_state(NR_FREE_PAGES);
+ int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
#else
int other_free = global_page_state(NR_FREE_PAGES) -
global_page_state(NR_FREE_CMA_PAGES);
@@ -169,152 +116,111 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
* this pass.
*
*/
-#ifdef ENHANCED_LMK_ROUTINE
- for (i = 0; i < LOWMEM_DEATHPENDING_DEPTH; i++) {
- if (lowmem_deathpending[i] &&
- time_before_eq(jiffies, lowmem_deathpending_timeout))
- return 0;
- }
-#else
if (lowmem_deathpending &&
time_before_eq(jiffies, lowmem_deathpending_timeout))
return 0;
-#endif
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
array_size = lowmem_minfree_size;
for (i = 0; i < array_size; i++) {
- if (other_free < lowmem_minfree[i] &&
- other_file < lowmem_minfree[i]) {
- min_adj = lowmem_adj[i];
+ minfree = lowmem_minfree[i];
+ if (other_free < minfree && other_file < minfree) {
+ min_score_adj = lowmem_adj[i];
break;
}
}
if (sc->nr_to_scan > 0)
lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %d\n",
- sc->nr_to_scan, sc->gfp_mask, other_free, other_file,
- min_adj);
+ sc->nr_to_scan, sc->gfp_mask, other_free,
+ other_file, min_score_adj);
rem = global_page_state(NR_ACTIVE_ANON) +
global_page_state(NR_ACTIVE_FILE) +
global_page_state(NR_INACTIVE_ANON) +
global_page_state(NR_INACTIVE_FILE);
- if (sc->nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
+ if (sc->nr_to_scan <= 0 || min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
lowmem_print(5, "lowmem_shrink %lu, %x, return %d\n",
sc->nr_to_scan, sc->gfp_mask, rem);
return rem;
}
-#ifdef ENHANCED_LMK_ROUTINE
- for (i = 0; i < LOWMEM_DEATHPENDING_DEPTH; i++)
- selected_oom_adj[i] = min_adj;
+ selected_oom_score_adj = min_score_adj;
+ rcu_read_lock();
+
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ for (tsk = pick_first_task();
+ tsk != pick_last_task() && tsk != NULL;
+ tsk = pick_next_from_adj_tree(tsk)) {
#else
- selected_oom_adj = min_adj;
+ for_each_process(tsk) {
#endif
+ struct task_struct *p;
+ int oom_score_adj;
+ if (tsk->flags & PF_KTHREAD)
+ continue;
- read_lock(&tasklist_lock);
- for_each_process(p) {
- struct mm_struct *mm;
- struct signal_struct *sig;
- int oom_adj;
-#ifdef ENHANCED_LMK_ROUTINE
- int is_exist_oom_task = 0;
-#endif
- task_lock(p);
- mm = p->mm;
- sig = p->signal;
- if (!mm || !sig) {
+ p = find_lock_task_mm(tsk);
+ if (!p)
+ continue;
+
+ oom_score_adj = p->signal->oom_score_adj;
+ if (oom_score_adj < min_score_adj) {
task_unlock(p);
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ break;
+#else
continue;
+#endif
}
- oom_adj = sig->oom_adj;
- if (oom_adj < min_adj) {
+ if (fatal_signal_pending(p)) {
+ lowmem_print(2, "skip slow dying process %d\n", p->pid);
task_unlock(p);
continue;
}
- tasksize = get_mm_rss(mm);
+ tasksize = get_mm_rss(p->mm);
task_unlock(p);
if (tasksize <= 0)
continue;
-#ifdef ENHANCED_LMK_ROUTINE
- if (all_selected_oom < LOWMEM_DEATHPENDING_DEPTH) {
- for (i = 0; i < LOWMEM_DEATHPENDING_DEPTH; i++) {
- if (!selected[i]) {
- is_exist_oom_task = 1;
- max_selected_oom_idx = i;
- break;
- }
- }
- } else if (selected_oom_adj[max_selected_oom_idx] < oom_adj ||
- (selected_oom_adj[max_selected_oom_idx] == oom_adj &&
- selected_tasksize[max_selected_oom_idx] < tasksize)) {
- is_exist_oom_task = 1;
- }
-
- if (is_exist_oom_task) {
- selected[max_selected_oom_idx] = p;
- selected_tasksize[max_selected_oom_idx] = tasksize;
- selected_oom_adj[max_selected_oom_idx] = oom_adj;
-
- if (all_selected_oom < LOWMEM_DEATHPENDING_DEPTH)
- all_selected_oom++;
-
- if (all_selected_oom == LOWMEM_DEATHPENDING_DEPTH) {
- for (i = 0; i < LOWMEM_DEATHPENDING_DEPTH; i++) {
- if (selected_oom_adj[i] < selected_oom_adj[max_selected_oom_idx])
- max_selected_oom_idx = i;
- else if (selected_oom_adj[i] == selected_oom_adj[max_selected_oom_idx] &&
- selected_tasksize[i] < selected_tasksize[max_selected_oom_idx])
- max_selected_oom_idx = i;
- }
- }
-
- lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
- p->pid, p->comm, oom_adj, tasksize);
- }
-#else
if (selected) {
- if (oom_adj < selected_oom_adj)
+ if (oom_score_adj < selected_oom_score_adj)
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ break;
+#else
continue;
- if (oom_adj == selected_oom_adj &&
+#endif
+ if (oom_score_adj == selected_oom_score_adj &&
tasksize <= selected_tasksize)
continue;
}
selected = p;
selected_tasksize = tasksize;
- selected_oom_adj = oom_adj;
- lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
- p->pid, p->comm, oom_adj, tasksize);
-#endif
+ selected_oom_score_adj = oom_score_adj;
+ lowmem_print(2, "select '%s' (%d), adj %d, size %d, to kill\n",
+ p->comm, p->pid, oom_score_adj, tasksize);
}
-#ifdef ENHANCED_LMK_ROUTINE
- for (i = 0; i < LOWMEM_DEATHPENDING_DEPTH; i++) {
- if (selected[i]) {
- lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
- selected[i]->pid, selected[i]->comm,
- selected_oom_adj[i], selected_tasksize[i]);
- lowmem_deathpending[i] = selected[i];
- lowmem_deathpending_timeout = jiffies + HZ;
- force_sig(SIGKILL, selected[i]);
- rem -= selected_tasksize[i];
- }
- }
-#else
if (selected) {
- lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
- selected->pid, selected->comm,
- selected_oom_adj, selected_tasksize);
+ lowmem_print(1, "Killing '%s' (%d), adj %d,\n" \
+ " to free %ldkB on behalf of '%s' (%d) because\n" \
+ " cache %ldkB is below limit %ldkB for oom_score_adj %d\n" \
+ " Free memory is %ldkB above reserved\n",
+ selected->comm, selected->pid,
+ selected_oom_score_adj,
+ selected_tasksize * (long)(PAGE_SIZE / 1024),
+ current->comm, current->pid,
+ other_file * (long)(PAGE_SIZE / 1024),
+ minfree * (long)(PAGE_SIZE / 1024),
+ min_score_adj,
+ other_free * (long)(PAGE_SIZE / 1024));
lowmem_deathpending = selected;
lowmem_deathpending_timeout = jiffies + HZ;
- force_sig(SIGKILL, selected);
+ send_sig(SIGKILL, selected, 0);
rem -= selected_tasksize;
}
-#endif
lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
sc->nr_to_scan, sc->gfp_mask, rem);
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return rem;
}
@@ -323,241 +229,203 @@ static struct shrinker lowmem_shrinker = {
.seeks = DEFAULT_SEEKS * 16
};
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-/*
- * zone_id_shrink_pagelist() clear page flags,
- * update the memory zone status, and swap pagelist
- */
-
-static unsigned int shrink_pages(struct mm_struct *mm,
- struct list_head *zone0_page_list,
- struct list_head *zone1_page_list,
- unsigned int num_to_scan)
+static int __init lowmem_init(void)
{
- unsigned long addr;
- unsigned int isolate_pages_countter = 0;
-
- struct vm_area_struct *vma = mm->mmap;
- while (vma != NULL) {
-
- for (addr = vma->vm_start; addr < vma->vm_end;
- addr += PAGE_SIZE) {
- struct page *page;
- /*get the page address from virtual memory address */
- page = follow_page(vma, addr, FOLL_GET);
-
- if (page && !IS_ERR(page)) {
-
- put_page(page);
- /* only moveable, anonymous and not dirty pages can be swapped */
- if ((!PageUnevictable(page))
- && (!PageDirty(page)) && ((PageAnon(page)))
- && (0 == page_is_file_cache(page))) {
- switch (page_zone_id(page)) {
- case 0:
- if (!isolate_lru_page_compcache(page)) {
- /* isolate page from LRU and add to temp list */
- /*create new page list, it will be used in shrink_page_list */
- list_add_tail(&page->lru, zone0_page_list);
- isolate_pages_countter++;
- }
- break;
- case 1:
- if (!isolate_lru_page_compcache(page)) {
- /* isolate page from LRU and add to temp list */
- /*create new page list, it will be used in shrink_page_list */
- list_add_tail(&page->lru, zone1_page_list);
- isolate_pages_countter++;
- }
- break;
- default:
- break;
- }
- }
- }
-
- if (isolate_pages_countter >= num_to_scan) {
- return isolate_pages_countter;
- }
- }
+ task_free_register(&task_nb);
+ register_shrinker(&lowmem_shrinker);
+ return 0;
+}
- vma = vma->vm_next;
- }
+static void __exit lowmem_exit(void)
+{
+ unregister_shrinker(&lowmem_shrinker);
+ task_free_unregister(&task_nb);
+}
- return isolate_pages_countter;
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+static int lowmem_oom_adj_to_oom_score_adj(int oom_adj)
+{
+ if (oom_adj == OOM_ADJUST_MAX)
+ return OOM_SCORE_ADJ_MAX;
+ else
+ return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
}
-/*
- * swap_application_pages() will search the
- * pages which can be swapped, then call
- * zone_id_shrink_pagelist to update zone
- * status
- */
-static unsigned int swap_pages(struct list_head *zone0_page_list,
- struct list_head *zone1_page_list)
+static void lowmem_autodetect_oom_adj_values(void)
{
- struct zone *zone_id_0 = &NODE_DATA(0)->node_zones[0];
- struct zone *zone_id_1 = &NODE_DATA(0)->node_zones[1];
- unsigned int pages_counter = 0;
-
- /*if the page list is not empty, call zone_id_shrink_pagelist to update zone status */
- if ((zone_id_0) && (!list_empty(zone0_page_list))) {
- pages_counter +=
- zone_id_shrink_pagelist(zone_id_0, zone0_page_list);
- }
- if ((zone_id_1) && (!list_empty(zone1_page_list))) {
- pages_counter +=
- zone_id_shrink_pagelist(zone_id_1, zone1_page_list);
+ int i;
+ int oom_adj;
+ int oom_score_adj;
+ int array_size = ARRAY_SIZE(lowmem_adj);
+
+ if (lowmem_adj_size < array_size)
+ array_size = lowmem_adj_size;
+
+ if (array_size <= 0)
+ return;
+
+ oom_adj = lowmem_adj[array_size - 1];
+ if (oom_adj > OOM_ADJUST_MAX)
+ return;
+
+ oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
+ if (oom_score_adj <= OOM_ADJUST_MAX)
+ return;
+
+ lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n");
+ for (i = 0; i < array_size; i++) {
+ oom_adj = lowmem_adj[i];
+ oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
+ lowmem_adj[i] = oom_score_adj;
+ lowmem_print(1, "oom_adj %d => oom_score_adj %d\n",
+ oom_adj, oom_score_adj);
}
- return pages_counter;
}
-static ssize_t lmk_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp)
{
- return sprintf(buf, "%d,%d\n", lmk_kill_pid, lmk_kill_ok);
+ int ret;
+
+ ret = param_array_ops.set(val, kp);
+
+ /* HACK: Autodetect oom_adj values in lowmem_adj array */
+ lowmem_autodetect_oom_adj_values();
+
+ return ret;
}
-/*
- * lmk_state_store() will called by framework,
- * the framework will send the pid of process that need to be swapped
- */
-static ssize_t lmk_state_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp)
{
- sscanf(buf, "%d,%d", &lmk_kill_pid, &lmk_kill_ok);
+ return param_array_ops.get(buffer, kp);
+}
- /* if the screen on, the optimized compcache will stop */
- if (atomic_read(&optimize_comp_on) != 1)
- return size;
+static void lowmem_adj_array_free(void *arg)
+{
+ param_array_ops.free(arg);
+}
- if (lmk_kill_ok == 1) {
- struct task_struct *p;
- struct task_struct *selected = NULL;
- struct sysinfo ramzswap_info = { 0 };
- struct mm_struct *mm_scan = NULL;
-
- /*
- * check the free RAM and swap area,
- * stop the optimized compcache in cpu idle case;
- * leave some swap area for using in low memory case
- */
- si_swapinfo(&ramzswap_info);
- si_meminfo(&ramzswap_info);
-
- if ((ramzswap_info.freeswap < CHECK_FREE_SWAPSPACE) ||
- (ramzswap_info.freeram < check_free_memory)) {
-#if SWAP_PROCESS_DEBUG_LOG > 0
- printk(KERN_INFO "idletime compcache is ignored : free RAM %lu, free swap %lu\n",
- ramzswap_info.freeram, ramzswap_info.freeswap);
-#endif
- lmk_kill_ok = 0;
- return size;
- }
+static struct kernel_param_ops lowmem_adj_array_ops = {
+ .set = lowmem_adj_array_set,
+ .get = lowmem_adj_array_get,
+ .free = lowmem_adj_array_free,
+};
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if ((p->pid == lmk_kill_pid) &&
- (__task_cred(p)->uid > 10000)) {
- task_lock(p);
- selected = p;
- if (!selected->mm || !selected->signal) {
- task_unlock(p);
- selected = NULL;
- break;
- }
- mm_scan = selected->mm;
- if (mm_scan) {
- if (selected->flags & PF_KTHREAD)
- mm_scan = NULL;
- else
- atomic_inc(&mm_scan->mm_users);
- }
- task_unlock(selected);
-
-#if SWAP_PROCESS_DEBUG_LOG > 0
- printk(KERN_INFO "idle time compcache: swap process pid %d, name %s, oom %d, task size %ld\n",
- p->pid, p->comm,
- p->signal->oom_adj,
- get_mm_rss(p->mm));
+static const struct kparam_array __param_arr_adj = {
+ .max = ARRAY_SIZE(lowmem_adj),
+ .num = &lowmem_adj_size,
+ .ops = &param_ops_int,
+ .elemsize = sizeof(lowmem_adj[0]),
+ .elem = lowmem_adj,
+};
#endif
- break;
- }
- }
- read_unlock(&tasklist_lock);
-
- if (mm_scan) {
- LIST_HEAD(zone0_page_list);
- LIST_HEAD(zone1_page_list);
- int pages_tofree = 0, pages_freed = 0;
-
- down_read(&mm_scan->mmap_sem);
- pages_tofree =
- shrink_pages(mm_scan, &zone0_page_list,
- &zone1_page_list, 0x7FFFFFFF);
- up_read(&mm_scan->mmap_sem);
- mmput(mm_scan);
- pages_freed =
- swap_pages(&zone0_page_list,
- &zone1_page_list);
- lmk_kill_ok = 0;
- }
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+DEFINE_SPINLOCK(lmk_lock);
+struct rb_root tasks_scoreadj = RB_ROOT;
+/*
+ * Makesure to invoke the function with holding sighand->siglock
+ */
+void add_2_adj_tree(struct task_struct *task)
+{
+ struct rb_node **link;
+ struct rb_node *parent = NULL;
+ struct signal_struct *sig_entry;
+ s64 key = task->signal->oom_score_adj;
+
+ /*
+ * Find the right place in the rbtree:
+ */
+ spin_lock(&lmk_lock);
+ link = &tasks_scoreadj.rb_node;
+ while (*link) {
+ parent = *link;
+ sig_entry = rb_entry(parent, struct signal_struct, adj_node);
+
+ if (key < sig_entry->oom_score_adj)
+ link = &parent->rb_right;
+ else
+ link = &parent->rb_left;
}
- return size;
+ rb_link_node(&task->signal->adj_node, parent, link);
+ rb_insert_color(&task->signal->adj_node, &tasks_scoreadj);
+ spin_unlock(&lmk_lock);
}
-static DEVICE_ATTR(lmk_state, 0664, lmk_state_show, lmk_state_store);
+/*
+ * Makesure to invoke the function with holding sighand->siglock
+ */
+void delete_from_adj_tree(struct task_struct *task)
+{
+ spin_lock(&lmk_lock);
+ if (!RB_EMPTY_NODE(&task->signal->adj_node)) {
+ rb_erase(&task->signal->adj_node, &tasks_scoreadj);
+ RB_CLEAR_NODE(&task->signal->adj_node);
+ }
+ spin_unlock(&lmk_lock);
+}
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-static int __init lowmem_init(void)
+static struct task_struct *pick_next_from_adj_tree(struct task_struct *task)
{
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- struct zone *zone;
- unsigned int high_wmark = 0;
-#endif
- task_free_register(&task_nb);
- register_shrinker(&lowmem_shrinker);
+ struct rb_node *next;
+ struct signal_struct *next_tsk_sig;
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- for_each_zone(zone) {
- if (high_wmark < zone->watermark[WMARK_HIGH])
- high_wmark = zone->watermark[WMARK_HIGH];
- }
- check_free_memory = (high_wmark != 0) ? high_wmark : CHECK_FREE_MEMORY;
+ spin_lock(&lmk_lock);
+ next = rb_next(&task->signal->adj_node);
+ spin_unlock(&lmk_lock);
- lmk_class = class_create(THIS_MODULE, "lmk");
- if (IS_ERR(lmk_class)) {
- printk(KERN_ERR "Failed to create class(lmk)\n");
- return 0;
- }
- lmk_dev = device_create(lmk_class, NULL, 0, NULL, "lowmemorykiller");
- if (IS_ERR(lmk_dev)) {
- printk(KERN_ERR
- "Failed to create device(lowmemorykiller)!= %ld\n",
- IS_ERR(lmk_dev));
- return 0;
- }
- if (device_create_file(lmk_dev, &dev_attr_lmk_state) < 0)
- printk(KERN_ERR "Failed to create device file(%s)!\n",
- dev_attr_lmk_state.attr.name);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
+ if (!next)
+ return NULL;
- return 0;
+ next_tsk_sig = rb_entry(next, struct signal_struct, adj_node);
+ return next_tsk_sig->curr_target->group_leader;
}
-static void __exit lowmem_exit(void)
+static struct task_struct *pick_first_task(void)
{
- unregister_shrinker(&lowmem_shrinker);
- task_free_unregister(&task_nb);
+ struct rb_node *left;
+ struct signal_struct *first_tsk_sig;
+
+ spin_lock(&lmk_lock);
+ left = rb_first(&tasks_scoreadj);
+ spin_unlock(&lmk_lock);
+
+ if (!left)
+ return NULL;
+
+ first_tsk_sig = rb_entry(left, struct signal_struct, adj_node);
+ return first_tsk_sig->curr_target->group_leader;
+}
+
+static struct task_struct *pick_last_task(void)
+{
+ struct rb_node *right;
+ struct signal_struct *last_tsk_sig;
+
+ spin_lock(&lmk_lock);
+ right = rb_last(&tasks_scoreadj);
+ spin_unlock(&lmk_lock);
+
+ if (!right)
+ return NULL;
+
+ last_tsk_sig = rb_entry(right, struct signal_struct, adj_node);
+ return last_tsk_sig->curr_target->group_leader;
}
+#endif
module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+__module_param_call(MODULE_PARAM_PREFIX, adj,
+ &lowmem_adj_array_ops,
+ .arr = &__param_arr_adj,
+ S_IRUGO | S_IWUSR, 0664);
+__MODULE_PARM_TYPE(adj, "array of int");
+#else
module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,
S_IRUGO | S_IWUSR);
+#endif
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
S_IRUGO | S_IWUSR);
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 80c2ee5..c43c7e3 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -617,11 +617,7 @@ err:
static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
{
u32 offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long base_pgoff;
- int status;
-
- struct omap_dsp_platform_data *pdata =
- omap_dspbridge_dev->dev.platform_data;
+ u32 status;
DBC_ASSERT(vma->vm_start < vma->vm_end);
@@ -632,27 +628,11 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
"%lx flags %lx\n", __func__, filp, offset,
vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags);
- /*
- * vm_iomap_memory() expects vma->vm_pgoff to be expressed as an offset
- * from the start of the physical memory pool, but we're called with
- * a pfn (physical page number) stored there instead.
- *
- * To avoid duplicating lots of tricky overflow checking logic,
- * temporarily convert vma->vm_pgoff to the offset vm_iomap_memory()
- * expects, but restore the original value once the mapping has been
- * created.
- */
- base_pgoff = pdata->phys_mempool_base >> PAGE_SHIFT;
- if (vma->vm_pgoff < base_pgoff)
- return -EINVAL;
- vma->vm_pgoff -= base_pgoff;
-
- status = vm_iomap_memory(vma,
- pdata->phys_mempool_base,
- pdata->phys_mempool_size);
-
- /* Restore the original value of vma->vm_pgoff */
- vma->vm_pgoff += base_pgoff;
+ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ if (status != 0)
+ status = -EAGAIN;
return status;
}
diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig
index 7fabcb2..4881839 100644
--- a/drivers/staging/zcache/Kconfig
+++ b/drivers/staging/zcache/Kconfig
@@ -1,13 +1,11 @@
config ZCACHE
- tristate "Dynamic compression of swap pages and clean pagecache pages"
- depends on CLEANCACHE || FRONTSWAP
- select XVMALLOC
- select LZO_COMPRESS
- select LZO_DECOMPRESS
+ bool "Dynamic compression of swap pages and clean pagecache pages"
+ depends on (CLEANCACHE || FRONTSWAP) && CRYPTO=y && ZSMALLOC=y
+ select CRYPTO_LZO
default n
help
Zcache doubles RAM efficiency while providing a significant
- performance boosts on many workloads. Zcache uses lzo1x
+ performance boosts on many workloads. Zcache uses
compression and an in-kernel implementation of transcendent
memory to store clean page cache pages and swap in RAM,
providing a noticeable reduction in disk I/O.
diff --git a/drivers/staging/zcache/Makefile b/drivers/staging/zcache/Makefile
index f5ec64f..60daa27 100644
--- a/drivers/staging/zcache/Makefile
+++ b/drivers/staging/zcache/Makefile
@@ -1,3 +1,3 @@
-zcache-y := tmem.o
+zcache-y := zcache-main.o tmem.o
obj-$(CONFIG_ZCACHE) += zcache.o
diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c
index e954d40..1ca66ea 100644
--- a/drivers/staging/zcache/tmem.c
+++ b/drivers/staging/zcache/tmem.c
@@ -142,6 +142,7 @@ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb,
obj->oid = *oidp;
obj->objnode_count = 0;
obj->pampd_count = 0;
+ (*tmem_pamops.new_obj)(obj);
SET_SENTINEL(obj, OBJ);
while (*new) {
BUG_ON(RB_EMPTY_NODE(*new));
@@ -274,7 +275,7 @@ static void tmem_objnode_free(struct tmem_objnode *objnode)
/*
* lookup index in object and return associated pampd (or NULL if not found)
*/
-static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
+static void **__tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
{
unsigned int height, shift;
struct tmem_objnode **slot = NULL;
@@ -303,9 +304,33 @@ static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
height--;
}
out:
+ return slot != NULL ? (void **)slot : NULL;
+}
+
+static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
+{
+ struct tmem_objnode **slot;
+
+ slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index);
return slot != NULL ? *slot : NULL;
}
+static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index,
+ void *new_pampd)
+{
+ struct tmem_objnode **slot;
+ void *ret = NULL;
+
+ slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index);
+ if ((slot != NULL) && (*slot != NULL)) {
+ void *old_pampd = *(void **)slot;
+ *(void **)slot = new_pampd;
+ (*tmem_pamops.free)(old_pampd, obj->pool, NULL, 0);
+ ret = new_pampd;
+ }
+ return ret;
+}
+
static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index,
void *pampd)
{
@@ -456,7 +481,7 @@ static void tmem_objnode_node_destroy(struct tmem_obj *obj,
if (ht == 1) {
obj->pampd_count--;
(*tmem_pamops.free)(objnode->slots[i],
- obj->pool);
+ obj->pool, NULL, 0);
objnode->slots[i] = NULL;
continue;
}
@@ -473,7 +498,7 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
return;
if (obj->objnode_tree_height == 0) {
obj->pampd_count--;
- (*tmem_pamops.free)(obj->objnode_tree_root, obj->pool);
+ (*tmem_pamops.free)(obj->objnode_tree_root, obj->pool, NULL, 0);
} else {
tmem_objnode_node_destroy(obj, obj->objnode_tree_root,
obj->objnode_tree_height);
@@ -481,6 +506,7 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
obj->objnode_tree_height = 0;
}
obj->objnode_tree_root = NULL;
+ (*tmem_pamops.free_obj)(obj->pool, obj);
}
/*
@@ -503,15 +529,13 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
* always flushes for simplicity.
*/
int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
- struct page *page)
+ char *data, size_t size, bool raw, bool ephemeral)
{
struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL;
void *pampd = NULL, *pampd_del = NULL;
int ret = -ENOMEM;
- bool ephemeral;
struct tmem_hashbucket *hb;
- ephemeral = is_ephemeral(pool);
hb = &pool->hashbucket[tmem_oid_hash(oidp)];
spin_lock(&hb->lock);
obj = objfound = tmem_obj_find(hb, oidp);
@@ -521,7 +545,7 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
/* if found, is a dup put, flush the old one */
pampd_del = tmem_pampd_delete_from_obj(obj, index);
BUG_ON(pampd_del != pampd);
- (*tmem_pamops.free)(pampd, pool);
+ (*tmem_pamops.free)(pampd, pool, oidp, index);
if (obj->pampd_count == 0) {
objnew = obj;
objfound = NULL;
@@ -538,7 +562,8 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
}
BUG_ON(obj == NULL);
BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound));
- pampd = (*tmem_pamops.create)(obj->pool, &obj->oid, index, page);
+ pampd = (*tmem_pamops.create)(data, size, raw, ephemeral,
+ obj->pool, &obj->oid, index);
if (unlikely(pampd == NULL))
goto free;
ret = tmem_pampd_add_to_obj(obj, index, pampd);
@@ -551,7 +576,7 @@ delete_and_free:
(void)tmem_pampd_delete_from_obj(obj, index);
free:
if (pampd)
- (*tmem_pamops.free)(pampd, pool);
+ (*tmem_pamops.free)(pampd, pool, NULL, 0);
if (objnew) {
tmem_obj_free(objnew, hb);
(*tmem_hostops.obj_free)(objnew, pool);
@@ -573,41 +598,52 @@ out:
* "put" done with the same handle).
*/
-int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp,
- uint32_t index, struct page *page)
+int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
+ char *data, size_t *size, bool raw, int get_and_free)
{
struct tmem_obj *obj;
void *pampd;
bool ephemeral = is_ephemeral(pool);
- uint32_t ret = -1;
+ int ret = -1;
struct tmem_hashbucket *hb;
+ bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral);
+ bool lock_held = false;
hb = &pool->hashbucket[tmem_oid_hash(oidp)];
spin_lock(&hb->lock);
+ lock_held = true;
obj = tmem_obj_find(hb, oidp);
if (obj == NULL)
goto out;
- ephemeral = is_ephemeral(pool);
- if (ephemeral)
+ if (free)
pampd = tmem_pampd_delete_from_obj(obj, index);
else
pampd = tmem_pampd_lookup_in_obj(obj, index);
if (pampd == NULL)
goto out;
- ret = (*tmem_pamops.get_data)(page, pampd, pool);
- if (ret < 0)
- goto out;
- if (ephemeral) {
- (*tmem_pamops.free)(pampd, pool);
+ if (free) {
if (obj->pampd_count == 0) {
tmem_obj_free(obj, hb);
(*tmem_hostops.obj_free)(obj, pool);
obj = NULL;
}
}
+ if (tmem_pamops.is_remote(pampd)) {
+ lock_held = false;
+ spin_unlock(&hb->lock);
+ }
+ if (free)
+ ret = (*tmem_pamops.get_data_and_free)(
+ data, size, raw, pampd, pool, oidp, index);
+ else
+ ret = (*tmem_pamops.get_data)(
+ data, size, raw, pampd, pool, oidp, index);
+ if (ret < 0)
+ goto out;
ret = 0;
out:
- spin_unlock(&hb->lock);
+ if (lock_held)
+ spin_unlock(&hb->lock);
return ret;
}
@@ -632,7 +668,7 @@ int tmem_flush_page(struct tmem_pool *pool,
pampd = tmem_pampd_delete_from_obj(obj, index);
if (pampd == NULL)
goto out;
- (*tmem_pamops.free)(pampd, pool);
+ (*tmem_pamops.free)(pampd, pool, oidp, index);
if (obj->pampd_count == 0) {
tmem_obj_free(obj, hb);
(*tmem_hostops.obj_free)(obj, pool);
@@ -645,6 +681,30 @@ out:
}
/*
+ * If a page in tmem matches the handle, replace the page so that any
+ * subsequent "get" gets the new page. Returns 0 if
+ * there was a page to replace, else returns -1.
+ */
+int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp,
+ uint32_t index, void *new_pampd)
+{
+ struct tmem_obj *obj;
+ int ret = -1;
+ struct tmem_hashbucket *hb;
+
+ hb = &pool->hashbucket[tmem_oid_hash(oidp)];
+ spin_lock(&hb->lock);
+ obj = tmem_obj_find(hb, oidp);
+ if (obj == NULL)
+ goto out;
+ new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd);
+ ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj);
+out:
+ spin_unlock(&hb->lock);
+ return ret;
+}
+
+/*
* "Flush" all pages in tmem matching this oid.
*/
int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp)
diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h
index 2e07e21..0d4aa82 100644
--- a/drivers/staging/zcache/tmem.h
+++ b/drivers/staging/zcache/tmem.h
@@ -47,7 +47,7 @@
#define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0)
#endif
-#define ASSERT_SPINLOCK(_l) WARN_ON(!spin_is_locked(_l))
+#define ASSERT_SPINLOCK(_l) lockdep_assert_held(_l)
/*
* A pool is the highest-level data structure managed by tmem and
@@ -147,6 +147,7 @@ struct tmem_obj {
unsigned int objnode_tree_height;
unsigned long objnode_count;
long pampd_count;
+ void *extra; /* for private use by pampd implementation */
DECL_SENTINEL
};
@@ -166,10 +167,18 @@ struct tmem_objnode {
/* pampd abstract datatype methods provided by the PAM implementation */
struct tmem_pamops {
- void *(*create)(struct tmem_pool *, struct tmem_oid *, uint32_t,
- struct page *);
- int (*get_data)(struct page *, void *, struct tmem_pool *);
- void (*free)(void *, struct tmem_pool *);
+ void *(*create)(char *, size_t, bool, int,
+ struct tmem_pool *, struct tmem_oid *, uint32_t);
+ int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *,
+ struct tmem_oid *, uint32_t);
+ int (*get_data_and_free)(char *, size_t *, bool, void *,
+ struct tmem_pool *, struct tmem_oid *,
+ uint32_t);
+ void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t);
+ void (*free_obj)(struct tmem_pool *, struct tmem_obj *);
+ bool (*is_remote)(void *);
+ void (*new_obj)(struct tmem_obj *);
+ int (*replace_in_obj)(void *, struct tmem_obj *);
};
extern void tmem_register_pamops(struct tmem_pamops *m);
@@ -184,9 +193,11 @@ extern void tmem_register_hostops(struct tmem_hostops *m);
/* core tmem accessor functions */
extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index,
- struct page *page);
+ char *, size_t, bool, bool);
extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index,
- struct page *page);
+ char *, size_t *, bool, int);
+extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index,
+ void *);
extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *,
uint32_t index);
extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);
diff --git a/drivers/staging/zcache/zcache.c b/drivers/staging/zcache/zcache-main.c
index 77ac2d4..eb65043 100644
--- a/drivers/staging/zcache/zcache.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -6,9 +6,10 @@
*
* Zcache provides an in-kernel "host implementation" for transcendent memory
* and, thus indirectly, for cleancache and frontswap. Zcache includes two
- * page-accessible memory [1] interfaces, both utilizing lzo1x compression:
+ * page-accessible memory [1] interfaces, both utilizing the crypto compression
+ * API:
* 1) "compression buddies" ("zbud") is used for ephemeral pages
- * 2) xvmalloc is used for persistent pages.
+ * 2) zsmalloc is used for persistent pages.
* Xvmalloc (based on the TLSF allocator) has very low fragmentation
* so maximizes space efficiency, while zbud allows pairs (and potentially,
* in the future, more than a pair of) compressed pages to be closely linked
@@ -19,17 +20,20 @@
* http://marc.info/?l=linux-mm&m=127811271605009
*/
+#include <linux/module.h>
#include <linux/cpu.h>
#include <linux/highmem.h>
#include <linux/list.h>
-#include <linux/lzo.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/atomic.h>
+#include <linux/math64.h>
+#include <linux/crypto.h>
+#include <linux/string.h>
#include "tmem.h"
-#include "../zram/xvmalloc.h" /* if built in drivers/staging */
+#include <linux/zsmalloc.h>
#if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP))
#error "zcache is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP"
@@ -49,6 +53,68 @@
(__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC)
#endif
+#define MAX_POOLS_PER_CLIENT 16
+
+#define MAX_CLIENTS 16
+#define LOCAL_CLIENT ((uint16_t)-1)
+
+MODULE_LICENSE("GPL");
+
+struct zcache_client {
+ struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
+ struct zs_pool *zspool;
+ bool allocated;
+ atomic_t refcount;
+};
+
+static struct zcache_client zcache_host;
+static struct zcache_client zcache_clients[MAX_CLIENTS];
+
+static inline uint16_t get_client_id_from_client(struct zcache_client *cli)
+{
+ BUG_ON(cli == NULL);
+ if (cli == &zcache_host)
+ return LOCAL_CLIENT;
+ return cli - &zcache_clients[0];
+}
+
+static inline bool is_local_client(struct zcache_client *cli)
+{
+ return cli == &zcache_host;
+}
+
+/* crypto API for zcache */
+#define ZCACHE_COMP_NAME_SZ CRYPTO_MAX_ALG_NAME
+static char zcache_comp_name[ZCACHE_COMP_NAME_SZ];
+static struct crypto_comp * __percpu *zcache_comp_pcpu_tfms;
+
+enum comp_op {
+ ZCACHE_COMPOP_COMPRESS,
+ ZCACHE_COMPOP_DECOMPRESS
+};
+
+static inline int zcache_comp_op(enum comp_op op,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{
+ struct crypto_comp *tfm;
+ int ret;
+
+ BUG_ON(!zcache_comp_pcpu_tfms);
+ tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, get_cpu());
+ BUG_ON(!tfm);
+ switch (op) {
+ case ZCACHE_COMPOP_COMPRESS:
+ ret = crypto_comp_compress(tfm, src, slen, dst, dlen);
+ break;
+ case ZCACHE_COMPOP_DECOMPRESS:
+ ret = crypto_comp_decompress(tfm, src, slen, dst, dlen);
+ break;
+ }
+ put_cpu();
+ return ret;
+}
+
/**********
* Compression buddies ("zbud") provides for packing two (or, possibly
* in the future, more) compressed ephemeral pages into a single "raw"
@@ -72,7 +138,8 @@
#define ZBUD_MAX_BUDS 2
struct zbud_hdr {
- uint32_t pool_id;
+ uint16_t client_id;
+ uint16_t pool_id;
struct tmem_oid oid;
uint32_t index;
uint16_t size; /* compressed size in bytes, zero means unused */
@@ -120,6 +187,7 @@ static unsigned long zcache_zbud_curr_zbytes;
static unsigned long zcache_zbud_cumul_zpages;
static unsigned long zcache_zbud_cumul_zbytes;
static unsigned long zcache_compress_poor;
+static unsigned long zcache_mean_compress_poor;
/* forward references */
static void *zcache_get_free_page(void);
@@ -265,10 +333,12 @@ static void zbud_free_and_delist(struct zbud_hdr *zh)
struct zbud_page *zbpg =
container_of(zh, struct zbud_page, buddy[budnum]);
+ spin_lock(&zbud_budlists_spinlock);
spin_lock(&zbpg->lock);
if (list_empty(&zbpg->bud_list)) {
/* ignore zombie page... see zbud_evict_pages() */
spin_unlock(&zbpg->lock);
+ spin_unlock(&zbud_budlists_spinlock);
return;
}
size = zbud_free(zh);
@@ -276,7 +346,6 @@ static void zbud_free_and_delist(struct zbud_hdr *zh)
zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0];
if (zh_other->size == 0) { /* was unbuddied: unlist and free */
chunks = zbud_size_to_chunks(size) ;
- spin_lock(&zbud_budlists_spinlock);
BUG_ON(list_empty(&zbud_unbuddied[chunks].list));
list_del_init(&zbpg->bud_list);
zbud_unbuddied[chunks].count--;
@@ -284,7 +353,6 @@ static void zbud_free_and_delist(struct zbud_hdr *zh)
zbud_free_raw_page(zbpg);
} else { /* was buddied: move remaining buddy to unbuddied list */
chunks = zbud_size_to_chunks(zh_other->size) ;
- spin_lock(&zbud_budlists_spinlock);
list_del_init(&zbpg->bud_list);
zcache_zbud_buddied_count--;
list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list);
@@ -294,7 +362,8 @@ static void zbud_free_and_delist(struct zbud_hdr *zh)
}
}
-static struct zbud_hdr *zbud_create(uint32_t pool_id, struct tmem_oid *oid,
+static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id,
+ struct tmem_oid *oid,
uint32_t index, struct page *page,
void *cdata, unsigned size)
{
@@ -323,8 +392,8 @@ static struct zbud_hdr *zbud_create(uint32_t pool_id, struct tmem_oid *oid,
if (unlikely(zbpg == NULL))
goto out;
/* ok, have a page, now compress the data before taking locks */
- spin_lock(&zbpg->lock);
spin_lock(&zbud_budlists_spinlock);
+ spin_lock(&zbpg->lock);
list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list);
zbud_unbuddied[nchunks].count++;
zh = &zbpg->buddy[0];
@@ -353,12 +422,12 @@ init_zh:
zh->index = index;
zh->oid = *oid;
zh->pool_id = pool_id;
- /* can wait to copy the data until the list locks are dropped */
- spin_unlock(&zbud_budlists_spinlock);
-
+ zh->client_id = client_id;
to = zbud_data(zh, size);
memcpy(to, cdata, size);
spin_unlock(&zbpg->lock);
+ spin_unlock(&zbud_budlists_spinlock);
+
zbud_cumul_chunk_counts[nchunks]++;
atomic_inc(&zcache_zbud_curr_zpages);
zcache_zbud_cumul_zpages++;
@@ -372,7 +441,7 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
{
struct zbud_page *zbpg;
unsigned budnum = zbud_budnum(zh);
- size_t out_len = PAGE_SIZE;
+ unsigned int out_len = PAGE_SIZE;
char *to_va, *from_va;
unsigned size;
int ret = 0;
@@ -389,8 +458,9 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
to_va = kmap_atomic(page, KM_USER0);
size = zh->size;
from_va = zbud_data(zh, size);
- ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len);
- BUG_ON(ret != LZO_E_OK);
+ ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, from_va, size,
+ to_va, &out_len);
+ BUG_ON(ret);
BUG_ON(out_len != PAGE_SIZE);
kunmap_atomic(to_va, KM_USER0);
out:
@@ -407,7 +477,8 @@ static unsigned long zcache_evicted_raw_pages;
static unsigned long zcache_evicted_buddied_pages;
static unsigned long zcache_evicted_unbuddied_pages;
-static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid);
+static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id,
+ uint16_t poolid);
static void zcache_put_pool(struct tmem_pool *pool);
/*
@@ -417,7 +488,8 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg)
{
struct zbud_hdr *zh;
int i, j;
- uint32_t pool_id[ZBUD_MAX_BUDS], index[ZBUD_MAX_BUDS];
+ uint32_t pool_id[ZBUD_MAX_BUDS], client_id[ZBUD_MAX_BUDS];
+ uint32_t index[ZBUD_MAX_BUDS];
struct tmem_oid oid[ZBUD_MAX_BUDS];
struct tmem_pool *pool;
@@ -426,6 +498,7 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg)
for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) {
zh = &zbpg->buddy[i];
if (zh->size) {
+ client_id[j] = zh->client_id;
pool_id[j] = zh->pool_id;
oid[j] = zh->oid;
index[j] = zh->index;
@@ -435,7 +508,7 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg)
}
spin_unlock(&zbpg->lock);
for (i = 0; i < j; i++) {
- pool = zcache_get_pool_by_id(pool_id[i]);
+ pool = zcache_get_pool_by_id(client_id[i], pool_id[i]);
if (pool != NULL) {
tmem_flush_page(pool, &oid[i], index[i]);
zcache_put_pool(pool);
@@ -552,9 +625,8 @@ static int zbud_show_unbuddied_list_counts(char *buf)
int i;
char *p = buf;
- for (i = 0; i < NCHUNKS - 1; i++)
+ for (i = 0; i < NCHUNKS; i++)
p += sprintf(p, "%u ", zbud_unbuddied[i].count);
- p += sprintf(p, "%d\n", zbud_unbuddied[i].count);
return p - buf;
}
@@ -585,8 +657,8 @@ static int zbud_show_cumul_chunk_counts(char *buf)
#endif
/**********
- * This "zv" PAM implementation combines the TLSF-based xvMalloc
- * with lzo1x compression to maximize the amount of data that can
+ * This "zv" PAM implementation combines the slab-based zsmalloc
+ * with the crypto compression API to maximize the amount of data that can
* be packed into a physical page.
*
* Zv represents a PAM page with the index and object (plus a "size" value
@@ -599,72 +671,250 @@ struct zv_hdr {
uint32_t pool_id;
struct tmem_oid oid;
uint32_t index;
+ size_t size;
DECL_SENTINEL
};
-static const int zv_max_page_size = (PAGE_SIZE / 8) * 7;
+/* rudimentary policy limits */
+/* total number of persistent pages may not exceed this percentage */
+static unsigned int zv_page_count_policy_percent = 75;
+/*
+ * byte count defining poor compression; pages with greater zsize will be
+ * rejected
+ */
+static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7;
+/*
+ * byte count defining poor *mean* compression; pages with greater zsize
+ * will be rejected until sufficient better-compressed pages are accepted
+ * driving the mean below this threshold
+ */
+static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5;
+
+static atomic_t zv_curr_dist_counts[NCHUNKS];
+static atomic_t zv_cumul_dist_counts[NCHUNKS];
-static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
+static unsigned long zv_create(struct zs_pool *pool, uint32_t pool_id,
struct tmem_oid *oid, uint32_t index,
void *cdata, unsigned clen)
{
- struct page *page;
- struct zv_hdr *zv = NULL;
- uint32_t offset;
- int ret;
+ struct zv_hdr *zv;
+ u32 size = clen + sizeof(struct zv_hdr);
+ int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT;
+ unsigned long handle = 0;
BUG_ON(!irqs_disabled());
- ret = xv_malloc(xvpool, clen + sizeof(struct zv_hdr),
- &page, &offset, ZCACHE_GFP_MASK);
- if (unlikely(ret))
+ BUG_ON(chunks >= NCHUNKS);
+ handle = zs_malloc(pool, size);
+ if (!handle)
goto out;
- zv = kmap_atomic(page, KM_USER0) + offset;
+ atomic_inc(&zv_curr_dist_counts[chunks]);
+ atomic_inc(&zv_cumul_dist_counts[chunks]);
+ zv = zs_map_object(pool, handle, ZS_MM_WO);
zv->index = index;
zv->oid = *oid;
zv->pool_id = pool_id;
+ zv->size = clen;
SET_SENTINEL(zv, ZVH);
memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen);
- kunmap_atomic(zv, KM_USER0);
+ zs_unmap_object(pool, handle);
out:
- return zv;
+ return handle;
}
-static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)
+static void zv_free(struct zs_pool *pool, unsigned long handle)
{
unsigned long flags;
- struct page *page;
- uint32_t offset;
+ struct zv_hdr *zv;
uint16_t size;
+ int chunks;
+ zv = zs_map_object(pool, handle, ZS_MM_RW);
ASSERT_SENTINEL(zv, ZVH);
- size = xv_get_object_size(zv) - sizeof(*zv);
- BUG_ON(size == 0 || size > zv_max_page_size);
+ size = zv->size + sizeof(struct zv_hdr);
INVERT_SENTINEL(zv, ZVH);
- page = virt_to_page(zv);
- offset = (unsigned long)zv & ~PAGE_MASK;
+ zs_unmap_object(pool, handle);
+
+ chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT;
+ BUG_ON(chunks >= NCHUNKS);
+ atomic_dec(&zv_curr_dist_counts[chunks]);
+
local_irq_save(flags);
- xv_free(xvpool, page, offset);
+ zs_free(pool, handle);
local_irq_restore(flags);
}
-static void zv_decompress(struct page *page, struct zv_hdr *zv)
+static void zv_decompress(struct page *page, unsigned long handle)
{
- size_t clen = PAGE_SIZE;
+ unsigned int clen = PAGE_SIZE;
char *to_va;
- unsigned size;
int ret;
+ struct zv_hdr *zv;
+ zv = zs_map_object(zcache_host.zspool, handle, ZS_MM_RO);
+ BUG_ON(zv->size == 0);
ASSERT_SENTINEL(zv, ZVH);
- size = xv_get_object_size(zv) - sizeof(*zv);
- BUG_ON(size == 0 || size > zv_max_page_size);
to_va = kmap_atomic(page, KM_USER0);
- ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv),
- size, to_va, &clen);
+ ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, (char *)zv + sizeof(*zv),
+ zv->size, to_va, &clen);
kunmap_atomic(to_va, KM_USER0);
- BUG_ON(ret != LZO_E_OK);
+ zs_unmap_object(zcache_host.zspool, handle);
+ BUG_ON(ret);
BUG_ON(clen != PAGE_SIZE);
}
+#ifdef CONFIG_SYSFS
+/*
+ * show a distribution of compression stats for zv pages.
+ */
+
+static int zv_curr_dist_counts_show(char *buf)
+{
+ unsigned long i, n, chunks = 0, sum_total_chunks = 0;
+ char *p = buf;
+
+ for (i = 0; i < NCHUNKS; i++) {
+ n = atomic_read(&zv_curr_dist_counts[i]);
+ p += sprintf(p, "%lu ", n);
+ chunks += n;
+ sum_total_chunks += i * n;
+ }
+ p += sprintf(p, "mean:%lu\n",
+ chunks == 0 ? 0 : sum_total_chunks / chunks);
+ return p - buf;
+}
+
+static int zv_cumul_dist_counts_show(char *buf)
+{
+ unsigned long i, n, chunks = 0, sum_total_chunks = 0;
+ char *p = buf;
+
+ for (i = 0; i < NCHUNKS; i++) {
+ n = atomic_read(&zv_cumul_dist_counts[i]);
+ p += sprintf(p, "%lu ", n);
+ chunks += n;
+ sum_total_chunks += i * n;
+ }
+ p += sprintf(p, "mean:%lu\n",
+ chunks == 0 ? 0 : sum_total_chunks / chunks);
+ return p - buf;
+}
+
+/*
+ * setting zv_max_zsize via sysfs causes all persistent (e.g. swap)
+ * pages that don't compress to less than this value (including metadata
+ * overhead) to be rejected. We don't allow the value to get too close
+ * to PAGE_SIZE.
+ */
+static ssize_t zv_max_zsize_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", zv_max_zsize);
+}
+
+static ssize_t zv_max_zsize_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7))
+ return -EINVAL;
+ zv_max_zsize = val;
+ return count;
+}
+
+/*
+ * setting zv_max_mean_zsize via sysfs causes all persistent (e.g. swap)
+ * pages that don't compress to less than this value (including metadata
+ * overhead) to be rejected UNLESS the mean compression is also smaller
+ * than this value. In other words, we are load-balancing-by-zsize the
+ * accepted pages. Again, we don't allow the value to get too close
+ * to PAGE_SIZE.
+ */
+static ssize_t zv_max_mean_zsize_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", zv_max_mean_zsize);
+}
+
+static ssize_t zv_max_mean_zsize_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7))
+ return -EINVAL;
+ zv_max_mean_zsize = val;
+ return count;
+}
+
+/*
+ * setting zv_page_count_policy_percent via sysfs sets an upper bound of
+ * persistent (e.g. swap) pages that will be retained according to:
+ * (zv_page_count_policy_percent * totalram_pages) / 100)
+ * when that limit is reached, further puts will be rejected (until
+ * some pages have been flushed). Note that, due to compression,
+ * this number may exceed 100; it defaults to 75 and we set an
+ * arbitary limit of 150. A poor choice will almost certainly result
+ * in OOM's, so this value should only be changed prudently.
+ */
+static ssize_t zv_page_count_policy_percent_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", zv_page_count_policy_percent);
+}
+
+static ssize_t zv_page_count_policy_percent_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err || (val == 0) || (val > 150))
+ return -EINVAL;
+ zv_page_count_policy_percent = val;
+ return count;
+}
+
+static struct kobj_attribute zcache_zv_max_zsize_attr = {
+ .attr = { .name = "zv_max_zsize", .mode = 0644 },
+ .show = zv_max_zsize_show,
+ .store = zv_max_zsize_store,
+};
+
+static struct kobj_attribute zcache_zv_max_mean_zsize_attr = {
+ .attr = { .name = "zv_max_mean_zsize", .mode = 0644 },
+ .show = zv_max_mean_zsize_show,
+ .store = zv_max_mean_zsize_store,
+};
+
+static struct kobj_attribute zcache_zv_page_count_policy_percent_attr = {
+ .attr = { .name = "zv_page_count_policy_percent",
+ .mode = 0644 },
+ .show = zv_page_count_policy_percent_show,
+ .store = zv_page_count_policy_percent_store,
+};
+#endif
+
/*
* zcache core code starts here
*/
@@ -677,51 +927,76 @@ static unsigned long zcache_flobj_found;
static unsigned long zcache_failed_eph_puts;
static unsigned long zcache_failed_pers_puts;
-#define MAX_POOLS_PER_CLIENT 16
-
-static struct {
- struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
- struct xv_pool *xvpool;
-} zcache_client;
-
/*
* Tmem operations assume the poolid implies the invoking client.
- * Zcache only has one client (the kernel itself), so translate
- * the poolid into the tmem_pool allocated for it. A KVM version
+ * Zcache only has one client (the kernel itself): LOCAL_CLIENT.
+ * RAMster has each client numbered by cluster node, and a KVM version
* of zcache would have one client per guest and each client might
* have a poolid==N.
*/
-static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid)
+static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid)
{
struct tmem_pool *pool = NULL;
+ struct zcache_client *cli = NULL;
- if (poolid >= 0) {
- pool = zcache_client.tmem_pools[poolid];
+ if (cli_id == LOCAL_CLIENT)
+ cli = &zcache_host;
+ else {
+ if (cli_id >= MAX_CLIENTS)
+ goto out;
+ cli = &zcache_clients[cli_id];
+ if (cli == NULL)
+ goto out;
+ atomic_inc(&cli->refcount);
+ }
+ if (poolid < MAX_POOLS_PER_CLIENT) {
+ pool = cli->tmem_pools[poolid];
if (pool != NULL)
atomic_inc(&pool->refcount);
}
+out:
return pool;
}
static void zcache_put_pool(struct tmem_pool *pool)
{
- if (pool != NULL)
- atomic_dec(&pool->refcount);
+ struct zcache_client *cli = NULL;
+
+ if (pool == NULL)
+ BUG();
+ cli = pool->client;
+ atomic_dec(&pool->refcount);
+ atomic_dec(&cli->refcount);
+}
+
+int zcache_new_client(uint16_t cli_id)
+{
+ struct zcache_client *cli = NULL;
+ int ret = -1;
+
+ if (cli_id == LOCAL_CLIENT)
+ cli = &zcache_host;
+ else if ((unsigned int)cli_id < MAX_CLIENTS)
+ cli = &zcache_clients[cli_id];
+ if (cli == NULL)
+ goto out;
+ if (cli->allocated)
+ goto out;
+ cli->allocated = 1;
+#ifdef CONFIG_FRONTSWAP
+ cli->zspool = zs_create_pool("zcache", ZCACHE_GFP_MASK);
+ if (cli->zspool == NULL)
+ goto out;
+#endif
+ ret = 0;
+out:
+ return ret;
}
/* counters for debugging */
static unsigned long zcache_failed_get_free_pages;
static unsigned long zcache_failed_alloc;
static unsigned long zcache_put_to_flush;
-static unsigned long zcache_aborted_preload;
-static unsigned long zcache_aborted_shrink;
-
-/*
- * Ensure that memory allocation requests in zcache don't result
- * in direct reclaim requests via the shrinker, which would cause
- * an infinite loop. Maybe a GFP flag would be better?
- */
-static DEFINE_SPINLOCK(zcache_direct_reclaim_lock);
/*
* for now, used named slabs so can easily track usage; later can
@@ -760,10 +1035,6 @@ static int zcache_do_preload(struct tmem_pool *pool)
goto out;
if (unlikely(zcache_obj_cache == NULL))
goto out;
- if (!spin_trylock(&zcache_direct_reclaim_lock)) {
- zcache_aborted_preload++;
- goto out;
- }
preempt_disable();
kp = &__get_cpu_var(zcache_preloads);
while (kp->nr < ARRAY_SIZE(kp->objnodes)) {
@@ -772,7 +1043,7 @@ static int zcache_do_preload(struct tmem_pool *pool)
ZCACHE_GFP_MASK);
if (unlikely(objnode == NULL)) {
zcache_failed_alloc++;
- goto unlock_out;
+ goto out;
}
preempt_disable();
kp = &__get_cpu_var(zcache_preloads);
@@ -785,13 +1056,13 @@ static int zcache_do_preload(struct tmem_pool *pool)
obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK);
if (unlikely(obj == NULL)) {
zcache_failed_alloc++;
- goto unlock_out;
+ goto out;
}
page = (void *)__get_free_page(ZCACHE_GFP_MASK);
if (unlikely(page == NULL)) {
zcache_failed_get_free_pages++;
kmem_cache_free(zcache_obj_cache, obj);
- goto unlock_out;
+ goto out;
}
preempt_disable();
kp = &__get_cpu_var(zcache_preloads);
@@ -804,8 +1075,6 @@ static int zcache_do_preload(struct tmem_pool *pool)
else
free_page((unsigned long)page);
ret = 0;
-unlock_out:
- spin_unlock(&zcache_direct_reclaim_lock);
out:
return ret;
}
@@ -899,50 +1168,63 @@ static atomic_t zcache_curr_pers_pampd_count = ATOMIC_INIT(0);
static unsigned long zcache_curr_pers_pampd_count_max;
/* forward reference */
-static int zcache_compress(struct page *from, void **out_va, size_t *out_len);
+static int zcache_compress(struct page *from, void **out_va, unsigned *out_len);
-static void *zcache_pampd_create(struct tmem_pool *pool, struct tmem_oid *oid,
- uint32_t index, struct page *page)
+static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph,
+ struct tmem_pool *pool, struct tmem_oid *oid,
+ uint32_t index)
{
void *pampd = NULL, *cdata;
- size_t clen;
+ unsigned clen;
int ret;
- bool ephemeral = is_ephemeral(pool);
unsigned long count;
-
- if (ephemeral) {
+ struct page *page = (struct page *)(data);
+ struct zcache_client *cli = pool->client;
+ uint16_t client_id = get_client_id_from_client(cli);
+ unsigned long zv_mean_zsize;
+ unsigned long curr_pers_pampd_count;
+ u64 total_zsize;
+
+ if (eph) {
ret = zcache_compress(page, &cdata, &clen);
if (ret == 0)
-
goto out;
if (clen == 0 || clen > zbud_max_buddy_size()) {
zcache_compress_poor++;
goto out;
}
- pampd = (void *)zbud_create(pool->pool_id, oid, index,
- page, cdata, clen);
+ pampd = (void *)zbud_create(client_id, pool->pool_id, oid,
+ index, page, cdata, clen);
if (pampd != NULL) {
count = atomic_inc_return(&zcache_curr_eph_pampd_count);
if (count > zcache_curr_eph_pampd_count_max)
zcache_curr_eph_pampd_count_max = count;
}
} else {
- /*
- * FIXME: This is all the "policy" there is for now.
- * 3/4 totpages should allow ~37% of RAM to be filled with
- * compressed frontswap pages
- */
- if (atomic_read(&zcache_curr_pers_pampd_count) >
- 3 * totalram_pages / 4)
+ curr_pers_pampd_count =
+ atomic_read(&zcache_curr_pers_pampd_count);
+ if (curr_pers_pampd_count >
+ (zv_page_count_policy_percent * totalram_pages) / 100)
goto out;
ret = zcache_compress(page, &cdata, &clen);
if (ret == 0)
goto out;
- if (clen > zv_max_page_size) {
+ /* reject if compression is too poor */
+ if (clen > zv_max_zsize) {
zcache_compress_poor++;
goto out;
}
- pampd = (void *)zv_create(zcache_client.xvpool, pool->pool_id,
+ /* reject if mean compression is too poor */
+ if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) {
+ total_zsize = zs_get_total_pages(cli->zspool) << PAGE_SHIFT;
+ zv_mean_zsize = div_u64(total_zsize,
+ curr_pers_pampd_count);
+ if (zv_mean_zsize > zv_max_mean_zsize) {
+ zcache_mean_compress_poor++;
+ goto out;
+ }
+ }
+ pampd = (void *)zv_create(cli->zspool, pool->pool_id,
oid, index, cdata, clen);
if (pampd == NULL)
goto out;
@@ -958,64 +1240,104 @@ out:
* fill the pageframe corresponding to the struct page with the data
* from the passed pampd
*/
-static int zcache_pampd_get_data(struct page *page, void *pampd,
- struct tmem_pool *pool)
+static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw,
+ void *pampd, struct tmem_pool *pool,
+ struct tmem_oid *oid, uint32_t index)
{
int ret = 0;
- if (is_ephemeral(pool))
- ret = zbud_decompress(page, pampd);
- else
- zv_decompress(page, pampd);
+ BUG_ON(is_ephemeral(pool));
+ zv_decompress((struct page *)(data), (unsigned long)pampd);
return ret;
}
/*
+ * fill the pageframe corresponding to the struct page with the data
+ * from the passed pampd
+ */
+static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw,
+ void *pampd, struct tmem_pool *pool,
+ struct tmem_oid *oid, uint32_t index)
+{
+ BUG_ON(!is_ephemeral(pool));
+ if (zbud_decompress((struct page *)(data), pampd) < 0)
+ return -EINVAL;
+ zbud_free_and_delist((struct zbud_hdr *)pampd);
+ atomic_dec(&zcache_curr_eph_pampd_count);
+ return 0;
+}
+
+/*
* free the pampd and remove it from any zcache lists
* pampd must no longer be pointed to from any tmem data structures!
*/
-static void zcache_pampd_free(void *pampd, struct tmem_pool *pool)
+static void zcache_pampd_free(void *pampd, struct tmem_pool *pool,
+ struct tmem_oid *oid, uint32_t index)
{
+ struct zcache_client *cli = pool->client;
+
if (is_ephemeral(pool)) {
zbud_free_and_delist((struct zbud_hdr *)pampd);
atomic_dec(&zcache_curr_eph_pampd_count);
BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0);
} else {
- zv_free(zcache_client.xvpool, (struct zv_hdr *)pampd);
+ zv_free(cli->zspool, (unsigned long)pampd);
atomic_dec(&zcache_curr_pers_pampd_count);
BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0);
}
}
+static void zcache_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj)
+{
+}
+
+static void zcache_pampd_new_obj(struct tmem_obj *obj)
+{
+}
+
+static int zcache_pampd_replace_in_obj(void *pampd, struct tmem_obj *obj)
+{
+ return -1;
+}
+
+static bool zcache_pampd_is_remote(void *pampd)
+{
+ return 0;
+}
+
static struct tmem_pamops zcache_pamops = {
.create = zcache_pampd_create,
.get_data = zcache_pampd_get_data,
+ .get_data_and_free = zcache_pampd_get_data_and_free,
.free = zcache_pampd_free,
+ .free_obj = zcache_pampd_free_obj,
+ .new_obj = zcache_pampd_new_obj,
+ .replace_in_obj = zcache_pampd_replace_in_obj,
+ .is_remote = zcache_pampd_is_remote,
};
/*
* zcache compression/decompression and related per-cpu stuff
*/
-#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS
-#define LZO_DSTMEM_PAGE_ORDER 1
-static DEFINE_PER_CPU(unsigned char *, zcache_workmem);
static DEFINE_PER_CPU(unsigned char *, zcache_dstmem);
+#define ZCACHE_DSTMEM_ORDER 1
-static int zcache_compress(struct page *from, void **out_va, size_t *out_len)
+static int zcache_compress(struct page *from, void **out_va, unsigned *out_len)
{
int ret = 0;
unsigned char *dmem = __get_cpu_var(zcache_dstmem);
- unsigned char *wmem = __get_cpu_var(zcache_workmem);
char *from_va;
BUG_ON(!irqs_disabled());
- if (unlikely(dmem == NULL || wmem == NULL))
- goto out; /* no buffer, so can't compress */
+ if (unlikely(dmem == NULL))
+ goto out; /* no buffer or no compressor so can't compress */
+ *out_len = PAGE_SIZE << ZCACHE_DSTMEM_ORDER;
from_va = kmap_atomic(from, KM_USER0);
mb();
- ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem);
- BUG_ON(ret != LZO_E_OK);
+ ret = zcache_comp_op(ZCACHE_COMPOP_COMPRESS, from_va, PAGE_SIZE, dmem,
+ out_len);
+ BUG_ON(ret);
*out_va = dmem;
kunmap_atomic(from_va, KM_USER0);
ret = 1;
@@ -1023,29 +1345,48 @@ out:
return ret;
}
+static int zcache_comp_cpu_up(int cpu)
+{
+ struct crypto_comp *tfm;
+
+ tfm = crypto_alloc_comp(zcache_comp_name, 0, 0);
+ if (IS_ERR(tfm))
+ return NOTIFY_BAD;
+ *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = tfm;
+ return NOTIFY_OK;
+}
+
+static void zcache_comp_cpu_down(int cpu)
+{
+ struct crypto_comp *tfm;
+
+ tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu);
+ crypto_free_comp(tfm);
+ *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = NULL;
+}
static int zcache_cpu_notifier(struct notifier_block *nb,
unsigned long action, void *pcpu)
{
- int cpu = (long)pcpu;
+ int ret, cpu = (long)pcpu;
struct zcache_preload *kp;
switch (action) {
case CPU_UP_PREPARE:
+ ret = zcache_comp_cpu_up(cpu);
+ if (ret != NOTIFY_OK) {
+ pr_err("zcache: can't allocate compressor transform\n");
+ return ret;
+ }
per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages(
- GFP_KERNEL | __GFP_REPEAT,
- LZO_DSTMEM_PAGE_ORDER),
- per_cpu(zcache_workmem, cpu) =
- kzalloc(LZO1X_MEM_COMPRESS,
- GFP_KERNEL | __GFP_REPEAT);
+ GFP_KERNEL | __GFP_REPEAT, ZCACHE_DSTMEM_ORDER);
break;
case CPU_DEAD:
case CPU_UP_CANCELED:
+ zcache_comp_cpu_down(cpu);
free_pages((unsigned long)per_cpu(zcache_dstmem, cpu),
- LZO_DSTMEM_PAGE_ORDER);
+ ZCACHE_DSTMEM_ORDER);
per_cpu(zcache_dstmem, cpu) = NULL;
- kfree(per_cpu(zcache_workmem, cpu));
- per_cpu(zcache_workmem, cpu) = NULL;
kp = &per_cpu(zcache_preloads, cpu);
while (kp->nr) {
kmem_cache_free(zcache_objnode_cache,
@@ -1053,8 +1394,14 @@ static int zcache_cpu_notifier(struct notifier_block *nb,
kp->objnodes[kp->nr - 1] = NULL;
kp->nr--;
}
- kmem_cache_free(zcache_obj_cache, kp->obj);
- free_page((unsigned long)kp->page);
+ if (kp->obj) {
+ kmem_cache_free(zcache_obj_cache, kp->obj);
+ kp->obj = NULL;
+ }
+ if (kp->page) {
+ free_page((unsigned long)kp->page);
+ kp->page = NULL;
+ }
break;
default:
break;
@@ -1119,9 +1466,8 @@ ZCACHE_SYSFS_RO(evicted_buddied_pages);
ZCACHE_SYSFS_RO(failed_get_free_pages);
ZCACHE_SYSFS_RO(failed_alloc);
ZCACHE_SYSFS_RO(put_to_flush);
-ZCACHE_SYSFS_RO(aborted_preload);
-ZCACHE_SYSFS_RO(aborted_shrink);
ZCACHE_SYSFS_RO(compress_poor);
+ZCACHE_SYSFS_RO(mean_compress_poor);
ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages);
ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages);
ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count);
@@ -1130,6 +1476,10 @@ ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts,
zbud_show_unbuddied_list_counts);
ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts,
zbud_show_cumul_chunk_counts);
+ZCACHE_SYSFS_RO_CUSTOM(zv_curr_dist_counts,
+ zv_curr_dist_counts_show);
+ZCACHE_SYSFS_RO_CUSTOM(zv_cumul_dist_counts,
+ zv_cumul_dist_counts_show);
static struct attribute *zcache_attrs[] = {
&zcache_curr_obj_count_attr.attr,
@@ -1143,6 +1493,7 @@ static struct attribute *zcache_attrs[] = {
&zcache_failed_eph_puts_attr.attr,
&zcache_failed_pers_puts_attr.attr,
&zcache_compress_poor_attr.attr,
+ &zcache_mean_compress_poor_attr.attr,
&zcache_zbud_curr_raw_pages_attr.attr,
&zcache_zbud_curr_zpages_attr.attr,
&zcache_zbud_curr_zbytes_attr.attr,
@@ -1156,10 +1507,13 @@ static struct attribute *zcache_attrs[] = {
&zcache_failed_get_free_pages_attr.attr,
&zcache_failed_alloc_attr.attr,
&zcache_put_to_flush_attr.attr,
- &zcache_aborted_preload_attr.attr,
- &zcache_aborted_shrink_attr.attr,
&zcache_zbud_unbuddied_list_counts_attr.attr,
&zcache_zbud_cumul_chunk_counts_attr.attr,
+ &zcache_zv_curr_dist_counts_attr.attr,
+ &zcache_zv_cumul_dist_counts_attr.attr,
+ &zcache_zv_max_zsize_attr.attr,
+ &zcache_zv_max_mean_zsize_attr.attr,
+ &zcache_zv_page_count_policy_percent_attr.attr,
NULL,
};
@@ -1192,11 +1546,7 @@ static int shrink_zcache_memory(struct shrinker *shrink,
if (!(gfp_mask & __GFP_FS))
/* does this case really need to be skipped? */
goto out;
- if (spin_trylock(&zcache_direct_reclaim_lock)) {
- zbud_evict_pages(nr);
- spin_unlock(&zcache_direct_reclaim_lock);
- } else
- zcache_aborted_shrink++;
+ zbud_evict_pages(nr);
}
ret = (int)atomic_read(&zcache_zbud_curr_raw_pages);
out:
@@ -1212,19 +1562,20 @@ static struct shrinker zcache_shrinker = {
* zcache shims between cleancache/frontswap ops and tmem
*/
-static int zcache_put_page(int pool_id, struct tmem_oid *oidp,
+static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
uint32_t index, struct page *page)
{
struct tmem_pool *pool;
int ret = -1;
BUG_ON(!irqs_disabled());
- pool = zcache_get_pool_by_id(pool_id);
+ pool = zcache_get_pool_by_id(cli_id, pool_id);
if (unlikely(pool == NULL))
goto out;
if (!zcache_freeze && zcache_do_preload(pool) == 0) {
/* preload does preempt_disable on success */
- ret = tmem_put(pool, oidp, index, page);
+ ret = tmem_put(pool, oidp, index, (char *)(page),
+ PAGE_SIZE, 0, is_ephemeral(pool));
if (ret < 0) {
if (is_ephemeral(pool))
zcache_failed_eph_puts++;
@@ -1244,25 +1595,28 @@ out:
return ret;
}
-static int zcache_get_page(int pool_id, struct tmem_oid *oidp,
+static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
uint32_t index, struct page *page)
{
struct tmem_pool *pool;
int ret = -1;
unsigned long flags;
+ size_t size = PAGE_SIZE;
local_irq_save(flags);
- pool = zcache_get_pool_by_id(pool_id);
+ pool = zcache_get_pool_by_id(cli_id, pool_id);
if (likely(pool != NULL)) {
if (atomic_read(&pool->obj_count) > 0)
- ret = tmem_get(pool, oidp, index, page);
+ ret = tmem_get(pool, oidp, index, (char *)(page),
+ &size, 0, is_ephemeral(pool));
zcache_put_pool(pool);
}
local_irq_restore(flags);
return ret;
}
-static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
+static int zcache_flush_page(int cli_id, int pool_id,
+ struct tmem_oid *oidp, uint32_t index)
{
struct tmem_pool *pool;
int ret = -1;
@@ -1270,7 +1624,7 @@ static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
local_irq_save(flags);
zcache_flush_total++;
- pool = zcache_get_pool_by_id(pool_id);
+ pool = zcache_get_pool_by_id(cli_id, pool_id);
if (likely(pool != NULL)) {
if (atomic_read(&pool->obj_count) > 0)
ret = tmem_flush_page(pool, oidp, index);
@@ -1282,7 +1636,8 @@ static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
return ret;
}
-static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
+static int zcache_flush_object(int cli_id, int pool_id,
+ struct tmem_oid *oidp)
{
struct tmem_pool *pool;
int ret = -1;
@@ -1290,7 +1645,7 @@ static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
local_irq_save(flags);
zcache_flobj_total++;
- pool = zcache_get_pool_by_id(pool_id);
+ pool = zcache_get_pool_by_id(cli_id, pool_id);
if (likely(pool != NULL)) {
if (atomic_read(&pool->obj_count) > 0)
ret = tmem_flush_object(pool, oidp);
@@ -1302,42 +1657,60 @@ static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
return ret;
}
-static int zcache_destroy_pool(int pool_id)
+static int zcache_destroy_pool(int cli_id, int pool_id)
{
struct tmem_pool *pool = NULL;
+ struct zcache_client *cli = NULL;
int ret = -1;
if (pool_id < 0)
goto out;
- pool = zcache_client.tmem_pools[pool_id];
+ if (cli_id == LOCAL_CLIENT)
+ cli = &zcache_host;
+ else if ((unsigned int)cli_id < MAX_CLIENTS)
+ cli = &zcache_clients[cli_id];
+ if (cli == NULL)
+ goto out;
+ atomic_inc(&cli->refcount);
+ pool = cli->tmem_pools[pool_id];
if (pool == NULL)
goto out;
- zcache_client.tmem_pools[pool_id] = NULL;
+ cli->tmem_pools[pool_id] = NULL;
/* wait for pool activity on other cpus to quiesce */
while (atomic_read(&pool->refcount) != 0)
;
+ atomic_dec(&cli->refcount);
local_bh_disable();
ret = tmem_destroy_pool(pool);
local_bh_enable();
kfree(pool);
- pr_info("zcache: destroyed pool id=%d\n", pool_id);
+ pr_info("zcache: destroyed pool id=%d, cli_id=%d\n",
+ pool_id, cli_id);
out:
return ret;
}
-static int zcache_new_pool(uint32_t flags)
+static int zcache_new_pool(uint16_t cli_id, uint32_t flags)
{
int poolid = -1;
struct tmem_pool *pool;
+ struct zcache_client *cli = NULL;
- pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL);
+ if (cli_id == LOCAL_CLIENT)
+ cli = &zcache_host;
+ else if ((unsigned int)cli_id < MAX_CLIENTS)
+ cli = &zcache_clients[cli_id];
+ if (cli == NULL)
+ goto out;
+ atomic_inc(&cli->refcount);
+ pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC);
if (pool == NULL) {
pr_info("zcache: pool creation failed: out of memory\n");
goto out;
}
for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++)
- if (zcache_client.tmem_pools[poolid] == NULL)
+ if (cli->tmem_pools[poolid] == NULL)
break;
if (poolid >= MAX_POOLS_PER_CLIENT) {
pr_info("zcache: pool creation failed: max exceeded\n");
@@ -1346,14 +1719,16 @@ static int zcache_new_pool(uint32_t flags)
goto out;
}
atomic_set(&pool->refcount, 0);
- pool->client = &zcache_client;
+ pool->client = cli;
pool->pool_id = poolid;
tmem_new_pool(pool, flags);
- zcache_client.tmem_pools[poolid] = pool;
- pr_info("zcache: created %s tmem pool, id=%d\n",
+ cli->tmem_pools[poolid] = pool;
+ pr_info("zcache: created %s tmem pool, id=%d, client=%d\n",
flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral",
- poolid);
+ poolid, cli_id);
out:
+ if (cli != NULL)
+ atomic_dec(&cli->refcount);
return poolid;
}
@@ -1373,8 +1748,10 @@ static void zcache_cleancache_put_page(int pool_id,
u32 ind = (u32) index;
struct tmem_oid oid = *(struct tmem_oid *)&key;
+ if (!PageWasActive(page))
+ return;
if (likely(ind == index))
- (void)zcache_put_page(pool_id, &oid, index, page);
+ (void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page);
}
static int zcache_cleancache_get_page(int pool_id,
@@ -1386,7 +1763,9 @@ static int zcache_cleancache_get_page(int pool_id,
int ret = -1;
if (likely(ind == index))
- ret = zcache_get_page(pool_id, &oid, index, page);
+ ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page);
+ if (ret == 0)
+ SetPageWasActive(page);
return ret;
}
@@ -1398,7 +1777,7 @@ static void zcache_cleancache_flush_page(int pool_id,
struct tmem_oid oid = *(struct tmem_oid *)&key;
if (likely(ind == index))
- (void)zcache_flush_page(pool_id, &oid, ind);
+ (void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind);
}
static void zcache_cleancache_flush_inode(int pool_id,
@@ -1406,13 +1785,13 @@ static void zcache_cleancache_flush_inode(int pool_id,
{
struct tmem_oid oid = *(struct tmem_oid *)&key;
- (void)zcache_flush_object(pool_id, &oid);
+ (void)zcache_flush_object(LOCAL_CLIENT, pool_id, &oid);
}
static void zcache_cleancache_flush_fs(int pool_id)
{
if (pool_id >= 0)
- (void)zcache_destroy_pool(pool_id);
+ (void)zcache_destroy_pool(LOCAL_CLIENT, pool_id);
}
static int zcache_cleancache_init_fs(size_t pagesize)
@@ -1420,7 +1799,7 @@ static int zcache_cleancache_init_fs(size_t pagesize)
BUG_ON(sizeof(struct cleancache_filekey) !=
sizeof(struct tmem_oid));
BUG_ON(pagesize != PAGE_SIZE);
- return zcache_new_pool(0);
+ return zcache_new_pool(LOCAL_CLIENT, 0);
}
static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
@@ -1429,15 +1808,15 @@ static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
BUG_ON(sizeof(struct cleancache_filekey) !=
sizeof(struct tmem_oid));
BUG_ON(pagesize != PAGE_SIZE);
- return zcache_new_pool(0);
+ return zcache_new_pool(LOCAL_CLIENT, 0);
}
static struct cleancache_ops zcache_cleancache_ops = {
.put_page = zcache_cleancache_put_page,
.get_page = zcache_cleancache_get_page,
- .flush_page = zcache_cleancache_flush_page,
- .flush_inode = zcache_cleancache_flush_inode,
- .flush_fs = zcache_cleancache_flush_fs,
+ .invalidate_page = zcache_cleancache_flush_page,
+ .invalidate_inode = zcache_cleancache_flush_inode,
+ .invalidate_fs = zcache_cleancache_flush_fs,
.init_shared_fs = zcache_cleancache_init_shared_fs,
.init_fs = zcache_cleancache_init_fs
};
@@ -1458,8 +1837,10 @@ static int zcache_frontswap_poolid = -1;
/*
* Swizzling increases objects per swaptype, increasing tmem concurrency
* for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS
+ * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from
+ * frontswap_get_page(), but has side-effects. Hence using 8.
*/
-#define SWIZ_BITS 4
+#define SWIZ_BITS 8
#define SWIZ_MASK ((1 << SWIZ_BITS) - 1)
#define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
#define iswiz(_ind) (_ind >> SWIZ_BITS)
@@ -1483,8 +1864,8 @@ static int zcache_frontswap_put_page(unsigned type, pgoff_t offset,
BUG_ON(!PageLocked(page));
if (likely(ind64 == ind)) {
local_irq_save(flags);
- ret = zcache_put_page(zcache_frontswap_poolid, &oid,
- iswiz(ind), page);
+ ret = zcache_put_page(LOCAL_CLIENT, zcache_frontswap_poolid,
+ &oid, iswiz(ind), page);
local_irq_restore(flags);
}
return ret;
@@ -1502,8 +1883,8 @@ static int zcache_frontswap_get_page(unsigned type, pgoff_t offset,
BUG_ON(!PageLocked(page));
if (likely(ind64 == ind))
- ret = zcache_get_page(zcache_frontswap_poolid, &oid,
- iswiz(ind), page);
+ ret = zcache_get_page(LOCAL_CLIENT, zcache_frontswap_poolid,
+ &oid, iswiz(ind), page);
return ret;
}
@@ -1515,8 +1896,8 @@ static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset)
struct tmem_oid oid = oswiz(type, ind);
if (likely(ind64 == ind))
- (void)zcache_flush_page(zcache_frontswap_poolid, &oid,
- iswiz(ind));
+ (void)zcache_flush_page(LOCAL_CLIENT, zcache_frontswap_poolid,
+ &oid, iswiz(ind));
}
/* flush all pages from the passed swaptype */
@@ -1527,7 +1908,8 @@ static void zcache_frontswap_flush_area(unsigned type)
for (ind = SWIZ_MASK; ind >= 0; ind--) {
oid = oswiz(type, ind);
- (void)zcache_flush_object(zcache_frontswap_poolid, &oid);
+ (void)zcache_flush_object(LOCAL_CLIENT,
+ zcache_frontswap_poolid, &oid);
}
}
@@ -1535,14 +1917,15 @@ static void zcache_frontswap_init(unsigned ignored)
{
/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
if (zcache_frontswap_poolid < 0)
- zcache_frontswap_poolid = zcache_new_pool(TMEM_POOL_PERSIST);
+ zcache_frontswap_poolid =
+ zcache_new_pool(LOCAL_CLIENT, TMEM_POOL_PERSIST);
}
static struct frontswap_ops zcache_frontswap_ops = {
.put_page = zcache_frontswap_put_page,
.get_page = zcache_frontswap_get_page,
- .flush_page = zcache_frontswap_flush_page,
- .flush_area = zcache_frontswap_flush_area,
+ .invalidate_page = zcache_frontswap_flush_page,
+ .invalidate_area = zcache_frontswap_flush_area,
.init = zcache_frontswap_init
};
@@ -1592,11 +1975,49 @@ static int __init no_frontswap(char *s)
__setup("nofrontswap", no_frontswap);
+static int __init enable_zcache_compressor(char *s)
+{
+ strncpy(zcache_comp_name, s, ZCACHE_COMP_NAME_SZ);
+ zcache_enabled = 1;
+ return 1;
+}
+__setup("zcache=", enable_zcache_compressor);
+
+
+static int zcache_comp_init(void)
+{
+ int ret = 0;
+
+ /* check crypto algorithm */
+ if (*zcache_comp_name != '\0') {
+ ret = crypto_has_comp(zcache_comp_name, 0, 0);
+ if (!ret)
+ pr_info("zcache: %s not supported\n",
+ zcache_comp_name);
+ }
+ if (!ret)
+ strcpy(zcache_comp_name, "lzo");
+ ret = crypto_has_comp(zcache_comp_name, 0, 0);
+ if (!ret) {
+ ret = 1;
+ goto out;
+ }
+ pr_info("zcache: using %s compressor\n", zcache_comp_name);
+
+ /* alloc percpu transforms */
+ ret = 0;
+ zcache_comp_pcpu_tfms = alloc_percpu(struct crypto_comp *);
+ if (!zcache_comp_pcpu_tfms)
+ ret = 1;
+out:
+ return ret;
+}
+
static int __init zcache_init(void)
{
-#ifdef CONFIG_SYSFS
int ret = 0;
+#ifdef CONFIG_SYSFS
ret = sysfs_create_group(mm_kobj, &zcache_attr_group);
if (ret) {
pr_err("zcache: can't create sysfs\n");
@@ -1614,6 +2035,11 @@ static int __init zcache_init(void)
pr_err("zcache: can't register cpu notifier\n");
goto out;
}
+ ret = zcache_comp_init();
+ if (ret) {
+ pr_err("zcache: compressor initialization failed\n");
+ goto out;
+ }
for_each_online_cpu(cpu) {
void *pcpu = (void *)(long)cpu;
zcache_cpu_notifier(&zcache_cpu_notifier_block,
@@ -1624,6 +2050,11 @@ static int __init zcache_init(void)
sizeof(struct tmem_objnode), 0, 0, NULL);
zcache_obj_cache = kmem_cache_create("zcache_obj",
sizeof(struct tmem_obj), 0, 0, NULL);
+ ret = zcache_new_client(LOCAL_CLIENT);
+ if (ret) {
+ pr_err("zcache: can't create client\n");
+ goto out;
+ }
#endif
#ifdef CONFIG_CLEANCACHE
if (zcache_enabled && use_cleancache) {
@@ -1642,16 +2073,11 @@ static int __init zcache_init(void)
if (zcache_enabled && use_frontswap) {
struct frontswap_ops old_ops;
- zcache_client.xvpool = xv_create_pool();
- if (zcache_client.xvpool == NULL) {
- pr_err("zcache: can't create xvpool\n");
- goto out;
- }
old_ops = zcache_frontswap_register_ops();
pr_info("zcache: frontswap enabled using kernel "
- "transcendent memory and xvmalloc\n");
+ "transcendent memory and zsmalloc\n");
if (old_ops.init != NULL)
- pr_warning("ktmem: frontswap_ops overridden");
+ pr_warning("zcache: frontswap_ops overridden");
}
#endif
out:
diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile
deleted file mode 100644
index 2a6d321..0000000
--- a/drivers/staging/zram/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-zram-y := zram_drv.o zram_sysfs.o
-
-obj-$(CONFIG_ZRAM) += zram.o
-obj-$(CONFIG_XVMALLOC) += xvmalloc.o \ No newline at end of file
diff --git a/drivers/staging/zram/xvmalloc.c b/drivers/staging/zram/xvmalloc.c
deleted file mode 100644
index 1f9c508..0000000
--- a/drivers/staging/zram/xvmalloc.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * xvmalloc memory allocator
- *
- * Copyright (C) 2008, 2009, 2010 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- */
-
-#ifdef CONFIG_ZRAM_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-#include <linux/errno.h>
-#include <linux/highmem.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "xvmalloc.h"
-#include "xvmalloc_int.h"
-
-static void stat_inc(u64 *value)
-{
- *value = *value + 1;
-}
-
-static void stat_dec(u64 *value)
-{
- *value = *value - 1;
-}
-
-static int test_flag(struct block_header *block, enum blockflags flag)
-{
- return block->prev & BIT(flag);
-}
-
-static void set_flag(struct block_header *block, enum blockflags flag)
-{
- block->prev |= BIT(flag);
-}
-
-static void clear_flag(struct block_header *block, enum blockflags flag)
-{
- block->prev &= ~BIT(flag);
-}
-
-/*
- * Given <page, offset> pair, provide a dereferencable pointer.
- * This is called from xv_malloc/xv_free path, so it
- * needs to be fast.
- */
-static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type)
-{
- unsigned char *base;
-
- base = kmap_atomic(page, type);
- return base + offset;
-}
-
-static void put_ptr_atomic(void *ptr, enum km_type type)
-{
- kunmap_atomic(ptr, type);
-}
-
-static u32 get_blockprev(struct block_header *block)
-{
- return block->prev & PREV_MASK;
-}
-
-static void set_blockprev(struct block_header *block, u16 new_offset)
-{
- block->prev = new_offset | (block->prev & FLAGS_MASK);
-}
-
-static struct block_header *BLOCK_NEXT(struct block_header *block)
-{
- return (struct block_header *)
- ((char *)block + block->size + XV_ALIGN);
-}
-
-/*
- * Get index of free list containing blocks of maximum size
- * which is less than or equal to given size.
- */
-static u32 get_index_for_insert(u32 size)
-{
- if (unlikely(size > XV_MAX_ALLOC_SIZE))
- size = XV_MAX_ALLOC_SIZE;
- size &= ~FL_DELTA_MASK;
- return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT;
-}
-
-/*
- * Get index of free list having blocks of size greater than
- * or equal to requested size.
- */
-static u32 get_index(u32 size)
-{
- if (unlikely(size < XV_MIN_ALLOC_SIZE))
- size = XV_MIN_ALLOC_SIZE;
- size = ALIGN(size, FL_DELTA);
- return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT;
-}
-
-/**
- * find_block - find block of at least given size
- * @pool: memory pool to search from
- * @size: size of block required
- * @page: page containing required block
- * @offset: offset within the page where block is located.
- *
- * Searches two level bitmap to locate block of at least
- * the given size. If such a block is found, it provides
- * <page, offset> to identify this block and returns index
- * in freelist where we found this block.
- * Otherwise, returns 0 and <page, offset> params are not touched.
- */
-static u32 find_block(struct xv_pool *pool, u32 size,
- struct page **page, u32 *offset)
-{
- ulong flbitmap, slbitmap;
- u32 flindex, slindex, slbitstart;
-
- /* There are no free blocks in this pool */
- if (!pool->flbitmap)
- return 0;
-
- /* Get freelist index correspoding to this size */
- slindex = get_index(size);
- slbitmap = pool->slbitmap[slindex / BITS_PER_LONG];
- slbitstart = slindex % BITS_PER_LONG;
-
- /*
- * If freelist is not empty at this index, we found the
- * block - head of this list. This is approximate best-fit match.
- */
- if (test_bit(slbitstart, &slbitmap)) {
- *page = pool->freelist[slindex].page;
- *offset = pool->freelist[slindex].offset;
- return slindex;
- }
-
- /*
- * No best-fit found. Search a bit further in bitmap for a free block.
- * Second level bitmap consists of series of 32-bit chunks. Search
- * further in the chunk where we expected a best-fit, starting from
- * index location found above.
- */
- slbitstart++;
- slbitmap >>= slbitstart;
-
- /* Skip this search if we were already at end of this bitmap chunk */
- if ((slbitstart != BITS_PER_LONG) && slbitmap) {
- slindex += __ffs(slbitmap) + 1;
- *page = pool->freelist[slindex].page;
- *offset = pool->freelist[slindex].offset;
- return slindex;
- }
-
- /* Now do a full two-level bitmap search to find next nearest fit */
- flindex = slindex / BITS_PER_LONG;
-
- flbitmap = (pool->flbitmap) >> (flindex + 1);
- if (!flbitmap)
- return 0;
-
- flindex += __ffs(flbitmap) + 1;
- slbitmap = pool->slbitmap[flindex];
- slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap);
- *page = pool->freelist[slindex].page;
- *offset = pool->freelist[slindex].offset;
-
- return slindex;
-}
-
-/*
- * Insert block at <page, offset> in freelist of given pool.
- * freelist used depends on block size.
- */
-static void insert_block(struct xv_pool *pool, struct page *page, u32 offset,
- struct block_header *block)
-{
- u32 flindex, slindex;
- struct block_header *nextblock;
-
- slindex = get_index_for_insert(block->size);
- flindex = slindex / BITS_PER_LONG;
-
- block->link.prev_page = NULL;
- block->link.prev_offset = 0;
- block->link.next_page = pool->freelist[slindex].page;
- block->link.next_offset = pool->freelist[slindex].offset;
- pool->freelist[slindex].page = page;
- pool->freelist[slindex].offset = offset;
-
- if (block->link.next_page) {
- nextblock = get_ptr_atomic(block->link.next_page,
- block->link.next_offset, KM_USER1);
- nextblock->link.prev_page = page;
- nextblock->link.prev_offset = offset;
- put_ptr_atomic(nextblock, KM_USER1);
- /* If there was a next page then the free bits are set. */
- return;
- }
-
- __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]);
- __set_bit(flindex, &pool->flbitmap);
-}
-
-/*
- * Remove block from freelist. Index 'slindex' identifies the freelist.
- */
-static void remove_block(struct xv_pool *pool, struct page *page, u32 offset,
- struct block_header *block, u32 slindex)
-{
- u32 flindex = slindex / BITS_PER_LONG;
- struct block_header *tmpblock;
-
- if (block->link.prev_page) {
- tmpblock = get_ptr_atomic(block->link.prev_page,
- block->link.prev_offset, KM_USER1);
- tmpblock->link.next_page = block->link.next_page;
- tmpblock->link.next_offset = block->link.next_offset;
- put_ptr_atomic(tmpblock, KM_USER1);
- }
-
- if (block->link.next_page) {
- tmpblock = get_ptr_atomic(block->link.next_page,
- block->link.next_offset, KM_USER1);
- tmpblock->link.prev_page = block->link.prev_page;
- tmpblock->link.prev_offset = block->link.prev_offset;
- put_ptr_atomic(tmpblock, KM_USER1);
- }
-
- /* Is this block is at the head of the freelist? */
- if (pool->freelist[slindex].page == page
- && pool->freelist[slindex].offset == offset) {
-
- pool->freelist[slindex].page = block->link.next_page;
- pool->freelist[slindex].offset = block->link.next_offset;
-
- if (pool->freelist[slindex].page) {
- struct block_header *tmpblock;
- tmpblock = get_ptr_atomic(pool->freelist[slindex].page,
- pool->freelist[slindex].offset,
- KM_USER1);
- tmpblock->link.prev_page = NULL;
- tmpblock->link.prev_offset = 0;
- put_ptr_atomic(tmpblock, KM_USER1);
- } else {
- /* This freelist bucket is empty */
- __clear_bit(slindex % BITS_PER_LONG,
- &pool->slbitmap[flindex]);
- if (!pool->slbitmap[flindex])
- __clear_bit(flindex, &pool->flbitmap);
- }
- }
-
- block->link.prev_page = NULL;
- block->link.prev_offset = 0;
- block->link.next_page = NULL;
- block->link.next_offset = 0;
-}
-
-/*
- * Allocate a page and add it to freelist of given pool.
- */
-static int grow_pool(struct xv_pool *pool, gfp_t flags)
-{
- struct page *page;
- struct block_header *block;
-
- page = alloc_page(flags);
- if (unlikely(!page))
- return -ENOMEM;
-
- stat_inc(&pool->total_pages);
-
- spin_lock(&pool->lock);
- block = get_ptr_atomic(page, 0, KM_USER0);
-
- block->size = PAGE_SIZE - XV_ALIGN;
- set_flag(block, BLOCK_FREE);
- clear_flag(block, PREV_FREE);
- set_blockprev(block, 0);
-
- insert_block(pool, page, 0, block);
-
- put_ptr_atomic(block, KM_USER0);
- spin_unlock(&pool->lock);
-
- return 0;
-}
-
-/*
- * Create a memory pool. Allocates freelist, bitmaps and other
- * per-pool metadata.
- */
-struct xv_pool *xv_create_pool(void)
-{
- u32 ovhd_size;
- struct xv_pool *pool;
-
- ovhd_size = roundup(sizeof(*pool), PAGE_SIZE);
- pool = kzalloc(ovhd_size, GFP_KERNEL);
- if (!pool)
- return NULL;
-
- spin_lock_init(&pool->lock);
-
- return pool;
-}
-EXPORT_SYMBOL_GPL(xv_create_pool);
-
-void xv_destroy_pool(struct xv_pool *pool)
-{
- kfree(pool);
-}
-EXPORT_SYMBOL_GPL(xv_destroy_pool);
-
-/**
- * xv_malloc - Allocate block of given size from pool.
- * @pool: pool to allocate from
- * @size: size of block to allocate
- * @page: page no. that holds the object
- * @offset: location of object within page
- *
- * On success, <page, offset> identifies block allocated
- * and 0 is returned. On failure, <page, offset> is set to
- * 0 and -ENOMEM is returned.
- *
- * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail.
- */
-int xv_malloc(struct xv_pool *pool, u32 size, struct page **page,
- u32 *offset, gfp_t flags)
-{
- int error;
- u32 index, tmpsize, origsize, tmpoffset;
- struct block_header *block, *tmpblock;
-
- *page = NULL;
- *offset = 0;
- origsize = size;
-
- if (unlikely(!size || size > XV_MAX_ALLOC_SIZE))
- return -ENOMEM;
-
- size = ALIGN(size, XV_ALIGN);
-
- spin_lock(&pool->lock);
-
- index = find_block(pool, size, page, offset);
-
- if (!*page) {
- spin_unlock(&pool->lock);
- if (flags & GFP_NOWAIT)
- return -ENOMEM;
- error = grow_pool(pool, flags);
- if (unlikely(error))
- return error;
-
- spin_lock(&pool->lock);
- index = find_block(pool, size, page, offset);
- }
-
- if (!*page) {
- spin_unlock(&pool->lock);
- return -ENOMEM;
- }
-
- block = get_ptr_atomic(*page, *offset, KM_USER0);
-
- remove_block(pool, *page, *offset, block, index);
-
- /* Split the block if required */
- tmpoffset = *offset + size + XV_ALIGN;
- tmpsize = block->size - size;
- tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN);
- if (tmpsize) {
- tmpblock->size = tmpsize - XV_ALIGN;
- set_flag(tmpblock, BLOCK_FREE);
- clear_flag(tmpblock, PREV_FREE);
-
- set_blockprev(tmpblock, *offset);
- if (tmpblock->size >= XV_MIN_ALLOC_SIZE)
- insert_block(pool, *page, tmpoffset, tmpblock);
-
- if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) {
- tmpblock = BLOCK_NEXT(tmpblock);
- set_blockprev(tmpblock, tmpoffset);
- }
- } else {
- /* This block is exact fit */
- if (tmpoffset != PAGE_SIZE)
- clear_flag(tmpblock, PREV_FREE);
- }
-
- block->size = origsize;
- clear_flag(block, BLOCK_FREE);
-
- put_ptr_atomic(block, KM_USER0);
- spin_unlock(&pool->lock);
-
- *offset += XV_ALIGN;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(xv_malloc);
-
-/*
- * Free block identified with <page, offset>
- */
-void xv_free(struct xv_pool *pool, struct page *page, u32 offset)
-{
- void *page_start;
- struct block_header *block, *tmpblock;
-
- offset -= XV_ALIGN;
-
- spin_lock(&pool->lock);
-
- page_start = get_ptr_atomic(page, 0, KM_USER0);
- block = (struct block_header *)((char *)page_start + offset);
-
- /* Catch double free bugs */
- BUG_ON(test_flag(block, BLOCK_FREE));
-
- block->size = ALIGN(block->size, XV_ALIGN);
-
- tmpblock = BLOCK_NEXT(block);
- if (offset + block->size + XV_ALIGN == PAGE_SIZE)
- tmpblock = NULL;
-
- /* Merge next block if its free */
- if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) {
- /*
- * Blocks smaller than XV_MIN_ALLOC_SIZE
- * are not inserted in any free list.
- */
- if (tmpblock->size >= XV_MIN_ALLOC_SIZE) {
- remove_block(pool, page,
- offset + block->size + XV_ALIGN, tmpblock,
- get_index_for_insert(tmpblock->size));
- }
- block->size += tmpblock->size + XV_ALIGN;
- }
-
- /* Merge previous block if its free */
- if (test_flag(block, PREV_FREE)) {
- tmpblock = (struct block_header *)((char *)(page_start) +
- get_blockprev(block));
- offset = offset - tmpblock->size - XV_ALIGN;
-
- if (tmpblock->size >= XV_MIN_ALLOC_SIZE)
- remove_block(pool, page, offset, tmpblock,
- get_index_for_insert(tmpblock->size));
-
- tmpblock->size += block->size + XV_ALIGN;
- block = tmpblock;
- }
-
- /* No used objects in this page. Free it. */
- if (block->size == PAGE_SIZE - XV_ALIGN) {
- put_ptr_atomic(page_start, KM_USER0);
- spin_unlock(&pool->lock);
-
- __free_page(page);
- stat_dec(&pool->total_pages);
- return;
- }
-
- set_flag(block, BLOCK_FREE);
- if (block->size >= XV_MIN_ALLOC_SIZE)
- insert_block(pool, page, offset, block);
-
- if (offset + block->size + XV_ALIGN != PAGE_SIZE) {
- tmpblock = BLOCK_NEXT(block);
- set_flag(tmpblock, PREV_FREE);
- set_blockprev(tmpblock, offset);
- }
-
- put_ptr_atomic(page_start, KM_USER0);
- spin_unlock(&pool->lock);
-}
-EXPORT_SYMBOL_GPL(xv_free);
-
-u32 xv_get_object_size(void *obj)
-{
- struct block_header *blk;
-
- blk = (struct block_header *)((char *)(obj) - XV_ALIGN);
- return blk->size;
-}
-EXPORT_SYMBOL_GPL(xv_get_object_size);
-
-/*
- * Returns total memory used by allocator (userdata + metadata)
- */
-u64 xv_get_total_size_bytes(struct xv_pool *pool)
-{
- return pool->total_pages << PAGE_SHIFT;
-}
-EXPORT_SYMBOL_GPL(xv_get_total_size_bytes);
diff --git a/drivers/staging/zram/xvmalloc.h b/drivers/staging/zram/xvmalloc.h
deleted file mode 100644
index 5b1a81a..0000000
--- a/drivers/staging/zram/xvmalloc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * xvmalloc memory allocator
- *
- * Copyright (C) 2008, 2009, 2010 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- */
-
-#ifndef _XV_MALLOC_H_
-#define _XV_MALLOC_H_
-
-#include <linux/types.h>
-
-struct xv_pool;
-
-struct xv_pool *xv_create_pool(void);
-void xv_destroy_pool(struct xv_pool *pool);
-
-int xv_malloc(struct xv_pool *pool, u32 size, struct page **page,
- u32 *offset, gfp_t flags);
-void xv_free(struct xv_pool *pool, struct page *page, u32 offset);
-
-u32 xv_get_object_size(void *obj);
-u64 xv_get_total_size_bytes(struct xv_pool *pool);
-
-#endif
diff --git a/drivers/staging/zram/xvmalloc_int.h b/drivers/staging/zram/xvmalloc_int.h
deleted file mode 100644
index b5f1f7f..0000000
--- a/drivers/staging/zram/xvmalloc_int.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * xvmalloc memory allocator
- *
- * Copyright (C) 2008, 2009, 2010 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- */
-
-#ifndef _XV_MALLOC_INT_H_
-#define _XV_MALLOC_INT_H_
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-/* User configurable params */
-
-/* Must be power of two */
-#ifdef CONFIG_64BIT
-#define XV_ALIGN_SHIFT 3
-#else
-#define XV_ALIGN_SHIFT 2
-#endif
-#define XV_ALIGN (1 << XV_ALIGN_SHIFT)
-#define XV_ALIGN_MASK (XV_ALIGN - 1)
-
-/* This must be greater than sizeof(link_free) */
-#define XV_MIN_ALLOC_SIZE 32
-#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN)
-
-/*
- * Free lists are separated by FL_DELTA bytes
- * This value is 3 for 4k pages and 4 for 64k pages, for any
- * other page size, a conservative (PAGE_SHIFT - 9) is used.
- */
-#if PAGE_SHIFT == 16
-#define FL_DELTA_SHIFT 4
-#else
-#define FL_DELTA_SHIFT (PAGE_SHIFT - 9)
-#endif
-#define FL_DELTA (1 << FL_DELTA_SHIFT)
-#define FL_DELTA_MASK (FL_DELTA - 1)
-#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \
- / FL_DELTA + 1)
-
-#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG)
-
-/* End of user params */
-
-enum blockflags {
- BLOCK_FREE,
- PREV_FREE,
- __NR_BLOCKFLAGS,
-};
-
-#define FLAGS_MASK XV_ALIGN_MASK
-#define PREV_MASK (~FLAGS_MASK)
-
-struct freelist_entry {
- struct page *page;
- u16 offset;
- u16 pad;
-};
-
-struct link_free {
- struct page *prev_page;
- struct page *next_page;
- u16 prev_offset;
- u16 next_offset;
-};
-
-struct block_header {
- union {
- /* This common header must be XV_ALIGN bytes */
- u8 common[XV_ALIGN];
- struct {
- u16 size;
- u16 prev;
- };
- };
- struct link_free link;
-};
-
-struct xv_pool {
- ulong flbitmap;
- ulong slbitmap[MAX_FLI];
- u64 total_pages; /* stats */
- struct freelist_entry freelist[NUM_FREE_LISTS];
- spinlock_t lock;
-};
-
-#endif
diff --git a/drivers/staging/zram/zram.txt b/drivers/staging/zram/zram.txt
deleted file mode 100644
index 5f75d29..0000000
--- a/drivers/staging/zram/zram.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-zram: Compressed RAM based block devices
-----------------------------------------
-
-Project home: http://compcache.googlecode.com/
-
-* Introduction
-
-The zram module creates RAM based block devices named /dev/zram<id>
-(<id> = 0, 1, ...). Pages written to these disks are compressed and stored
-in memory itself. These disks allow very fast I/O and compression provides
-good amounts of memory savings. Some of the usecases include /tmp storage,
-use as swap disks, various caches under /var and maybe many more :)
-
-Statistics for individual zram devices are exported through sysfs nodes at
-/sys/block/zram<id>/
-
-* Usage
-
-Following shows a typical sequence of steps for using zram.
-
-1) Load Module:
- modprobe zram num_devices=4
- This creates 4 devices: /dev/zram{0,1,2,3}
- (num_devices parameter is optional. Default: 1)
-
-2) Set Disksize (Optional):
- Set disk size by writing the value to sysfs node 'disksize'
- (in bytes). If disksize is not given, default value of 25%
- of RAM is used.
-
- # Initialize /dev/zram0 with 50MB disksize
- echo $((50*1024*1024)) > /sys/block/zram0/disksize
-
- NOTE: disksize cannot be changed if the disk contains any
- data. So, for such a disk, you need to issue 'reset' (see below)
- before you can change its disksize.
-
-3) Activate:
- mkswap /dev/zram0
- swapon /dev/zram0
-
- mkfs.ext4 /dev/zram1
- mount /dev/zram1 /tmp
-
-4) Stats:
- Per-device statistics are exported as various nodes under
- /sys/block/zram<id>/
- disksize
- num_reads
- num_writes
- invalid_io
- notify_free
- discard
- zero_pages
- orig_data_size
- compr_data_size
- mem_used_total
-
-5) Deactivate:
- swapoff /dev/zram0
- umount /dev/zram1
-
-6) Reset:
- Write any positive value to 'reset' sysfs node
- echo 1 > /sys/block/zram0/reset
- echo 1 > /sys/block/zram1/reset
-
- (This frees all the memory allocated for the given device).
-
-
-Please report any problems at:
- - Mailing list: linux-mm-cc at laptop dot org
- - Issue tracker: http://code.google.com/p/compcache/issues/list
-
-Nitin Gupta
-ngupta@vflare.org
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
deleted file mode 100644
index 5258c78..0000000
--- a/drivers/staging/zram/zram_drv.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Compressed RAM block device
- *
- * Copyright (C) 2008, 2009, 2010 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- *
- * Project home: http://compcache.googlecode.com
- */
-
-#define KMSG_COMPONENT "zram"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
-#ifdef CONFIG_ZRAM_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bio.h>
-#include <linux/bitops.h>
-#include <linux/blkdev.h>
-#include <linux/buffer_head.h>
-#include <linux/device.h>
-#include <linux/genhd.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/lzo.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-#include <linux/swap.h>
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
-
-#include "zram_drv.h"
-
-/* Globals */
-static int zram_major;
-struct zram *zram_devices;
-
-/* Module params (documentation at end) */
-unsigned int num_devices;
-
-static void zram_stat_inc(u32 *v)
-{
- *v = *v + 1;
-}
-
-static void zram_stat_dec(u32 *v)
-{
- *v = *v - 1;
-}
-
-static void zram_stat64_add(struct zram *zram, u64 *v, u64 inc)
-{
- spin_lock(&zram->stat64_lock);
- *v = *v + inc;
- spin_unlock(&zram->stat64_lock);
-}
-
-static void zram_stat64_sub(struct zram *zram, u64 *v, u64 dec)
-{
- spin_lock(&zram->stat64_lock);
- *v = *v - dec;
- spin_unlock(&zram->stat64_lock);
-}
-
-static void zram_stat64_inc(struct zram *zram, u64 *v)
-{
- zram_stat64_add(zram, v, 1);
-}
-
-static int zram_test_flag(struct zram *zram, u32 index,
- enum zram_pageflags flag)
-{
- return zram->table[index].flags & BIT(flag);
-}
-
-static void zram_set_flag(struct zram *zram, u32 index,
- enum zram_pageflags flag)
-{
- zram->table[index].flags |= BIT(flag);
-}
-
-static void zram_clear_flag(struct zram *zram, u32 index,
- enum zram_pageflags flag)
-{
- zram->table[index].flags &= ~BIT(flag);
-}
-
-static int page_zero_filled(void *ptr)
-{
- unsigned int pos;
- unsigned long *page;
-
- page = (unsigned long *)ptr;
-
- for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
- if (page[pos])
- return 0;
- }
-
- return 1;
-}
-
-static void zram_set_disksize(struct zram *zram, size_t totalram_bytes)
-{
- if (!zram->disksize) {
- pr_info(
- "disk size not provided. You can use disksize_kb module "
- "param to specify size.\nUsing default: (%u%% of RAM).\n",
- default_disksize_perc_ram
- );
- zram->disksize = default_disksize_perc_ram *
- (totalram_bytes / 100);
- }
-
- if (zram->disksize > 2 * (totalram_bytes)) {
- pr_info(
- "There is little point creating a zram of greater than "
- "twice the size of memory since we expect a 2:1 compression "
- "ratio. Note that zram uses about 0.1%% of the size of "
- "the disk when not in use so a huge zram is "
- "wasteful.\n"
- "\tMemory Size: %zu kB\n"
- "\tSize you selected: %llu kB\n"
- "Continuing anyway ...\n",
- totalram_bytes >> 10, zram->disksize
- );
- }
-
- zram->disksize &= PAGE_MASK;
-}
-
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-/*
- * Swap header (1st page of swap device) contains information
- * about a swap file/partition. Prepare such a header for the
- * given ramzswap device so that swapon can identify it as a
- * swap partition.
- */
-static void setup_swap_header(struct zram *zram, union swap_header *s)
-{
- s->info.version = 1;
- s->info.last_page = (zram->disksize >> PAGE_SHIFT) - 1;
- s->info.nr_badpages = 0;
- memcpy(s->magic.magic, "SWAPSPACE2", 10);
-}
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
-static void zram_free_page(struct zram *zram, size_t index)
-{
- u32 clen;
- void *obj;
-
- struct page *page = zram->table[index].page;
- u32 offset = zram->table[index].offset;
-
- if (unlikely(!page)) {
- /*
- * No memory is allocated for zero filled pages.
- * Simply clear zero page flag.
- */
- if (zram_test_flag(zram, index, ZRAM_ZERO)) {
- zram_clear_flag(zram, index, ZRAM_ZERO);
- zram_stat_dec(&zram->stats.pages_zero);
- }
- return;
- }
-
- if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
- clen = PAGE_SIZE;
- __free_page(page);
- zram_clear_flag(zram, index, ZRAM_UNCOMPRESSED);
- zram_stat_dec(&zram->stats.pages_expand);
- goto out;
- }
-
- obj = kmap_atomic(page, KM_USER0) + offset;
- clen = xv_get_object_size(obj) - sizeof(struct zobj_header);
- kunmap_atomic(obj, KM_USER0);
-
- xv_free(zram->mem_pool, page, offset);
- if (clen <= PAGE_SIZE / 2)
- zram_stat_dec(&zram->stats.good_compress);
-
-out:
- zram_stat64_sub(zram, &zram->stats.compr_size, clen);
- zram_stat_dec(&zram->stats.pages_stored);
-
- zram->table[index].page = NULL;
- zram->table[index].offset = 0;
-}
-
-static void handle_zero_page(struct page *page)
-{
- void *user_mem;
-
- user_mem = kmap_atomic(page, KM_USER0);
- memset(user_mem, 0, PAGE_SIZE);
- kunmap_atomic(user_mem, KM_USER0);
-
- flush_dcache_page(page);
-}
-
-static void handle_uncompressed_page(struct zram *zram,
- struct page *page, u32 index)
-{
- unsigned char *user_mem, *cmem;
-
- user_mem = kmap_atomic(page, KM_USER0);
- cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
- zram->table[index].offset;
-
- memcpy(user_mem, cmem, PAGE_SIZE);
- kunmap_atomic(user_mem, KM_USER0);
- kunmap_atomic(cmem, KM_USER1);
-
- flush_dcache_page(page);
-}
-
-static void zram_read(struct zram *zram, struct bio *bio)
-{
-
- int i;
- u32 index;
- struct bio_vec *bvec;
-
- zram_stat64_inc(zram, &zram->stats.num_reads);
- index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
-
- bio_for_each_segment(bvec, bio, i) {
- int ret;
- size_t clen;
- struct page *page;
- struct zobj_header *zheader;
- unsigned char *user_mem, *cmem;
-
- page = bvec->bv_page;
-
- if (zram_test_flag(zram, index, ZRAM_ZERO)) {
- handle_zero_page(page);
- index++;
- continue;
- }
-
- /* Requested page is not present in compressed area */
- if (unlikely(!zram->table[index].page)) {
- pr_debug("Read before write: sector=%lu, size=%u",
- (ulong)(bio->bi_sector), bio->bi_size);
- handle_zero_page(page);
- index++;
- continue;
- }
-
- /* Page is stored uncompressed since it's incompressible */
- if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
- handle_uncompressed_page(zram, page, index);
- index++;
- continue;
- }
-
- user_mem = kmap_atomic(page, KM_USER0);
- clen = PAGE_SIZE;
-
- cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
- zram->table[index].offset;
-
- ret = lzo1x_decompress_safe(
- cmem + sizeof(*zheader),
- xv_get_object_size(cmem) - sizeof(*zheader),
- user_mem, &clen);
-
- kunmap_atomic(user_mem, KM_USER0);
- kunmap_atomic(cmem, KM_USER1);
-
- /* Should NEVER happen. Return bio error if it does. */
- if (unlikely(ret != LZO_E_OK)) {
- pr_err("Decompression failed! err=%d, page=%u\n",
- ret, index);
- zram_stat64_inc(zram, &zram->stats.failed_reads);
- goto out;
- }
-
- flush_dcache_page(page);
- index++;
- }
-
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return;
-
-out:
- bio_io_error(bio);
-}
-
-static void zram_write(struct zram *zram, struct bio *bio)
-{
- int i;
- u32 index;
- struct bio_vec *bvec;
-
- zram_stat64_inc(zram, &zram->stats.num_writes);
- index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
-
- bio_for_each_segment(bvec, bio, i) {
- int ret;
- u32 offset;
- size_t clen;
- struct zobj_header *zheader;
- struct page *page, *page_store;
- unsigned char *user_mem, *cmem, *src;
-
- page = bvec->bv_page;
- src = zram->compress_buffer;
-
- /*
- * System overwrites unused sectors. Free memory associated
- * with this sector now.
- */
- if (zram->table[index].page ||
- zram_test_flag(zram, index, ZRAM_ZERO))
- zram_free_page(zram, index);
-
- mutex_lock(&zram->lock);
-
- user_mem = kmap_atomic(page, KM_USER0);
- if (page_zero_filled(user_mem)) {
- kunmap_atomic(user_mem, KM_USER0);
- mutex_unlock(&zram->lock);
- zram_stat_inc(&zram->stats.pages_zero);
- zram_set_flag(zram, index, ZRAM_ZERO);
- index++;
- continue;
- }
-
- ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
- zram->compress_workmem);
-
- kunmap_atomic(user_mem, KM_USER0);
-
- if (unlikely(ret != LZO_E_OK)) {
- mutex_unlock(&zram->lock);
- pr_err("Compression failed! err=%d\n", ret);
- zram_stat64_inc(zram, &zram->stats.failed_writes);
- goto out;
- }
-
- /*
- * Page is incompressible. Store it as-is (uncompressed)
- * since we do not want to return too many disk write
- * errors which has side effect of hanging the system.
- */
- if (unlikely(clen > max_zpage_size)) {
- clen = PAGE_SIZE;
- page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
- if (unlikely(!page_store)) {
- mutex_unlock(&zram->lock);
- pr_info("Error allocating memory for "
- "incompressible page: %u\n", index);
- zram_stat64_inc(zram,
- &zram->stats.failed_writes);
- goto out;
- }
-
- offset = 0;
- zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
- zram_stat_inc(&zram->stats.pages_expand);
- zram->table[index].page = page_store;
- src = kmap_atomic(page, KM_USER0);
- goto memstore;
- }
-
- if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader),
- &zram->table[index].page, &offset,
- GFP_NOIO | __GFP_HIGHMEM)) {
- mutex_unlock(&zram->lock);
- pr_info("Error allocating memory for compressed "
- "page: %u, size=%zu\n", index, clen);
- zram_stat64_inc(zram, &zram->stats.failed_writes);
- goto out;
- }
-
-memstore:
- zram->table[index].offset = offset;
-
- cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
- zram->table[index].offset;
-
-#if 0
- /* Back-reference needed for memory defragmentation */
- if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) {
- zheader = (struct zobj_header *)cmem;
- zheader->table_idx = index;
- cmem += sizeof(*zheader);
- }
-#endif
-
- memcpy(cmem, src, clen);
-
- kunmap_atomic(cmem, KM_USER1);
- if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
- kunmap_atomic(src, KM_USER0);
-
- /* Update stats */
- zram_stat64_add(zram, &zram->stats.compr_size, clen);
- zram_stat_inc(&zram->stats.pages_stored);
- if (clen <= PAGE_SIZE / 2)
- zram_stat_inc(&zram->stats.good_compress);
-
- mutex_unlock(&zram->lock);
- index++;
- }
-
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return;
-
-out:
- bio_io_error(bio);
-}
-
-/*
- * Check if request is within bounds and page aligned.
- */
-static inline int valid_io_request(struct zram *zram, struct bio *bio)
-{
- if (unlikely(
- (bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) ||
- (bio->bi_sector & (SECTORS_PER_PAGE - 1)) ||
- (bio->bi_size & (PAGE_SIZE - 1)))) {
-
- return 0;
- }
-
- /* I/O request is valid */
- return 1;
-}
-
-/*
- * Handler function for all zram I/O requests.
- */
-static int zram_make_request(struct request_queue *queue, struct bio *bio)
-{
- struct zram *zram = queue->queuedata;
-
- if (!valid_io_request(zram, bio)) {
- zram_stat64_inc(zram, &zram->stats.invalid_io);
- bio_io_error(bio);
- return 0;
- }
-
- if (unlikely(!zram->init_done) && zram_init_device(zram)) {
- bio_io_error(bio);
- return 0;
- }
-
- switch (bio_data_dir(bio)) {
- case READ:
- zram_read(zram, bio);
- break;
-
- case WRITE:
- zram_write(zram, bio);
- break;
- }
-
- return 0;
-}
-
-void zram_reset_device(struct zram *zram)
-{
- size_t index;
-
- mutex_lock(&zram->init_lock);
- zram->init_done = 0;
-
- /* Free various per-device buffers */
- kfree(zram->compress_workmem);
- free_pages((unsigned long)zram->compress_buffer, 1);
-
- zram->compress_workmem = NULL;
- zram->compress_buffer = NULL;
-
- /* Free all pages that are still in this zram device */
- for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) {
- struct page *page;
- u16 offset;
-
- page = zram->table[index].page;
- offset = zram->table[index].offset;
-
- if (!page)
- continue;
-
- if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
- __free_page(page);
- else
- xv_free(zram->mem_pool, page, offset);
- }
-
- vfree(zram->table);
- zram->table = NULL;
-
- xv_destroy_pool(zram->mem_pool);
- zram->mem_pool = NULL;
-
- /* Reset stats */
- memset(&zram->stats, 0, sizeof(zram->stats));
-
- zram->disksize = 0;
- mutex_unlock(&zram->init_lock);
-}
-
-int zram_init_device(struct zram *zram)
-{
- int ret;
- size_t num_pages;
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- struct page *page;
- union swap_header *swap_header;
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
- mutex_lock(&zram->init_lock);
-
- if (zram->init_done) {
- mutex_unlock(&zram->init_lock);
- return 0;
- }
-
- zram_set_disksize(zram, totalram_pages << PAGE_SHIFT);
-
- zram->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
- if (!zram->compress_workmem) {
- pr_err("Error allocating compressor working memory!\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- zram->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1);
- if (!zram->compress_buffer) {
- pr_err("Error allocating compressor buffer space\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- num_pages = zram->disksize >> PAGE_SHIFT;
- zram->table = vzalloc(num_pages * sizeof(*zram->table));
- if (!zram->table) {
- pr_err("Error allocating zram address table\n");
- /* To prevent accessing table entries during cleanup */
- zram->disksize = 0;
- ret = -ENOMEM;
- goto fail;
- }
-
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- page = alloc_page(__GFP_ZERO);
- if (!page) {
- pr_err("Error allocating swap header page\n");
- ret = -ENOMEM;
- goto fail;
- }
- zram->table[0].page = page;
- zram_set_flag(zram, 0, ZRAM_UNCOMPRESSED);
- swap_header = kmap(page);
- setup_swap_header(zram, swap_header);
- kunmap(page);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
- set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
-
- /* zram devices sort of resembles non-rotational disks */
- queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
-
- zram->mem_pool = xv_create_pool();
- if (!zram->mem_pool) {
- pr_err("Error creating memory pool\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- zram->init_done = 1;
- mutex_unlock(&zram->init_lock);
-
- pr_debug("Initialization done!\n");
- return 0;
-
-fail:
- mutex_unlock(&zram->init_lock);
- zram_reset_device(zram);
-
- pr_err("Initialization failed: err=%d\n", ret);
- return ret;
-}
-
-void zram_slot_free_notify(struct block_device *bdev, unsigned long index)
-{
- struct zram *zram;
-
- zram = bdev->bd_disk->private_data;
- zram_free_page(zram, index);
- zram_stat64_inc(zram, &zram->stats.notify_free);
-}
-
-static const struct block_device_operations zram_devops = {
- .swap_slot_free_notify = zram_slot_free_notify,
- .owner = THIS_MODULE
-};
-
-static int create_device(struct zram *zram, int device_id)
-{
- int ret = 0;
-
- mutex_init(&zram->lock);
- mutex_init(&zram->init_lock);
- spin_lock_init(&zram->stat64_lock);
-
- zram->queue = blk_alloc_queue(GFP_KERNEL);
- if (!zram->queue) {
- pr_err("Error allocating disk queue for device %d\n",
- device_id);
- ret = -ENOMEM;
- goto out;
- }
-
- blk_queue_make_request(zram->queue, zram_make_request);
- zram->queue->queuedata = zram;
-
- /* gendisk structure */
- zram->disk = alloc_disk(1);
- if (!zram->disk) {
- blk_cleanup_queue(zram->queue);
- pr_warning("Error allocating disk structure for device %d\n",
- device_id);
- ret = -ENOMEM;
- goto out;
- }
-
- zram->disk->major = zram_major;
- zram->disk->first_minor = device_id;
- zram->disk->fops = &zram_devops;
- zram->disk->queue = zram->queue;
- zram->disk->private_data = zram;
- snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
-
- /* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
- set_capacity(zram->disk, 0);
-
- /*
- * To ensure that we always get PAGE_SIZE aligned
- * and n*PAGE_SIZED sized I/O requests.
- */
- blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE);
- blk_queue_logical_block_size(zram->disk->queue,
- ZRAM_LOGICAL_BLOCK_SIZE);
- blk_queue_io_min(zram->disk->queue, PAGE_SIZE);
- blk_queue_io_opt(zram->disk->queue, PAGE_SIZE);
-
- add_disk(zram->disk);
-
- ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
- &zram_disk_attr_group);
- if (ret < 0) {
- pr_warning("Error creating sysfs group");
- goto out;
- }
-
- zram->init_done = 0;
-
-out:
- return ret;
-}
-
-static void destroy_device(struct zram *zram)
-{
- sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
- &zram_disk_attr_group);
-
- if (zram->disk) {
- del_gendisk(zram->disk);
- put_disk(zram->disk);
- }
-
- if (zram->queue)
- blk_cleanup_queue(zram->queue);
-}
-
-static int __init zram_init(void)
-{
- int ret, dev_id;
-
- if (num_devices > max_num_devices) {
- pr_warning("Invalid value for num_devices: %u\n",
- num_devices);
- ret = -EINVAL;
- goto out;
- }
-
- zram_major = register_blkdev(0, "zram");
- if (zram_major <= 0) {
- pr_warning("Unable to get major number\n");
- ret = -EBUSY;
- goto out;
- }
-
- if (!num_devices) {
- pr_info("num_devices not specified. Using default: 1\n");
- num_devices = 1;
- }
-
- /* Allocate the device array and initialize each one */
- pr_info("Creating %u devices ...\n", num_devices);
- zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
- if (!zram_devices) {
- ret = -ENOMEM;
- goto unregister;
- }
-
- for (dev_id = 0; dev_id < num_devices; dev_id++) {
- ret = create_device(&zram_devices[dev_id], dev_id);
- if (ret)
- goto free_devices;
- }
-
- return 0;
-
-free_devices:
- while (dev_id)
- destroy_device(&zram_devices[--dev_id]);
- kfree(zram_devices);
-unregister:
- unregister_blkdev(zram_major, "zram");
-out:
- return ret;
-}
-
-static void __exit zram_exit(void)
-{
- int i;
- struct zram *zram;
-
- for (i = 0; i < num_devices; i++) {
- zram = &zram_devices[i];
-
- destroy_device(zram);
- if (zram->init_done)
- zram_reset_device(zram);
- }
-
- unregister_blkdev(zram_major, "zram");
-
- kfree(zram_devices);
- pr_debug("Cleanup done!\n");
-}
-
-module_param(num_devices, uint, 0);
-MODULE_PARM_DESC(num_devices, "Number of zram devices");
-
-module_init(zram_init);
-module_exit(zram_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
-MODULE_DESCRIPTION("Compressed RAM Block Device");
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
deleted file mode 100644
index 3ad9486..0000000
--- a/drivers/staging/zram/zram_drv.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Compressed RAM block device
- *
- * Copyright (C) 2008, 2009, 2010 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- *
- * Project home: http://compcache.googlecode.com
- */
-
-#ifndef _ZRAM_DRV_H_
-#define _ZRAM_DRV_H_
-
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include "xvmalloc.h"
-
-/*
- * Some arbitrary value. This is just to catch
- * invalid value for num_devices module parameter.
- */
-static const unsigned max_num_devices = 32;
-
-/*
- * Stored at beginning of each compressed object.
- *
- * It stores back-reference to table entry which points to this
- * object. This is required to support memory defragmentation.
- */
-struct zobj_header {
-#if 0
- u32 table_idx;
-#endif
-};
-
-/*-- Configurable parameters */
-
-/* Default zram disk size: 25% of total RAM */
-static const unsigned default_disksize_perc_ram = 25;
-
-/*
- * Pages that compress to size greater than this are stored
- * uncompressed in memory.
- */
-static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3;
-
-/*
- * NOTE: max_zpage_size must be less than or equal to:
- * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header)
- * otherwise, xv_malloc() would always return failure.
- */
-
-/*-- End of configurable params */
-
-#define SECTOR_SHIFT 9
-#define SECTOR_SIZE (1 << SECTOR_SHIFT)
-#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
-#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)
-#define ZRAM_LOGICAL_BLOCK_SIZE 4096
-
-/* Flags for zram pages (table[page_no].flags) */
-enum zram_pageflags {
- /* Page is stored uncompressed */
- ZRAM_UNCOMPRESSED,
-
- /* Page consists entirely of zeros */
- ZRAM_ZERO,
-
- __NR_ZRAM_PAGEFLAGS,
-};
-
-/*-- Data structures */
-
-/* Allocated for each disk page */
-struct table {
- struct page *page;
- u16 offset;
- u8 count; /* object ref count (not yet used) */
- u8 flags;
-} __attribute__((aligned(4)));
-
-struct zram_stats {
- u64 compr_size; /* compressed size of pages stored */
- u64 num_reads; /* failed + successful */
- u64 num_writes; /* --do-- */
- u64 failed_reads; /* should NEVER! happen */
- u64 failed_writes; /* can happen when memory is too low */
- u64 invalid_io; /* non-page-aligned I/O requests */
- u64 notify_free; /* no. of swap slot free notifications */
- u32 pages_zero; /* no. of zero filled pages */
- u32 pages_stored; /* no. of pages currently stored */
- u32 good_compress; /* % of pages with compression ratio<=50% */
- u32 pages_expand; /* % of incompressible pages */
-};
-
-struct zram {
- struct xv_pool *mem_pool;
- void *compress_workmem;
- void *compress_buffer;
- struct table *table;
- spinlock_t stat64_lock; /* protect 64-bit stats */
- struct mutex lock; /* protect compression buffers against
- * concurrent writes */
- struct request_queue *queue;
- struct gendisk *disk;
- int init_done;
- /* Prevent concurrent execution of device init and reset */
- struct mutex init_lock;
- /*
- * This is the limit on amount of *uncompressed* worth of data
- * we can store in a disk.
- */
- u64 disksize; /* bytes */
-
- struct zram_stats stats;
-};
-
-extern struct zram *zram_devices;
-extern unsigned int num_devices;
-#ifdef CONFIG_SYSFS
-extern struct attribute_group zram_disk_attr_group;
-#endif
-
-extern int zram_init_device(struct zram *zram);
-extern void zram_reset_device(struct zram *zram);
-
-#endif
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c
deleted file mode 100644
index 8a23554..0000000
--- a/drivers/staging/zram/zram_sysfs.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Compressed RAM block device
- *
- * Copyright (C) 2008, 2009, 2010 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- *
- * Project home: http://compcache.googlecode.com/
- */
-
-#include <linux/device.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-
-#include "zram_drv.h"
-
-static u64 zram_stat64_read(struct zram *zram, u64 *v)
-{
- u64 val;
-
- spin_lock(&zram->stat64_lock);
- val = *v;
- spin_unlock(&zram->stat64_lock);
-
- return val;
-}
-
-static struct zram *dev_to_zram(struct device *dev)
-{
- int i;
- struct zram *zram = NULL;
-
- for (i = 0; i < num_devices; i++) {
- zram = &zram_devices[i];
- if (disk_to_dev(zram->disk) == dev)
- break;
- }
-
- return zram;
-}
-
-static ssize_t disksize_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n", zram->disksize);
-}
-
-static ssize_t disksize_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- int ret;
- struct zram *zram = dev_to_zram(dev);
-
- if (zram->init_done) {
- pr_info("Cannot change disksize for initialized device\n");
- return -EBUSY;
- }
-
- ret = strict_strtoull(buf, 10, &zram->disksize);
- if (ret)
- return ret;
-
- zram->disksize = PAGE_ALIGN(zram->disksize);
- set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
-
- return len;
-}
-
-static ssize_t initstate_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%u\n", zram->init_done);
-}
-
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-extern int swapon(const char*specialfile, int swap_flags);
-
-static ssize_t initstate_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t len)
-{
- int ret;
- unsigned long do_init;
- struct zram *zram = dev_to_zram(dev);
-
- if (zram->init_done) {
- pr_info("the device is initialized device\n");
- return -EBUSY;
- }
-
- ret = strict_strtoul(buf, 10, &do_init);
- if (ret)
- return ret;
- if (!do_init)
- return -EINVAL;
-
- zram_init_device(zram);
- swapon("/dev/block/zram0", 0);
- return len;
-}
-#else
-static inline ssize_t initstate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- return 0;
-}
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
-
-static ssize_t reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- int ret;
- unsigned long do_reset;
- struct zram *zram;
- struct block_device *bdev;
-
- zram = dev_to_zram(dev);
- bdev = bdget_disk(zram->disk, 0);
-
- /* Do not reset an active device! */
- if (bdev->bd_holders)
- return -EBUSY;
-
- ret = strict_strtoul(buf, 10, &do_reset);
- if (ret)
- return ret;
-
- if (!do_reset)
- return -EINVAL;
-
- /* Make sure all pending I/O is finished */
- if (bdev)
- fsync_bdev(bdev);
-
- if (zram->init_done)
- zram_reset_device(zram);
-
- return len;
-}
-
-static ssize_t num_reads_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n",
- zram_stat64_read(zram, &zram->stats.num_reads));
-}
-
-static ssize_t num_writes_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n",
- zram_stat64_read(zram, &zram->stats.num_writes));
-}
-
-static ssize_t invalid_io_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n",
- zram_stat64_read(zram, &zram->stats.invalid_io));
-}
-
-static ssize_t notify_free_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n",
- zram_stat64_read(zram, &zram->stats.notify_free));
-}
-
-static ssize_t zero_pages_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%u\n", zram->stats.pages_zero);
-}
-
-static ssize_t orig_data_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n",
- (u64)(zram->stats.pages_stored) << PAGE_SHIFT);
-}
-
-static ssize_t compr_data_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct zram *zram = dev_to_zram(dev);
-
- return sprintf(buf, "%llu\n",
- zram_stat64_read(zram, &zram->stats.compr_size));
-}
-
-static ssize_t mem_used_total_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u64 val = 0;
- struct zram *zram = dev_to_zram(dev);
-
- if (zram->init_done) {
- val = xv_get_total_size_bytes(zram->mem_pool) +
- ((u64)(zram->stats.pages_expand) << PAGE_SHIFT);
- }
-
- return sprintf(buf, "%llu\n", val);
-}
-
-static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
- disksize_show, disksize_store);
-static DEVICE_ATTR(initstate, S_IRUGO | S_IWUSR, initstate_show, initstate_store);
-static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
-static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL);
-static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL);
-static DEVICE_ATTR(invalid_io, S_IRUGO, invalid_io_show, NULL);
-static DEVICE_ATTR(notify_free, S_IRUGO, notify_free_show, NULL);
-static DEVICE_ATTR(zero_pages, S_IRUGO, zero_pages_show, NULL);
-static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
-static DEVICE_ATTR(compr_data_size, S_IRUGO, compr_data_size_show, NULL);
-static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
-
-static struct attribute *zram_disk_attrs[] = {
- &dev_attr_disksize.attr,
- &dev_attr_initstate.attr,
- &dev_attr_reset.attr,
- &dev_attr_num_reads.attr,
- &dev_attr_num_writes.attr,
- &dev_attr_invalid_io.attr,
- &dev_attr_notify_free.attr,
- &dev_attr_zero_pages.attr,
- &dev_attr_orig_data_size.attr,
- &dev_attr_compr_data_size.attr,
- &dev_attr_mem_used_total.attr,
- NULL,
-};
-
-struct attribute_group zram_disk_attr_group = {
- .attrs = zram_disk_attrs,
-};
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index a76c808..606c0956 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -424,6 +424,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
* they are not on hot paths so a little discipline won't do
* any harm.
*
+ * The line discipline-related tty_struct fields are reset to
+ * prevent the ldisc driver from re-using stale information for
+ * the new ldisc instance.
+ *
* Locking: takes termios_mutex
*/
@@ -432,6 +436,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
mutex_lock(&tty->termios_mutex);
tty->termios->c_line = num;
mutex_unlock(&tty->termios_mutex);
+
+ tty->disc_data = NULL;
+ tty->receive_room = 0;
}
/**
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 84e69ea..c8fee56 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -895,6 +895,9 @@ static int acm_probe(struct usb_interface *intf,
if (quirks == NO_UNION_NORMAL) {
data_interface = usb_ifnum_to_if(usb_dev, 1);
control_interface = usb_ifnum_to_if(usb_dev, 0);
+ /* we would crash */
+ if (!data_interface || !control_interface)
+ return -ENODEV;
goto skip_normal_probe;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 461e785..8aff636 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1012,10 +1012,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
static int proc_connectinfo(struct dev_state *ps, void __user *arg)
{
- struct usbdevfs_connectinfo ci = {
- .devnum = ps->dev->devnum,
- .slow = ps->dev->speed == USB_SPEED_LOW
- };
+ struct usbdevfs_connectinfo ci;
+
+ memset(&ci, 0, sizeof(ci));
+ ci.devnum = ps->dev->devnum;
+ ci.slow = ps->dev->speed == USB_SPEED_LOW;
if (copy_to_user(arg, &ci, sizeof(ci)))
return -EFAULT;
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 5c3960d..b1d63b5 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -166,6 +166,9 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
int tooff = 0, fromoff = 0;
int size;
+ if (!to || !from)
+ return -EINVAL;
+
if (to->start > from->start)
fromoff = to->start - from->start;
else
@@ -177,9 +180,12 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
return -EINVAL;
size *= sizeof(u16);
- memcpy(to->red+tooff, from->red+fromoff, size);
- memcpy(to->green+tooff, from->green+fromoff, size);
- memcpy(to->blue+tooff, from->blue+fromoff, size);
+ if (from->red && to->red)
+ memcpy(to->red+tooff, from->red+fromoff, size);
+ if (from->green && to->green)
+ memcpy(to->green+tooff, from->green+fromoff, size);
+ if (from->blue && to->blue)
+ memcpy(to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp)
memcpy(to->transp+tooff, from->transp+fromoff, size);
return 0;
@@ -190,6 +196,9 @@ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
int tooff = 0, fromoff = 0;
int size;
+ if (!to || !from || (int)(to->start) < 0)
+ return -EINVAL;
+
if (to->start > from->start)
fromoff = to->start - from->start;
else
@@ -201,12 +210,15 @@ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
return -EINVAL;
size *= sizeof(u16);
- if (copy_to_user(to->red+tooff, from->red+fromoff, size))
- return -EFAULT;
- if (copy_to_user(to->green+tooff, from->green+fromoff, size))
- return -EFAULT;
- if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
- return -EFAULT;
+ if (from->red && to->red)
+ if (copy_to_user(to->red+tooff, from->red+fromoff, size))
+ return -EFAULT;
+ if (from->green && to->green)
+ if (copy_to_user(to->green+tooff, from->green+fromoff, size))
+ return -EFAULT;
+ if (from->blue && to->blue)
+ if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
+ return -EFAULT;
if (from->transp && to->transp)
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
return -EFAULT;
@@ -285,8 +297,8 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
rc = -ENODEV;
goto out;
}
- if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
- !info->fbops->fb_setcmap)) {
+ if (!info->fbops->fb_setcolreg &&
+ !info->fbops->fb_setcmap) {
rc = -EINVAL;
goto out1;
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index fcc52d4..4716e62 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1108,6 +1108,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT;
ret = fb_set_user_cmap(&cmap, info);
+ if (ret) {
+ if (info)
+ fb_dealloc_cmap(&info->cmap);
+ }
break;
case FBIOGETCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c
index 816a449..4cac54a 100644
--- a/drivers/xen/tmem.c
+++ b/drivers/xen/tmem.c
@@ -234,9 +234,9 @@ __setup("nocleancache", no_cleancache);
static struct cleancache_ops tmem_cleancache_ops = {
.put_page = tmem_cleancache_put_page,
.get_page = tmem_cleancache_get_page,
- .flush_page = tmem_cleancache_flush_page,
- .flush_inode = tmem_cleancache_flush_inode,
- .flush_fs = tmem_cleancache_flush_fs,
+ .invalidate_page = tmem_cleancache_flush_page,
+ .invalidate_inode = tmem_cleancache_flush_inode,
+ .invalidate_fs = tmem_cleancache_flush_fs,
.init_shared_fs = tmem_cleancache_init_shared_fs,
.init_fs = tmem_cleancache_init_fs
};
diff --git a/fs/exec.c b/fs/exec.c
index 807400f..8c75690 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -957,12 +957,23 @@ static int de_thread(struct task_struct *tsk)
transfer_pid(leader, tsk, PIDTYPE_SID);
list_replace_rcu(&leader->tasks, &tsk->tasks);
+ delete_from_adj_tree(leader);
+ add_2_adj_tree(tsk);
list_replace_init(&leader->sibling, &tsk->sibling);
tsk->group_leader = tsk;
leader->group_leader = tsk;
tsk->exit_signal = SIGCHLD;
+ /*
+ * need to delete leader from adj tree, because it will not be
+ * group leader (exit_signal = -1) soon. release_task(leader)
+ * can't delete it.
+ */
+ spin_lock_irq(lock);
+ delete_from_adj_tree(leader);
+ add_2_adj_tree(tsk);
+ spin_unlock_irq(lock);
BUG_ON(leader->exit_state != EXIT_ZOMBIE);
leader->exit_state = EXIT_DEAD;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 294bc8f..c2bd302 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4484,6 +4484,7 @@ int ext4_can_truncate(struct inode *inode)
int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
{
+#if 0
struct inode *inode = file->f_path.dentry->d_inode;
if (!S_ISREG(inode->i_mode))
return -ENOTSUPP;
@@ -4494,6 +4495,12 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
}
return ext4_ext_punch_hole(file, offset, length);
+#else
+ /*
+ * Disabled as per b/28760453
+ */
+ return -EOPNOTSUPP;
+#endif
}
/*
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 7da2a06..e325e9f 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -160,8 +160,10 @@ static int get_task_ioprio(struct task_struct *p)
if (ret)
goto out;
ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM);
+ task_lock(p);
if (p->io_context)
ret = p->io_context->ioprio;
+ task_unlock(p);
out:
return ret;
}
diff --git a/fs/namespace.c b/fs/namespace.c
index 900812f..8b34a97 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1477,8 +1477,14 @@ struct vfsmount *collect_mounts(struct path *path)
{
struct vfsmount *tree;
down_write(&namespace_sem);
- tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
+ if (!check_mnt(path->mnt))
+ tree = ERR_PTR(-EINVAL);
+ else
+ tree = copy_tree(path->mnt, path->dentry,
+ CL_COPY_ALL | CL_PRIVATE);
up_write(&namespace_sem);
+ if (IS_ERR(tree))
+ return NULL;
return tree;
}
diff --git a/fs/pipe.c b/fs/pipe.c
index 6060d2f..35bca6b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -35,6 +35,12 @@ unsigned int pipe_max_size = 1048576;
*/
unsigned int pipe_min_size = PAGE_SIZE;
+/* Maximum allocatable pages per user. Hard limit is unset by default, soft
+ * matches default values.
+ */
+unsigned long pipe_user_pages_hard;
+unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
+
/*
* We use a start+len construction, which provides full use of the
* allocated memory.
@@ -389,6 +395,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
void *addr;
size_t chars = buf->len, remaining;
int error, atomic;
+ int offset;
if (chars > total_len)
chars = total_len;
@@ -402,9 +409,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
atomic = !iov_fault_in_pages_write(iov, chars);
remaining = chars;
+ offset = buf->offset;
redo:
addr = ops->map(pipe, buf, atomic);
- error = pipe_iov_copy_to_user(iov, addr, &buf->offset,
+ error = pipe_iov_copy_to_user(iov, addr, &offset,
&remaining, atomic);
ops->unmap(pipe, buf, addr);
if (unlikely(error)) {
@@ -420,6 +428,7 @@ redo:
break;
}
ret += chars;
+ buf->offset += chars;
buf->len -= chars;
/* Was it a packet buffer? Clean up and exit */
@@ -929,20 +938,49 @@ const struct file_operations rdwr_pipefifo_fops = {
.fasync = pipe_rdwr_fasync,
};
+static void account_pipe_buffers(struct pipe_inode_info *pipe,
+ unsigned long old, unsigned long new)
+{
+ atomic_long_add(new - old, &pipe->user->pipe_bufs);
+}
+
+static bool too_many_pipe_buffers_soft(struct user_struct *user)
+{
+ return pipe_user_pages_soft &&
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
+}
+
+static bool too_many_pipe_buffers_hard(struct user_struct *user)
+{
+ return pipe_user_pages_hard &&
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
+}
+
struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
{
struct pipe_inode_info *pipe;
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
if (pipe) {
- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
+ unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
+ struct user_struct *user = get_current_user();
+
+ if (!too_many_pipe_buffers_hard(user)) {
+ if (too_many_pipe_buffers_soft(user))
+ pipe_bufs = 1;
+ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
+ }
+
if (pipe->bufs) {
init_waitqueue_head(&pipe->wait);
pipe->r_counter = pipe->w_counter = 1;
pipe->inode = inode;
- pipe->buffers = PIPE_DEF_BUFFERS;
+ pipe->buffers = pipe_bufs;
+ pipe->user = user;
+ account_pipe_buffers(pipe, 0, pipe_bufs);
return pipe;
}
+ free_uid(user);
kfree(pipe);
}
@@ -953,6 +991,8 @@ void __free_pipe_info(struct pipe_inode_info *pipe)
{
int i;
+ account_pipe_buffers(pipe, pipe->buffers, 0);
+ free_uid(pipe->user);
for (i = 0; i < pipe->buffers; i++) {
struct pipe_buffer *buf = pipe->bufs + i;
if (buf->ops)
@@ -1201,6 +1241,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
}
+ account_pipe_buffers(pipe, pipe->buffers, nr_pages);
pipe->curbuf = 0;
kfree(pipe->bufs);
pipe->bufs = bufs;
@@ -1274,6 +1315,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
ret = -EPERM;
goto out;
+ } else if ((too_many_pipe_buffers_hard(pipe->user) ||
+ too_many_pipe_buffers_soft(pipe->user)) &&
+ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+ ret = -EPERM;
+ goto out;
}
ret = pipe_set_size(pipe, nr_pages);
break;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1a140ca..56d23e1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1063,6 +1063,8 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
else
task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) /
-OOM_DISABLE;
+ delete_from_adj_tree(task);
+ add_2_adj_tree(task);
err_sighand:
unlock_task_sighand(task, &flags);
err_task_lock:
@@ -1187,6 +1189,8 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
atomic_dec(&task->mm->oom_disable_count);
}
task->signal->oom_score_adj = oom_score_adj;
+ delete_from_adj_tree(task);
+ add_2_adj_tree(task);
if (has_capability_noaudit(current, CAP_SYS_RESOURCE))
task->signal->oom_score_adj_min = oom_score_adj;
/*
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 00e7ac4..f43c540 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -88,6 +88,56 @@ static void pad_len_spaces(struct seq_file *m, int len)
seq_printf(m, "%*c", len, ' ');
}
+static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma)
+{
+ const char __user *name = vma_get_anon_name(vma);
+ struct mm_struct *mm = vma->vm_mm;
+
+ unsigned long page_start_vaddr;
+ unsigned long page_offset;
+ unsigned long num_pages;
+ unsigned long max_len = NAME_MAX;
+ int i;
+
+ page_start_vaddr = (unsigned long)name & PAGE_MASK;
+ page_offset = (unsigned long)name - page_start_vaddr;
+ num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE);
+
+ seq_puts(m, "[anon:");
+
+ for (i = 0; i < num_pages; i++) {
+ int len;
+ int write_len;
+ const char *kaddr;
+ long pages_pinned;
+ struct page *page;
+
+ pages_pinned = get_user_pages(current, mm, page_start_vaddr,
+ 1, 0, 0, &page, NULL);
+ if (pages_pinned < 1) {
+ seq_puts(m, "<fault>]");
+ return;
+ }
+
+ kaddr = (const char *)kmap(page);
+ len = min(max_len, PAGE_SIZE - page_offset);
+ write_len = strnlen(kaddr + page_offset, len);
+ seq_write(m, kaddr + page_offset, write_len);
+ kunmap(page);
+ put_page(page);
+
+ /* if strnlen hit a null terminator then we're done */
+ if (write_len != len)
+ break;
+
+ max_len -= len;
+ page_offset = 0;
+ page_start_vaddr += PAGE_SIZE;
+ }
+
+ seq_putc(m, ']');
+}
+
static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
{
if (vma && vma != priv->tail_vma) {
@@ -264,7 +314,14 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
} else {
name = "[vdso]";
}
+ goto done;
}
+
+ if (vma_get_anon_name(vma)) {
+ pad_len_spaces(m, len);
+ seq_print_vma_name(m, vma);
+ }
+done:
if (name) {
pad_len_spaces(m, len);
seq_puts(m, name);
@@ -474,6 +531,12 @@ static int show_smap(struct seq_file *m, void *v)
(vma->vm_flags & VM_LOCKED) ?
(unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0);
+ if (vma_get_anon_name(vma)) {
+ seq_puts(m, "Name: ");
+ seq_print_vma_name(m, vma);
+ seq_putc(m, '\n');
+ }
+
if (m->count < m->size) /* vma is copied successfully */
m->version = (vma != get_gate_vma(task->mm))
? vma->vm_start : 0;
diff --git a/include/linux/android_pmem.h b/include/linux/android_pmem.h
deleted file mode 100644
index f633621..0000000
--- a/include/linux/android_pmem.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* include/linux/android_pmem.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef _ANDROID_PMEM_H_
-#define _ANDROID_PMEM_H_
-
-#define PMEM_IOCTL_MAGIC 'p'
-#define PMEM_GET_PHYS _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
-#define PMEM_MAP _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
-#define PMEM_GET_SIZE _IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
-#define PMEM_UNMAP _IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
-/* This ioctl will allocate pmem space, backing the file, it will fail
- * if the file already has an allocation, pass it the len as the argument
- * to the ioctl */
-#define PMEM_ALLOCATE _IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
-/* This will connect a one pmem file to another, pass the file that is already
- * backed in memory as the argument to the ioctl
- */
-#define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
-/* Returns the total size of the pmem region it is sent to as a pmem_region
- * struct (with offset set to 0).
- */
-#define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
-#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
-
-struct android_pmem_platform_data
-{
- const char* name;
- /* starting physical address of memory region */
- unsigned long start;
- /* size of memory region */
- unsigned long size;
- /* set to indicate the region should not be managed with an allocator */
- unsigned no_allocator;
- /* set to indicate maps of this region should be cached, if a mix of
- * cached and uncached is desired, set this and open the device with
- * O_SYNC to get an uncached region */
- unsigned cached;
- /* The MSM7k has bits to enable a write buffer in the bus controller*/
- unsigned buffered;
-};
-
-struct pmem_region {
- unsigned long offset;
- unsigned long len;
-};
-
-#ifdef CONFIG_ANDROID_PMEM
-int is_pmem_file(struct file *file);
-int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
- unsigned long *end, struct file **filp);
-int get_pmem_user_addr(struct file *file, unsigned long *start,
- unsigned long *end);
-void put_pmem_file(struct file* file);
-void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
-int pmem_setup(struct android_pmem_platform_data *pdata,
- long (*ioctl)(struct file *, unsigned int, unsigned long),
- int (*release)(struct inode *, struct file *));
-int pmem_remap(struct pmem_region *region, struct file *file,
- unsigned operation);
-
-#else
-static inline int is_pmem_file(struct file *file) { return 0; }
-static inline int get_pmem_file(int fd, unsigned long *start,
- unsigned long *vstart, unsigned long *end,
- struct file **filp) { return -ENOSYS; }
-static inline int get_pmem_user_addr(struct file *file, unsigned long *start,
- unsigned long *end) { return -ENOSYS; }
-static inline void put_pmem_file(struct file* file) { return; }
-static inline void flush_pmem_file(struct file *file, unsigned long start,
- unsigned long len) { return; }
-static inline int pmem_setup(struct android_pmem_platform_data *pdata,
- long (*ioctl)(struct file *, unsigned int, unsigned long),
- int (*release)(struct inode *, struct file *)) { return -ENOSYS; }
-
-static inline int pmem_remap(struct pmem_region *region, struct file *file,
- unsigned operation) { return -ENOSYS; }
-#endif
-
-#endif //_ANDROID_PPP_H_
-
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1b13021..af75d16 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -403,6 +403,7 @@ struct request_queue
#define QUEUE_FLAG_NOXMERGES 15 /* No extended merges */
#define QUEUE_FLAG_ADD_RANDOM 16 /* Contributes to random pool */
#define QUEUE_FLAG_SECDISCARD 17 /* supports SECDISCARD */
+#define QUEUE_FLAG_FAST 20 /* fast block device (e.g. ram based) */
#define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \
(1 << QUEUE_FLAG_STACKABLE) | \
@@ -487,6 +488,7 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
#define blk_queue_discard(q) test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags)
#define blk_queue_secdiscard(q) (blk_queue_discard(q) && \
test_bit(QUEUE_FLAG_SECDISCARD, &(q)->queue_flags))
+#define blk_queue_fast(q) test_bit(QUEUE_FLAG_FAST, &(q)->queue_flags)
#define blk_noretry_request(rq) \
((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \
diff --git a/include/linux/cleancache.h b/include/linux/cleancache.h
index 04ffb2e..1ccdcea 100644
--- a/include/linux/cleancache.h
+++ b/include/linux/cleancache.h
@@ -28,9 +28,9 @@ struct cleancache_ops {
pgoff_t, struct page *);
void (*put_page)(int, struct cleancache_filekey,
pgoff_t, struct page *);
- void (*flush_page)(int, struct cleancache_filekey, pgoff_t);
- void (*flush_inode)(int, struct cleancache_filekey);
- void (*flush_fs)(int);
+ void (*invalidate_page)(int, struct cleancache_filekey, pgoff_t);
+ void (*invalidate_inode)(int, struct cleancache_filekey);
+ void (*invalidate_fs)(int);
};
extern struct cleancache_ops
diff --git a/include/linux/decompress/unlz4.h b/include/linux/decompress/unlz4.h
new file mode 100644
index 0000000..d5b68bf
--- /dev/null
+++ b/include/linux/decompress/unlz4.h
@@ -0,0 +1,10 @@
+#ifndef DECOMPRESS_UNLZ4_H
+#define DECOMPRESS_UNLZ4_H
+
+int unlz4(unsigned char *inbuf, int len,
+ int(*fill)(void*, unsigned int),
+ int(*flush)(void*, unsigned int),
+ unsigned char *output,
+ int *pos,
+ void(*error)(char *x));
+#endif
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index ef820a3..ee4410a 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -390,7 +390,7 @@ struct lock_class_key { };
#define lockdep_depth(tsk) (0)
-#define lockdep_assert_held(l) do { } while (0)
+#define lockdep_assert_held(l) do { (void)(l); } while (0)
#endif /* !LOCKDEP */
diff --git a/include/linux/lz4.h b/include/linux/lz4.h
new file mode 100644
index 0000000..4356686
--- /dev/null
+++ b/include/linux/lz4.h
@@ -0,0 +1,87 @@
+#ifndef __LZ4_H__
+#define __LZ4_H__
+/*
+ * LZ4 Kernel Interface
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define LZ4_MEM_COMPRESS (4096 * sizeof(unsigned char *))
+#define LZ4HC_MEM_COMPRESS (65538 * sizeof(unsigned char *))
+
+/*
+ * lz4_compressbound()
+ * Provides the maximum size that LZ4 may output in a "worst case" scenario
+ * (input data not compressible)
+ */
+static inline size_t lz4_compressbound(size_t isize)
+{
+ return isize + (isize / 255) + 16;
+}
+
+/*
+ * lz4_compress()
+ * src : source address of the original data
+ * src_len : size of the original data
+ * dst : output buffer address of the compressed data
+ * This requires 'dst' of size LZ4_COMPRESSBOUND.
+ * dst_len : is the output size, which is returned after compress done
+ * workmem : address of the working memory.
+ * This requires 'workmem' of size LZ4_MEM_COMPRESS.
+ * return : Success if return 0
+ * Error if return (< 0)
+ * note : Destination buffer and workmem must be already allocated with
+ * the defined size.
+ */
+int lz4_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+ /*
+ * lz4hc_compress()
+ * src : source address of the original data
+ * src_len : size of the original data
+ * dst : output buffer address of the compressed data
+ * This requires 'dst' of size LZ4_COMPRESSBOUND.
+ * dst_len : is the output size, which is returned after compress done
+ * workmem : address of the working memory.
+ * This requires 'workmem' of size LZ4HC_MEM_COMPRESS.
+ * return : Success if return 0
+ * Error if return (< 0)
+ * note : Destination buffer and workmem must be already allocated with
+ * the defined size.
+ */
+int lz4hc_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+/*
+ * lz4_decompress()
+ * src : source address of the compressed data
+ * src_len : is the input size, whcih is returned after decompress done
+ * dest : output buffer address of the decompressed data
+ * actual_dest_len: is the size of uncompressed data, supposing it's known
+ * return : Success if return 0
+ * Error if return (< 0)
+ * note : Destination buffer must be already allocated.
+ * slightly faster than lz4_decompress_unknownoutputsize()
+ */
+int lz4_decompress(const unsigned char *src, size_t *src_len,
+ unsigned char *dest, size_t actual_dest_len);
+
+/*
+ * lz4_decompress_unknownoutputsize()
+ * src : source address of the compressed data
+ * src_len : is the input size, therefore the compressed size
+ * dest : output buffer address of the decompressed data
+ * dest_len: is the max size of the destination buffer, which is
+ * returned with actual size of decompressed data after
+ * decompress done
+ * return : Success if return 0
+ * Error if return (< 0)
+ * note : Destination buffer must be already allocated.
+ */
+int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len,
+ unsigned char *dest, size_t *dest_len);
+#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d5dc6af..b465c7f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1418,7 +1418,7 @@ extern int vma_adjust(struct vm_area_struct *vma, unsigned long start,
extern struct vm_area_struct *vma_merge(struct mm_struct *,
struct vm_area_struct *prev, unsigned long addr, unsigned long end,
unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t,
- struct mempolicy *);
+ struct mempolicy *, const char __user *);
extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
extern int split_vma(struct mm_struct *,
struct vm_area_struct *, unsigned long addr, int new_below);
@@ -1574,6 +1574,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
#define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */
#define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */
#define FOLL_NO_CMA 0x200 /* avoid putting pages to CMA regions */
+#define FOLL_COW 0x4000 /* internal GUP flag */
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
void *data);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 0f230ce..557f9b6 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -162,6 +162,10 @@ struct vm_area_struct {
* linkage into the address_space->i_mmap prio tree, or
* linkage to the list of like vmas hanging off its node, or
* linkage of vma in the address_space->i_mmap_nonlinear list.
+ *
+ * For private anonymous mappings, a pointer to a null terminated string
+ * in the user process containing the name given to the vma, or NULL
+ * if unnamed.
*/
union {
struct {
@@ -171,6 +175,7 @@ struct vm_area_struct {
} vm_set;
struct raw_prio_tree_node prio_tree_node;
+ const char __user *anon_name;
} shared;
/*
@@ -198,9 +203,6 @@ struct vm_area_struct {
#ifdef CONFIG_NUMA
struct mempolicy *vm_policy; /* NUMA policy for the VMA */
#endif
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- int vma_swap_done;
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
};
struct core_thread {
@@ -333,9 +335,6 @@ struct mm_struct {
#ifdef CONFIG_CPUMASK_OFFSTACK
struct cpumask cpumask_allocation;
#endif
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- int mm_swap_done;
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
};
static inline void mm_init_cpumask(struct mm_struct *mm)
@@ -351,4 +350,14 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
return mm->cpu_vm_mask_var;
}
+
+/* Return the name for an anonymous mapping or NULL for a file-backed mapping */
+static inline const char __user *vma_get_anon_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_file)
+ return NULL;
+
+ return vma->shared.anon_name;
+}
+
#endif /* _LINUX_MM_TYPES_H */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 87a0009..657ba2c 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -51,6 +51,9 @@
* PG_hwpoison indicates that a page got corrupted in hardware and contains
* data with incorrect ECC bits that triggered a machine check. Accessing is
* not safe since it may cause another machine check. Don't touch!
+ *
+ * PG_wasactive reflects that a page previously was promoted to active status.
+ * Such pages should be considered higher priority for cleancache backends.
*/
/*
@@ -107,6 +110,9 @@ enum pageflags {
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
PG_compound_lock,
#endif
+#ifdef CONFIG_CLEANCACHE
+ PG_was_active,
+#endif
__NR_PAGEFLAGS,
/* Filesystems */
@@ -264,6 +270,10 @@ __PAGEFLAG(SlobFree, slob_free)
__PAGEFLAG(SlubFrozen, slub_frozen)
+#ifdef CONFIG_CLEANCACHE
+PAGEFLAG(WasActive, was_active)
+#endif
+
/*
* Private page markings that may be used by the filesystem that owns the page
* for its own purposes.
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e4d3640..82660a6 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -757,6 +757,12 @@ struct perf_event {
int nr_siblings;
int group_flags;
struct perf_event *group_leader;
+
+ /*
+ * Protect the pmu, attributes and context of a group leader.
+ * Note: does not protect the pointer to the group_leader.
+ */
+ struct mutex group_leader_mutex;
struct pmu *pmu;
enum perf_event_active_state state;
@@ -979,6 +985,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr,
int cpu,
struct task_struct *task,
perf_overflow_handler_t callback);
+extern void perf_pmu_migrate_context(struct pmu *pmu,
+ int src_cpu, int dst_cpu);
extern u64 perf_event_read_value(struct perf_event *event,
u64 *enabled, u64 *running);
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 0072a53..1aefc3f 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -43,6 +43,7 @@ struct pipe_buffer {
* @fasync_writers: writer side fasync
* @inode: inode this pipe is attached to
* @bufs: the circular array of pipe buffers
+ * @user: the user who created this pipe
**/
struct pipe_inode_info {
wait_queue_head_t wait;
@@ -57,6 +58,7 @@ struct pipe_inode_info {
struct fasync_struct *fasync_writers;
struct inode *inode;
struct pipe_buffer *bufs;
+ struct user_struct *user;
};
/*
@@ -142,6 +144,8 @@ void pipe_unlock(struct pipe_inode_info *);
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
extern unsigned int pipe_max_size, pipe_min_size;
+extern unsigned long pipe_user_pages_hard;
+extern unsigned long pipe_user_pages_soft;
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 8289fca..35b7ed6 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -146,6 +146,7 @@ enum power_supply_type {
POWER_SUPPLY_TYPE_WIRELESS,
POWER_SUPPLY_TYPE_UARTOFF,
POWER_SUPPLY_TYPE_OTG,
+ POWER_SUPPLY_TYPE_UNKNOWN,
};
enum {
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index a3baeb2..dd90287 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -102,4 +102,7 @@
#define PR_MCE_KILL_GET 34
+#define PR_SET_VMA 0x53564d41
+# define PR_SET_VMA_ANON_NAME 0
+
#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8ff666c..6b030a5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -645,11 +645,13 @@ struct signal_struct {
struct rw_semaphore threadgroup_fork_lock;
#endif
- int oom_adj; /* OOM kill score adjustment (bit shift) */
- int oom_score_adj; /* OOM kill score adjustment */
- int oom_score_adj_min; /* OOM kill score adjustment minimum value.
+ int oom_adj; /* OOM kill score adjustment (bit shift) */
+ short oom_score_adj; /* OOM kill score adjustment */
+ short oom_score_adj_min;/* OOM kill score adjustment min value.
* Only settable by CAP_SYS_RESOURCE. */
-
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ struct rb_node adj_node;
+#endif
struct mutex cred_guard_mutex; /* guard against foreign influences on
* credential calculations
* (notably. ptrace) */
@@ -705,6 +707,7 @@ struct user_struct {
unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
#endif
unsigned long locked_shm; /* How many pages of mlocked shm ? */
+ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
#ifdef CONFIG_KEYS
struct key *uid_keyring; /* UID specific keyring */
@@ -1281,6 +1284,9 @@ struct task_struct {
#endif
struct list_head tasks;
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ struct rb_node adj_node;
+#endif
#ifdef CONFIG_SMP
struct plist_node pushable_tasks;
#endif
@@ -1620,6 +1626,13 @@ static inline struct pid *task_tgid(struct task_struct *task)
return task->group_leader->pids[PIDTYPE_PID].pid;
}
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+extern void add_2_adj_tree(struct task_struct *task);
+extern void delete_from_adj_tree(struct task_struct *task);
+#else
+static inline void add_2_adj_tree(struct task_struct *task) { }
+static inline void delete_from_adj_tree(struct task_struct *task) { }
+#endif
/*
* Without tasklist or rcu lock it is not safe to dereference
* the result of task_pgrp/task_session even if task == current,
diff --git a/include/linux/swap.h b/include/linux/swap.h
index e73799d..bd6e937 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -150,6 +150,7 @@ enum {
SWP_BLKDEV = (1 << 6), /* its a block device */
/* add others here before... */
SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */
+ SWP_FAST = (1 << 9), /* blkdev access is fast and cheap */
};
#define SWAP_CLUSTER_MAX 32
@@ -201,9 +202,6 @@ struct swap_list_t {
int next; /* swapfile to be used next */
};
-/* Swap 50% full? Release swapcache more aggressively.. */
-#define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
-
/* linux/mm/page_alloc.c */
extern unsigned long totalram_pages;
extern unsigned long totalreserve_pages;
@@ -320,6 +318,21 @@ extern struct page *swapin_readahead(swp_entry_t, gfp_t,
/* linux/mm/swapfile.c */
extern long nr_swap_pages;
extern long total_swap_pages;
+extern bool is_swap_fast(swp_entry_t entry);
+
+/* Swap 50% full? Release swapcache more aggressively.. */
+static inline bool vm_swap_full(struct swap_info_struct *si)
+{
+ /*
+ * If the swap device is fast, return true
+ * not to delay swap free.
+ */
+ if (si->flags & SWP_FAST)
+ return true;
+
+ return nr_swap_pages*2 < total_swap_pages;
+}
+
extern void si_swapinfo(struct sysinfo *);
extern swp_entry_t get_swap_page(void);
extern swp_entry_t get_swap_page_of_type(int);
@@ -335,6 +348,7 @@ extern int swap_type_of(dev_t, sector_t, struct block_device **);
extern unsigned int count_swap_pages(int, int);
extern sector_t map_swap_page(struct page *, struct block_device **);
extern sector_t swapdev_block(int, pgoff_t);
+extern struct swap_info_struct *page_swap_info(struct page *);
extern int reuse_swap_page(struct page *);
extern int try_to_free_swap(struct page *);
struct backing_dev_info;
@@ -379,6 +393,7 @@ static inline void mem_cgroup_uncharge_swap(swp_entry_t ent)
#define nr_swap_pages 0L
#define total_swap_pages 0L
#define total_swapcache_pages 0UL
+#define vm_swap_full(si) 0
#define si_swapinfo(val) \
do { (val)->freeswap = (val)->totalswap = 0; } while (0)
diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h
new file mode 100644
index 0000000..05c2147
--- /dev/null
+++ b/include/linux/zsmalloc.h
@@ -0,0 +1,51 @@
+/*
+ * zsmalloc memory allocator
+ *
+ * Copyright (C) 2011 Nitin Gupta
+ * Copyright (C) 2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the license that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ */
+
+#ifndef _ZS_MALLOC_H_
+#define _ZS_MALLOC_H_
+
+#include <linux/types.h>
+
+/*
+ * zsmalloc mapping modes
+ *
+ * NOTE: These only make a difference when a mapped object spans pages.
+ * They also have no effect when PGTABLE_MAPPING is selected.
+ */
+enum zs_mapmode {
+ ZS_MM_RW, /* normal read-write mapping */
+ ZS_MM_RO, /* read-only (no copy-out at unmap time) */
+ ZS_MM_WO /* write-only (no copy-in at map time) */
+ /*
+ * NOTE: ZS_MM_WO should only be used for initializing new
+ * (uninitialized) allocations. Partial writes to already
+ * initialized allocations should use ZS_MM_RW to preserve the
+ * existing data.
+ */
+};
+
+struct zs_pool;
+
+struct zs_pool *zs_create_pool(gfp_t flags);
+void zs_destroy_pool(struct zs_pool *pool);
+
+unsigned long zs_malloc(struct zs_pool *pool, size_t size);
+void zs_free(struct zs_pool *pool, unsigned long obj);
+
+void *zs_map_object(struct zs_pool *pool, unsigned long handle,
+ enum zs_mapmode mm);
+void zs_unmap_object(struct zs_pool *pool, unsigned long handle);
+
+unsigned long zs_get_total_pages(struct zs_pool *pool);
+
+#endif
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 0f6a452..4fdc312 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1250,6 +1250,8 @@ static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unli
{
if (sk->sk_send_head == skb_unlinked)
sk->sk_send_head = NULL;
+ if (tcp_sk(sk)->highest_sack == skb_unlinked)
+ tcp_sk(sk)->highest_sack = NULL;
}
static inline void tcp_init_send_head(struct sock *sk)
diff --git a/init/Kconfig b/init/Kconfig
index ae99e63..ac45380 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -130,10 +130,13 @@ config HAVE_KERNEL_XZ
config HAVE_KERNEL_LZO
bool
+config HAVE_KERNEL_LZ4
+ bool
+
choice
prompt "Kernel compression mode"
default KERNEL_GZIP
- depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO
+ depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4
help
The linux kernel is a kind of self-extracting executable.
Several compression algorithms are available, which differ
@@ -201,6 +204,18 @@ config KERNEL_LZO
size is about 10% bigger than gzip; however its speed
(both compression and decompression) is the fastest.
+config KERNEL_LZ4
+ bool "LZ4"
+ depends on HAVE_KERNEL_LZ4
+ help
+ LZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding.
+ A preliminary version of LZ4 de/compression tool is available at
+ <https://code.google.com/p/lz4/>.
+
+ Its compression ratio is worse than LZO. The size of the kernel
+ is about 8% bigger than LZO. But the decompression speed is
+ faster than LZO.
+
endchoice
config DEFAULT_HOSTNAME
diff --git a/kernel/events/core.c b/kernel/events/core.c
index acdc087..466213f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -604,6 +604,77 @@ static void put_ctx(struct perf_event_context *ctx)
}
}
+/*
+ * Because of perf_event::ctx migration in sys_perf_event_open::move_group and
+ * perf_pmu_migrate_context() we need some magic.
+ *
+ * Those places that change perf_event::ctx will hold both
+ * perf_event_ctx::mutex of the 'old' and 'new' ctx value.
+ *
+ * Lock ordering is by mutex address. There is one other site where
+ * perf_event_context::mutex nests and that is put_event(). But remember that
+ * that is a parent<->child context relation, and migration does not affect
+ * children, therefore these two orderings should not interact.
+ *
+ * The change in perf_event::ctx does not affect children (as claimed above)
+ * because the sys_perf_event_open() case will install a new event and break
+ * the ctx parent<->child relation, and perf_pmu_migrate_context() is only
+ * concerned with cpuctx and that doesn't have children.
+ *
+ * The places that change perf_event::ctx will issue:
+ *
+ * perf_remove_from_context();
+ * synchronize_rcu();
+ * perf_install_in_context();
+ *
+ * to affect the change. The remove_from_context() + synchronize_rcu() should
+ * quiesce the event, after which we can install it in the new location. This
+ * means that only external vectors (perf_fops, prctl) can perturb the event
+ * while in transit. Therefore all such accessors should also acquire
+ * perf_event_context::mutex to serialize against this.
+ *
+ * However; because event->ctx can change while we're waiting to acquire
+ * ctx->mutex we must be careful and use the below perf_event_ctx_lock()
+ * function.
+ *
+ * Lock order:
+ * task_struct::perf_event_mutex
+ * perf_event_context::mutex
+ * perf_event_context::lock
+ * perf_event::child_mutex;
+ * perf_event::mmap_mutex
+ * mmap_sem
+ */
+static struct perf_event_context *perf_event_ctx_lock(struct perf_event *event)
+{
+ struct perf_event_context *ctx;
+
+again:
+ rcu_read_lock();
+ ctx = ACCESS_ONCE(event->ctx);
+ if (!atomic_inc_not_zero(&ctx->refcount)) {
+ rcu_read_unlock();
+ goto again;
+ }
+ rcu_read_unlock();
+
+ mutex_lock(&ctx->mutex);
+ if (event->ctx != ctx) {
+ mutex_unlock(&ctx->mutex);
+ put_ctx(ctx);
+ goto again;
+ }
+
+ return ctx;
+}
+
+static void perf_event_ctx_unlock(struct perf_event *event,
+ struct perf_event_context *ctx)
+{
+ mutex_unlock(&ctx->mutex);
+ put_ctx(ctx);
+}
+
static void unclone_ctx(struct perf_event_context *ctx)
{
if (ctx->parent_ctx) {
@@ -1245,7 +1316,7 @@ static int __perf_event_disable(void *info)
* is the current context on this CPU and preemption is disabled,
* hence we can't get into perf_event_task_sched_out for this context.
*/
-void perf_event_disable(struct perf_event *event)
+static void _perf_event_disable(struct perf_event *event)
{
struct perf_event_context *ctx = event->ctx;
struct task_struct *task = ctx->task;
@@ -1287,6 +1358,19 @@ retry:
raw_spin_unlock_irq(&ctx->lock);
}
+/*
+ * Strictly speaking kernel users cannot create groups and therefore this
+ * interface does not need the perf_event_ctx_lock() magic.
+ */
+void perf_event_disable(struct perf_event *event)
+{
+ struct perf_event_context *ctx;
+
+ ctx = perf_event_ctx_lock(event);
+ _perf_event_disable(event);
+ perf_event_ctx_unlock(event, ctx);
+}
+
static void perf_set_shadow_time(struct perf_event *event,
struct perf_event_context *ctx,
u64 tstamp)
@@ -1580,6 +1664,8 @@ perf_install_in_context(struct perf_event_context *ctx,
lockdep_assert_held(&ctx->mutex);
event->ctx = ctx;
+ if (event->cpu != -1)
+ event->cpu = cpu;
if (!task) {
/*
@@ -1720,7 +1806,7 @@ unlock:
* perf_event_for_each_child or perf_event_for_each as described
* for perf_event_disable.
*/
-void perf_event_enable(struct perf_event *event)
+static void _perf_event_enable(struct perf_event *event)
{
struct perf_event_context *ctx = event->ctx;
struct task_struct *task = ctx->task;
@@ -1777,7 +1863,19 @@ out:
raw_spin_unlock_irq(&ctx->lock);
}
-static int perf_event_refresh(struct perf_event *event, int refresh)
+/*
+ * See perf_event_disable();
+ */
+void perf_event_enable(struct perf_event *event)
+{
+ struct perf_event_context *ctx;
+
+ ctx = perf_event_ctx_lock(event);
+ _perf_event_enable(event);
+ perf_event_ctx_unlock(event, ctx);
+}
+
+static int _perf_event_refresh(struct perf_event *event, int refresh)
{
/*
* not supported on inherited events
@@ -1786,11 +1884,26 @@ static int perf_event_refresh(struct perf_event *event, int refresh)
return -EINVAL;
atomic_add(refresh, &event->event_limit);
- perf_event_enable(event);
+ _perf_event_enable(event);
return 0;
}
+/*
+ * See perf_event_disable()
+ */
+int perf_event_refresh(struct perf_event *event, int refresh)
+{
+ struct perf_event_context *ctx;
+ int ret;
+
+ ctx = perf_event_ctx_lock(event);
+ ret = _perf_event_refresh(event, refresh);
+ perf_event_ctx_unlock(event, ctx);
+
+ return ret;
+}
+
static void ctx_sched_out(struct perf_event_context *ctx,
struct perf_cpu_context *cpuctx,
enum event_type_t event_type)
@@ -3034,7 +3147,16 @@ static void put_event(struct perf_event *event)
rcu_read_unlock();
if (owner) {
- mutex_lock(&owner->perf_event_mutex);
+ /*
+ * If we're here through perf_event_exit_task() we're already
+ * holding ctx->mutex which would be an inversion wrt. the
+ * normal lock order.
+ *
+ * However we can safely take this lock because its the child
+ * ctx->mutex.
+ */
+ mutex_lock_nested(&owner->perf_event_mutex, SINGLE_DEPTH_NESTING);
+
/*
* We have to re-check the event->owner field, if it is cleared
* we raced with perf_event_exit_task(), acquiring the mutex
@@ -3086,12 +3208,13 @@ static int perf_event_read_group(struct perf_event *event,
u64 read_format, char __user *buf)
{
struct perf_event *leader = event->group_leader, *sub;
- int n = 0, size = 0, ret = -EFAULT;
struct perf_event_context *ctx = leader->ctx;
- u64 values[5];
+ int n = 0, size = 0, ret;
u64 count, enabled, running;
+ u64 values[5];
+
+ lockdep_assert_held(&ctx->mutex);
- mutex_lock(&ctx->mutex);
count = perf_event_read_value(leader, &enabled, &running);
values[n++] = 1 + leader->nr_siblings;
@@ -3106,7 +3229,7 @@ static int perf_event_read_group(struct perf_event *event,
size = n * sizeof(u64);
if (copy_to_user(buf, values, size))
- goto unlock;
+ return -EFAULT;
ret = size;
@@ -3120,14 +3243,12 @@ static int perf_event_read_group(struct perf_event *event,
size = n * sizeof(u64);
if (copy_to_user(buf + ret, values, size)) {
- ret = -EFAULT;
- goto unlock;
+ return -EFAULT;
}
ret += size;
}
-unlock:
- mutex_unlock(&ctx->mutex);
+
return ret;
}
@@ -3186,8 +3307,14 @@ static ssize_t
perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct perf_event *event = file->private_data;
+ struct perf_event_context *ctx;
+ int ret;
+
+ ctx = perf_event_ctx_lock(event);
+ ret = perf_read_hw(event, buf, count);
+ perf_event_ctx_unlock(event, ctx);
- return perf_read_hw(event, buf, count);
+ return ret;
}
static unsigned int perf_poll(struct file *file, poll_table *wait)
@@ -3207,7 +3334,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait)
return events;
}
-static void perf_event_reset(struct perf_event *event)
+static void _perf_event_reset(struct perf_event *event)
{
(void)perf_event_read(event);
local64_set(&event->count, 0);
@@ -3306,25 +3433,24 @@ static int perf_event_set_output(struct perf_event *event,
struct perf_event *output_event);
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
-static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
{
- struct perf_event *event = file->private_data;
void (*func)(struct perf_event *);
u32 flags = arg;
switch (cmd) {
case PERF_EVENT_IOC_ENABLE:
- func = perf_event_enable;
+ func = _perf_event_enable;
break;
case PERF_EVENT_IOC_DISABLE:
- func = perf_event_disable;
+ func = _perf_event_disable;
break;
case PERF_EVENT_IOC_RESET:
- func = perf_event_reset;
+ func = _perf_event_reset;
break;
case PERF_EVENT_IOC_REFRESH:
- return perf_event_refresh(event, arg);
+ return _perf_event_refresh(event, arg);
case PERF_EVENT_IOC_PERIOD:
return perf_event_period(event, (u64 __user *)arg);
@@ -3365,13 +3491,30 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return 0;
}
+static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct perf_event *event = file->private_data;
+ struct perf_event_context *ctx;
+ long ret;
+
+ ctx = perf_event_ctx_lock(event);
+ ret = _perf_ioctl(event, cmd, arg);
+ perf_event_ctx_unlock(event, ctx);
+
+ return ret;
+}
+
int perf_event_task_enable(void)
{
+ struct perf_event_context *ctx;
struct perf_event *event;
mutex_lock(&current->perf_event_mutex);
- list_for_each_entry(event, &current->perf_event_list, owner_entry)
- perf_event_for_each_child(event, perf_event_enable);
+ list_for_each_entry(event, &current->perf_event_list, owner_entry) {
+ ctx = perf_event_ctx_lock(event);
+ perf_event_for_each_child(event, _perf_event_enable);
+ perf_event_ctx_unlock(event, ctx);
+ }
mutex_unlock(&current->perf_event_mutex);
return 0;
@@ -3379,11 +3522,15 @@ int perf_event_task_enable(void)
int perf_event_task_disable(void)
{
+ struct perf_event_context *ctx;
struct perf_event *event;
mutex_lock(&current->perf_event_mutex);
- list_for_each_entry(event, &current->perf_event_list, owner_entry)
- perf_event_for_each_child(event, perf_event_disable);
+ list_for_each_entry(event, &current->perf_event_list, owner_entry) {
+ ctx = perf_event_ctx_lock(event);
+ perf_event_for_each_child(event, _perf_event_disable);
+ perf_event_ctx_unlock(event, ctx);
+ }
mutex_unlock(&current->perf_event_mutex);
return 0;
@@ -5416,7 +5563,6 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
int err = 0;
mutex_lock(&swhash->hlist_mutex);
-
if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
struct swevent_hlist *hlist;
@@ -6216,6 +6362,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
if (!group_leader)
group_leader = event;
+ mutex_init(&event->group_leader_mutex);
mutex_init(&event->child_mutex);
INIT_LIST_HEAD(&event->child_list);
@@ -6444,6 +6591,15 @@ out:
return ret;
}
+static void mutex_lock_double(struct mutex *a, struct mutex *b)
+{
+ if (b < a)
+ swap(a, b);
+
+ mutex_lock(a);
+ mutex_lock_nested(b, SINGLE_DEPTH_NESTING);
+}
+
/**
* sys_perf_event_open - open a performance event, associate it to a task/cpu
*
@@ -6459,7 +6615,7 @@ SYSCALL_DEFINE5(perf_event_open,
struct perf_event *group_leader = NULL, *output_event = NULL;
struct perf_event *event, *sibling;
struct perf_event_attr attr;
- struct perf_event_context *ctx;
+ struct perf_event_context *ctx, *uninitialized_var(gctx);
struct file *event_file = NULL;
struct file *group_file = NULL;
struct task_struct *task = NULL;
@@ -6513,6 +6669,16 @@ SYSCALL_DEFINE5(perf_event_open,
group_leader = NULL;
}
+ /*
+ * Take the group_leader's group_leader_mutex before observing
+ * anything in the group leader that leads to changes in ctx,
+ * many of which may be changing on another thread.
+ * In particular, we want to take this lock before deciding
+ * whether we need to move_group.
+ */
+ if (group_leader)
+ mutex_lock(&group_leader->group_leader_mutex);
+
if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) {
task = find_lively_task_by_vpid(pid);
if (IS_ERR(task)) {
@@ -6572,7 +6738,7 @@ SYSCALL_DEFINE5(perf_event_open,
/*
* Get the target context (task or percpu):
*/
- ctx = find_get_context(pmu, task, cpu);
+ ctx = find_get_context(pmu, task, event->cpu);
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx);
goto err_alloc;
@@ -6627,9 +6793,14 @@ SYSCALL_DEFINE5(perf_event_open,
}
if (move_group) {
- struct perf_event_context *gctx = group_leader->ctx;
+ gctx = group_leader->ctx;
+
+ /*
+ * See perf_event_ctx_lock() for comments on the details
+ * of swizzling perf_event::ctx.
+ */
+ mutex_lock_double(&gctx->mutex, &ctx->mutex);
- mutex_lock(&gctx->mutex);
perf_remove_from_context(group_leader);
/*
@@ -6644,28 +6815,41 @@ SYSCALL_DEFINE5(perf_event_open,
perf_event__state_init(sibling);
put_ctx(gctx);
}
- mutex_unlock(&gctx->mutex);
- put_ctx(gctx);
+ } else {
+ mutex_lock(&ctx->mutex);
}
WARN_ON_ONCE(ctx->parent_ctx);
- mutex_lock(&ctx->mutex);
if (move_group) {
- perf_install_in_context(ctx, group_leader, cpu);
+ /*
+ * Wait for everybody to stop referencing the events through
+ * the old lists, before installing it on new lists.
+ */
+ synchronize_rcu();
+
+ perf_install_in_context(ctx, group_leader, event->cpu);
get_ctx(ctx);
list_for_each_entry(sibling, &group_leader->sibling_list,
group_entry) {
- perf_install_in_context(ctx, sibling, cpu);
+ perf_install_in_context(ctx, sibling, event->cpu);
get_ctx(ctx);
}
}
- perf_install_in_context(ctx, event, cpu);
+ perf_install_in_context(ctx, event, event->cpu);
++ctx->generation;
perf_unpin_context(ctx);
+
+ if (move_group) {
+ mutex_unlock(&gctx->mutex);
+ put_ctx(gctx);
+ }
mutex_unlock(&ctx->mutex);
+ if (group_leader)
+ mutex_unlock(&group_leader->group_leader_mutex);
+
event->owner = current;
mutex_lock(&current->perf_event_mutex);
@@ -6697,6 +6881,8 @@ err_task:
if (task)
put_task_struct(task);
err_group_fd:
+ if (group_leader)
+ mutex_unlock(&group_leader->group_leader_mutex);
fput_light(group_file, fput_needed);
err_fd:
put_unused_fd(event_fd);
@@ -6751,6 +6937,42 @@ err:
}
EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
+void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
+{
+ struct perf_event_context *src_ctx;
+ struct perf_event_context *dst_ctx;
+ struct perf_event *event, *tmp;
+ LIST_HEAD(events);
+
+ src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx;
+ dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx;
+
+ /*
+ * See perf_event_ctx_lock() for comments on the details
+ * of swizzling perf_event::ctx.
+ */
+ mutex_lock_double(&src_ctx->mutex, &dst_ctx->mutex);
+ list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
+ event_entry) {
+ perf_remove_from_context(event);
+ put_ctx(src_ctx);
+ list_add(&event->event_entry, &events);
+ }
+
+ synchronize_rcu();
+
+ list_for_each_entry_safe(event, tmp, &events, event_entry) {
+ list_del(&event->event_entry);
+ if (event->state >= PERF_EVENT_STATE_OFF)
+ event->state = PERF_EVENT_STATE_INACTIVE;
+ perf_install_in_context(dst_ctx, event, dst_cpu);
+ get_ctx(dst_ctx);
+ }
+ mutex_unlock(&dst_ctx->mutex);
+ mutex_unlock(&src_ctx->mutex);
+}
+EXPORT_SYMBOL_GPL(perf_pmu_migrate_context);
+
static void sync_child_event(struct perf_event *child_event,
struct task_struct *child)
{
@@ -7309,12 +7531,6 @@ static void perf_event_exit_cpu_context(int cpu)
static void perf_event_exit_cpu(int cpu)
{
- struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-
- mutex_lock(&swhash->hlist_mutex);
- swevent_hlist_release(swhash);
- mutex_unlock(&swhash->hlist_mutex);
-
perf_event_exit_cpu_context(cpu);
}
#else
diff --git a/kernel/exit.c b/kernel/exit.c
index 97dd317..6b8a7af 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -68,6 +68,7 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
detach_pid(p, PIDTYPE_SID);
list_del_rcu(&p->tasks);
+ delete_from_adj_tree(p);
list_del_init(&p->sibling);
__this_cpu_dec(process_counts);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index 158ca4f..ba7e2bc 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -317,6 +317,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
account_kernel_stack(ti, 1);
+ RB_CLEAR_NODE(&tsk->adj_node);
+
return tsk;
out:
@@ -1009,6 +1011,10 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
sig->oom_score_adj = current->signal->oom_score_adj;
sig->oom_score_adj_min = current->signal->oom_score_adj_min;
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ RB_CLEAR_NODE(&sig->adj_node);
+#endif
+
mutex_init(&sig->cred_guard_mutex);
return 0;
@@ -1375,6 +1381,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
attach_pid(p, PIDTYPE_SID, task_session(current));
list_add_tail(&p->sibling, &p->real_parent->children);
list_add_tail_rcu(&p->tasks, &init_task.tasks);
+ add_2_adj_tree(p);
__this_cpu_inc(process_counts);
}
attach_pid(p, PIDTYPE_PID, pid);
diff --git a/kernel/futex.c b/kernel/futex.c
index 7517c78..c7c19cb 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -588,55 +588,6 @@ void exit_pi_state_list(struct task_struct *curr)
raw_spin_unlock_irq(&curr->pi_lock);
}
-/*
- * We need to check the following states:
- *
- * Waiter | pi_state | pi->owner | uTID | uODIED | ?
- *
- * [1] NULL | --- | --- | 0 | 0/1 | Valid
- * [2] NULL | --- | --- | >0 | 0/1 | Valid
- *
- * [3] Found | NULL | -- | Any | 0/1 | Invalid
- *
- * [4] Found | Found | NULL | 0 | 1 | Valid
- * [5] Found | Found | NULL | >0 | 1 | Invalid
- *
- * [6] Found | Found | task | 0 | 1 | Valid
- *
- * [7] Found | Found | NULL | Any | 0 | Invalid
- *
- * [8] Found | Found | task | ==taskTID | 0/1 | Valid
- * [9] Found | Found | task | 0 | 0 | Invalid
- * [10] Found | Found | task | !=taskTID | 0/1 | Invalid
- *
- * [1] Indicates that the kernel can acquire the futex atomically. We
- * came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
- *
- * [2] Valid, if TID does not belong to a kernel thread. If no matching
- * thread is found then it indicates that the owner TID has died.
- *
- * [3] Invalid. The waiter is queued on a non PI futex
- *
- * [4] Valid state after exit_robust_list(), which sets the user space
- * value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
- *
- * [5] The user space value got manipulated between exit_robust_list()
- * and exit_pi_state_list()
- *
- * [6] Valid state after exit_pi_state_list() which sets the new owner in
- * the pi_state but cannot access the user space value.
- *
- * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
- *
- * [8] Owner and user space value match
- *
- * [9] There is no transient state which sets the user space TID to 0
- * except exit_robust_list(), but this is indicated by the
- * FUTEX_OWNER_DIED bit. See [4]
- *
- * [10] There is no transient state which leaves owner and user space
- * TID out of sync.
- */
static int
lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
union futex_key *key, struct futex_pi_state **ps)
@@ -652,13 +603,12 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
plist_for_each_entry_safe(this, next, head, list) {
if (match_futex(&this->key, key)) {
/*
- * Sanity check the waiter before increasing
- * the refcount and attaching to it.
+ * Another waiter already exists - bump up
+ * the refcount and return its pi_state:
*/
pi_state = this->pi_state;
/*
- * Userspace might have messed up non-PI and
- * PI futexes [3]
+ * Userspace might have messed up non-PI and PI futexes
*/
if (unlikely(!pi_state))
return -EINVAL;
@@ -666,70 +616,34 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
WARN_ON(!atomic_read(&pi_state->refcount));
/*
- * Handle the owner died case:
+ * When pi_state->owner is NULL then the owner died
+ * and another waiter is on the fly. pi_state->owner
+ * is fixed up by the task which acquires
+ * pi_state->rt_mutex.
+ *
+ * We do not check for pid == 0 which can happen when
+ * the owner died and robust_list_exit() cleared the
+ * TID.
*/
- if (uval & FUTEX_OWNER_DIED) {
+ if (pid && pi_state->owner) {
/*
- * exit_pi_state_list sets owner to NULL and
- * wakes the topmost waiter. The task which
- * acquires the pi_state->rt_mutex will fixup
- * owner.
+ * Bail out if user space manipulated the
+ * futex value.
*/
- if (!pi_state->owner) {
- /*
- * No pi state owner, but the user
- * space TID is not 0. Inconsistent
- * state. [5]
- */
- if (pid)
- return -EINVAL;
- /*
- * Take a ref on the state and
- * return. [4]
- */
- goto out_state;
- }
-
- /*
- * If TID is 0, then either the dying owner
- * has not yet executed exit_pi_state_list()
- * or some waiter acquired the rtmutex in the
- * pi state, but did not yet fixup the TID in
- * user space.
- *
- * Take a ref on the state and return. [6]
- */
- if (!pid)
- goto out_state;
- } else {
- /*
- * If the owner died bit is not set,
- * then the pi_state must have an
- * owner. [7]
- */
- if (!pi_state->owner)
+ if (pid != task_pid_vnr(pi_state->owner))
return -EINVAL;
}
- /*
- * Bail out if user space manipulated the
- * futex value. If pi state exists then the
- * owner TID must be the same as the user
- * space TID. [9/10]
- */
- if (pid != task_pid_vnr(pi_state->owner))
- return -EINVAL;
-
- out_state:
atomic_inc(&pi_state->refcount);
*ps = pi_state;
+
return 0;
}
}
/*
* We are the first waiter - try to look up the real owner and attach
- * the new pi_state to it, but bail out when TID = 0 [1]
+ * the new pi_state to it, but bail out when TID = 0
*/
if (!pid)
return -ESRCH;
@@ -737,11 +651,6 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
if (!p)
return -ESRCH;
- if (!p->mm) {
- put_task_struct(p);
- return -EPERM;
- }
-
/*
* We need to look at the task state flags to figure out,
* whether the task is exiting. To protect against the do_exit
@@ -762,9 +671,6 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
return ret;
}
- /*
- * No existing pi state. First waiter. [2]
- */
pi_state = alloc_pi_state();
/*
@@ -836,18 +742,10 @@ retry:
return -EDEADLK;
/*
- * Surprise - we got the lock, but we do not trust user space at all.
+ * Surprise - we got the lock. Just return to userspace:
*/
- if (unlikely(!curval)) {
- /*
- * We verify whether there is kernel state for this
- * futex. If not, we can safely assume, that the 0 ->
- * TID transition is correct. If state exists, we do
- * not bother to fixup the user space state as it was
- * corrupted already.
- */
- return futex_top_waiter(hb, key) ? -EINVAL : 1;
- }
+ if (unlikely(!curval))
+ return 1;
uval = curval;
@@ -977,7 +875,6 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
struct task_struct *new_owner;
struct futex_pi_state *pi_state = this->pi_state;
u32 curval, newval;
- int ret = 0;
if (!pi_state)
return -EINVAL;
@@ -1001,19 +898,23 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
new_owner = this->task;
/*
- * We pass it to the next owner. The WAITERS bit is always
- * kept enabled while there is PI state around. We cleanup the
- * owner died bit, because we are the owner.
+ * We pass it to the next owner. (The WAITERS bit is always
+ * kept enabled while there is PI state around. We must also
+ * preserve the owner died bit.)
*/
- newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
+ if (!(uval & FUTEX_OWNER_DIED)) {
+ int ret = 0;
- if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
- ret = -EFAULT;
- else if (curval != uval)
- ret = -EINVAL;
- if (ret) {
- raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
- return ret;
+ newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
+
+ if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
+ ret = -EFAULT;
+ else if (curval != uval)
+ ret = -EINVAL;
+ if (ret) {
+ raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
+ return ret;
+ }
}
raw_spin_lock_irq(&pi_state->owner->pi_lock);
@@ -1292,7 +1193,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
*
* Returns:
* 0 - failed to acquire the lock atomicly
- * >0 - acquired the lock, return value is vpid of the top_waiter
+ * 1 - acquired the lock
* <0 - error
*/
static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1303,7 +1204,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
{
struct futex_q *top_waiter = NULL;
u32 curval;
- int ret, vpid;
+ int ret;
if (get_futex_value_locked(&curval, pifutex))
return -EFAULT;
@@ -1331,14 +1232,11 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
* the contended case or if set_waiters is 1. The pi_state is returned
* in ps in contended cases.
*/
- vpid = task_pid_vnr(top_waiter->task);
ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
set_waiters);
- if (ret == 1) {
+ if (ret == 1)
requeue_pi_wake_futex(top_waiter, key2, hb2);
- return vpid;
- }
return ret;
}
@@ -1370,6 +1268,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
struct futex_hash_bucket *hb1, *hb2;
struct plist_head *head1;
struct futex_q *this, *next;
+ u32 curval2;
if (requeue_pi) {
/*
@@ -1471,25 +1370,16 @@ retry_private:
* At this point the top_waiter has either taken uaddr2 or is
* waiting on it. If the former, then the pi_state will not
* exist yet, look it up one more time to ensure we have a
- * reference to it. If the lock was taken, ret contains the
- * vpid of the top waiter task.
+ * reference to it.
*/
- if (ret > 0) {
+ if (ret == 1) {
WARN_ON(pi_state);
drop_count++;
task_count++;
- /*
- * If we acquired the lock, then the user
- * space value of uaddr2 should be vpid. It
- * cannot be changed by the top waiter as it
- * is blocked on hb2 lock if it tries to do
- * so. If something fiddled with it behind our
- * back the pi state lookup might unearth
- * it. So we rather use the known value than
- * rereading and handing potential crap to
- * lookup_pi_state.
- */
- ret = lookup_pi_state(ret, hb2, &key2, &pi_state);
+ ret = get_futex_value_locked(&curval2, uaddr2);
+ if (!ret)
+ ret = lookup_pi_state(curval2, hb2, &key2,
+ &pi_state);
}
switch (ret) {
@@ -2259,10 +2149,9 @@ retry:
/*
* To avoid races, try to do the TID -> 0 atomic transition
* again. If it succeeds then we can return without waking
- * anyone else up. We only try this if neither the waiters nor
- * the owner died bit are set.
+ * anyone else up:
*/
- if (!(uval & ~FUTEX_TID_MASK) &&
+ if (!(uval & FUTEX_OWNER_DIED) &&
cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
goto pi_faulted;
/*
@@ -2294,9 +2183,11 @@ retry:
/*
* No waiters - kernel unlocks the futex:
*/
- ret = unlock_futex_pi(uaddr, uval);
- if (ret == -EFAULT)
- goto pi_faulted;
+ if (!(uval & FUTEX_OWNER_DIED)) {
+ ret = unlock_futex_pi(uaddr, uval);
+ if (ret == -EFAULT)
+ goto pi_faulted;
+ }
out_unlock:
spin_unlock(&hb->lock);
diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
index e6303fd..f0fb629 100644
--- a/kernel/power/earlysuspend.c
+++ b/kernel/power/earlysuspend.c
@@ -20,9 +20,6 @@
#include <linux/syscalls.h> /* sys_sync */
#include <linux/wakelock.h>
#include <linux/workqueue.h>
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-#include <asm/atomic.h>
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
#include "power.h"
@@ -32,10 +29,6 @@ enum {
DEBUG_VERBOSE = 1U << 3,
};
static int debug_mask = DEBUG_USER_STATE;
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-atomic_t optimize_comp_on = ATOMIC_INIT(0);
-EXPORT_SYMBOL(optimize_comp_on);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
@@ -102,9 +95,6 @@ static void early_suspend(struct work_struct *work)
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- atomic_set(&optimize_comp_on, 1);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
if (state == SUSPEND_REQUESTED)
state |= SUSPENDED;
else
@@ -156,9 +146,6 @@ static void late_resume(struct work_struct *work)
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- atomic_set(&optimize_comp_on, 0);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
if (state == SUSPENDED)
state &= ~SUSPENDED;
else
diff --git a/kernel/sys.c b/kernel/sys.c
index be53817..79b66c0 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -40,6 +40,9 @@
#include <linux/syscore_ops.h>
#include <linux/version.h>
#include <linux/ctype.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mempolicy.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
@@ -1660,6 +1663,146 @@ SYSCALL_DEFINE1(umask, int, mask)
return mask;
}
+
+static int prctl_update_vma_anon_name(struct vm_area_struct *vma,
+ struct vm_area_struct **prev,
+ unsigned long start, unsigned long end,
+ const char __user *name_addr)
+{
+ struct mm_struct * mm = vma->vm_mm;
+ int error = 0;
+ pgoff_t pgoff;
+
+ if (name_addr == vma_get_anon_name(vma)) {
+ *prev = vma;
+ goto out;
+ }
+
+ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+ *prev = vma_merge(mm, *prev, start, end, vma->vm_flags, vma->anon_vma,
+ vma->vm_file, pgoff, vma_policy(vma),
+ name_addr);
+ if (*prev) {
+ vma = *prev;
+ goto success;
+ }
+
+ *prev = vma;
+
+ if (start != vma->vm_start) {
+ error = split_vma(mm, vma, start, 1);
+ if (error)
+ goto out;
+ }
+
+ if (end != vma->vm_end) {
+ error = split_vma(mm, vma, end, 0);
+ if (error)
+ goto out;
+ }
+
+success:
+ if (!vma->vm_file)
+ vma->shared.anon_name = name_addr;
+
+out:
+ if (error == -ENOMEM)
+ error = -EAGAIN;
+ return error;
+}
+
+static int prctl_set_vma_anon_name(unsigned long start, unsigned long end,
+ unsigned long arg)
+{
+ unsigned long tmp;
+ struct vm_area_struct * vma, *prev;
+ int unmapped_error = 0;
+ int error = -EINVAL;
+
+ /*
+ * If the interval [start,end) covers some unmapped address
+ * ranges, just ignore them, but return -ENOMEM at the end.
+ * - this matches the handling in madvise.
+ */
+ vma = find_vma_prev(current->mm, start, &prev);
+ if (vma && start > vma->vm_start)
+ prev = vma;
+
+ for (;;) {
+ /* Still start < end. */
+ error = -ENOMEM;
+ if (!vma)
+ return error;
+
+ /* Here start < (end|vma->vm_end). */
+ if (start < vma->vm_start) {
+ unmapped_error = -ENOMEM;
+ start = vma->vm_start;
+ if (start >= end)
+ return error;
+ }
+
+ /* Here vma->vm_start <= start < (end|vma->vm_end) */
+ tmp = vma->vm_end;
+ if (end < tmp)
+ tmp = end;
+
+ /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
+ error = prctl_update_vma_anon_name(vma, &prev, start, end,
+ (const char __user *)arg);
+ if (error)
+ return error;
+ start = tmp;
+ if (prev && start < prev->vm_end)
+ start = prev->vm_end;
+ error = unmapped_error;
+ if (start >= end)
+ return error;
+ if (prev)
+ vma = prev->vm_next;
+ else /* madvise_remove dropped mmap_sem */
+ vma = find_vma(current->mm, start);
+ }
+}
+
+static int prctl_set_vma(unsigned long opt, unsigned long start,
+ unsigned long len_in, unsigned long arg)
+{
+ struct mm_struct *mm = current->mm;
+ int error;
+ unsigned long len;
+ unsigned long end;
+
+ if (start & ~PAGE_MASK)
+ return -EINVAL;
+ len = (len_in + ~PAGE_MASK) & PAGE_MASK;
+
+ /* Check to see whether len was rounded up from small -ve to zero */
+ if (len_in && !len)
+ return -EINVAL;
+
+ end = start + len;
+ if (end < start)
+ return -EINVAL;
+
+ if (end == start)
+ return 0;
+
+ down_write(&mm->mmap_sem);
+
+ switch (opt) {
+ case PR_SET_VMA_ANON_NAME:
+ error = prctl_set_vma_anon_name(start, end, arg);
+ break;
+ default:
+ error = -EINVAL;
+ }
+
+ up_write(&mm->mmap_sem);
+
+ return error;
+}
+
SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
unsigned long, arg4, unsigned long, arg5)
{
@@ -1808,6 +1951,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
else
error = PR_MCE_KILL_DEFAULT;
break;
+ case PR_SET_VMA:
+ error = prctl_set_vma(arg2, arg3, arg4, arg5);
+ break;
default:
error = -EINVAL;
break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5b6afb2..3cd04f1 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1515,6 +1515,20 @@ static struct ctl_table fs_table[] = {
.proc_handler = &pipe_proc_fn,
.extra1 = &pipe_min_size,
},
+ {
+ .procname = "pipe-user-pages-hard",
+ .data = &pipe_user_pages_hard,
+ .maxlen = sizeof(pipe_user_pages_hard),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax,
+ },
+ {
+ .procname = "pipe-user-pages-soft",
+ .data = &pipe_user_pages_soft,
+ .maxlen = sizeof(pipe_user_pages_soft),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax,
+ },
{ }
};
diff --git a/lib/Kconfig b/lib/Kconfig
index 830181c..e07b9a0 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -99,6 +99,15 @@ config LZO_COMPRESS
config LZO_DECOMPRESS
tristate
+config LZ4_COMPRESS
+ tristate
+
+config LZ4HC_COMPRESS
+ tristate
+
+config LZ4_DECOMPRESS
+ tristate
+
source "lib/xz/Kconfig"
#
@@ -123,6 +132,10 @@ config DECOMPRESS_LZO
select LZO_DECOMPRESS
tristate
+config DECOMPRESS_LZ4
+ select LZ4_DECOMPRESS
+ tristate
+
#
# Generic allocator support is selected if needed
#
diff --git a/lib/Makefile b/lib/Makefile
index 578414a..a2b9ff8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -69,6 +69,9 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
obj-$(CONFIG_BCH) += bch.o
obj-$(CONFIG_LZO_COMPRESS) += lzo/
obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
+obj-$(CONFIG_LZ4_COMPRESS) += lz4/
+obj-$(CONFIG_LZ4HC_COMPRESS) += lz4/
+obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
obj-$(CONFIG_XZ_DEC) += xz/
obj-$(CONFIG_RAID6_PQ) += raid6/
@@ -77,6 +80,7 @@ lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
+lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
diff --git a/lib/decompress.c b/lib/decompress.c
index 3d766b7..fc3f2dd 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -11,6 +11,7 @@
#include <linux/decompress/unxz.h>
#include <linux/decompress/inflate.h>
#include <linux/decompress/unlzo.h>
+#include <linux/decompress/unlz4.h>
#include <linux/types.h>
#include <linux/string.h>
@@ -30,6 +31,9 @@
#ifndef CONFIG_DECOMPRESS_LZO
# define unlzo NULL
#endif
+#ifndef CONFIG_DECOMPRESS_LZ4
+# define unlz4 NULL
+#endif
static const struct compress_format {
unsigned char magic[2];
@@ -42,6 +46,7 @@ static const struct compress_format {
{ {0x5d, 0x00}, "lzma", unlzma },
{ {0xfd, 0x37}, "xz", unxz },
{ {0x89, 0x4c}, "lzo", unlzo },
+ { {0x02, 0x21}, "lz4", unlz4 },
{ {0, 0}, NULL, NULL }
};
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c
new file mode 100644
index 0000000..3e67cfa
--- /dev/null
+++ b/lib/decompress_unlz4.c
@@ -0,0 +1,187 @@
+/*
+ * Wrapper for decompressing LZ4-compressed kernel, initramfs, and initrd
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifdef STATIC
+#define PREBOOT
+#include "lz4/lz4_decompress.c"
+#else
+#include <linux/decompress/unlz4.h>
+#endif
+#include <linux/types.h>
+#include <linux/lz4.h>
+#include <linux/decompress/mm.h>
+#include <linux/compiler.h>
+
+#include <asm/unaligned.h>
+
+/*
+ * Note: Uncompressed chunk size is used in the compressor side
+ * (userspace side for compression).
+ * It is hardcoded because there is not proper way to extract it
+ * from the binary stream which is generated by the preliminary
+ * version of LZ4 tool so far.
+ */
+#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20)
+#define ARCHIVE_MAGICNUMBER 0x184C2102
+
+STATIC inline int INIT unlz4(u8 *input, int in_len,
+ int (*fill) (void *, unsigned int),
+ int (*flush) (void *, unsigned int),
+ u8 *output, int *posp,
+ void (*error) (char *x))
+{
+ int ret = -1;
+ size_t chunksize = 0;
+ size_t uncomp_chunksize = LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE;
+ u8 *inp;
+ u8 *inp_start;
+ u8 *outp;
+ int size = in_len;
+#ifdef PREBOOT
+ size_t out_len = get_unaligned_le32(input + in_len);
+#endif
+ size_t dest_len;
+
+
+ if (output) {
+ outp = output;
+ } else if (!flush) {
+ error("NULL output pointer and no flush function provided");
+ goto exit_0;
+ } else {
+ outp = large_malloc(uncomp_chunksize);
+ if (!outp) {
+ error("Could not allocate output buffer");
+ goto exit_0;
+ }
+ }
+
+ if (input && fill) {
+ error("Both input pointer and fill function provided,");
+ goto exit_1;
+ } else if (input) {
+ inp = input;
+ } else if (!fill) {
+ error("NULL input pointer and missing fill function");
+ goto exit_1;
+ } else {
+ inp = large_malloc(lz4_compressbound(uncomp_chunksize));
+ if (!inp) {
+ error("Could not allocate input buffer");
+ goto exit_1;
+ }
+ }
+ inp_start = inp;
+
+ if (posp)
+ *posp = 0;
+
+ if (fill)
+ fill(inp, 4);
+
+ chunksize = get_unaligned_le32(inp);
+ if (chunksize == ARCHIVE_MAGICNUMBER) {
+ inp += 4;
+ size -= 4;
+ } else {
+ error("invalid header");
+ goto exit_2;
+ }
+
+ if (posp)
+ *posp += 4;
+
+ for (;;) {
+
+ if (fill)
+ fill(inp, 4);
+
+ chunksize = get_unaligned_le32(inp);
+ if (chunksize == ARCHIVE_MAGICNUMBER) {
+ inp += 4;
+ size -= 4;
+ if (posp)
+ *posp += 4;
+ continue;
+ }
+ inp += 4;
+ size -= 4;
+
+ if (posp)
+ *posp += 4;
+
+ if (fill) {
+ if (chunksize > lz4_compressbound(uncomp_chunksize)) {
+ error("chunk length is longer than allocated");
+ goto exit_2;
+ }
+ fill(inp, chunksize);
+ }
+#ifdef PREBOOT
+ if (out_len >= uncomp_chunksize) {
+ dest_len = uncomp_chunksize;
+ out_len -= dest_len;
+ } else
+ dest_len = out_len;
+ ret = lz4_decompress(inp, &chunksize, outp, dest_len);
+#else
+ dest_len = uncomp_chunksize;
+ ret = lz4_decompress_unknownoutputsize(inp, chunksize, outp,
+ &dest_len);
+#endif
+ if (ret < 0) {
+ error("Decoding failed");
+ goto exit_2;
+ }
+
+ if (flush && flush(outp, dest_len) != dest_len)
+ goto exit_2;
+ if (output)
+ outp += dest_len;
+ if (posp)
+ *posp += chunksize;
+
+ size -= chunksize;
+
+ if (size == 0)
+ break;
+ else if (size < 0) {
+ error("data corrupted");
+ goto exit_2;
+ }
+
+ inp += chunksize;
+ if (fill)
+ inp = inp_start;
+ }
+
+ ret = 0;
+exit_2:
+ if (!input)
+ large_free(inp_start);
+exit_1:
+ if (!output)
+ large_free(outp);
+exit_0:
+ return ret;
+}
+
+#ifdef PREBOOT
+STATIC int INIT decompress(unsigned char *buf, int in_len,
+ int(*fill)(void*, unsigned int),
+ int(*flush)(void*, unsigned int),
+ unsigned char *output,
+ int *posp,
+ void(*error)(char *x)
+ )
+{
+ return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
+}
+#endif
diff --git a/lib/lz4/Makefile b/lib/lz4/Makefile
new file mode 100644
index 0000000..8085d04
--- /dev/null
+++ b/lib/lz4/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_LZ4_COMPRESS) += lz4_compress.o
+obj-$(CONFIG_LZ4HC_COMPRESS) += lz4hc_compress.o
+obj-$(CONFIG_LZ4_DECOMPRESS) += lz4_decompress.o
diff --git a/lib/lz4/lz4_compress.c b/lib/lz4/lz4_compress.c
new file mode 100644
index 0000000..28321d8
--- /dev/null
+++ b/lib/lz4/lz4_compress.c
@@ -0,0 +1,443 @@
+/*
+ * LZ4 - Fast LZ compression algorithm
+ * Copyright (C) 2011-2012, Yann Collet.
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You can contact the author at :
+ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ * - LZ4 source repository : http://code.google.com/p/lz4/
+ *
+ * Changed for kernel use by:
+ * Chanho Min <chanho.min@lge.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lz4.h>
+#include <asm/unaligned.h>
+#include "lz4defs.h"
+
+/*
+ * LZ4_compressCtx :
+ * -----------------
+ * Compress 'isize' bytes from 'source' into an output buffer 'dest' of
+ * maximum size 'maxOutputSize'. * If it cannot achieve it, compression
+ * will stop, and result of the function will be zero.
+ * return : the number of bytes written in buffer 'dest', or 0 if the
+ * compression fails
+ */
+static inline int lz4_compressctx(void *ctx,
+ const char *source,
+ char *dest,
+ int isize,
+ int maxoutputsize)
+{
+ HTYPE *hashtable = (HTYPE *)ctx;
+ const u8 *ip = (u8 *)source;
+#if LZ4_ARCH64
+ const BYTE * const base = ip;
+#else
+ const int base = 0;
+#endif
+ const u8 *anchor = ip;
+ const u8 *const iend = ip + isize;
+ const u8 *const mflimit = iend - MFLIMIT;
+ #define MATCHLIMIT (iend - LASTLITERALS)
+
+ u8 *op = (u8 *) dest;
+ u8 *const oend = op + maxoutputsize;
+ int length;
+ const int skipstrength = SKIPSTRENGTH;
+ u32 forwardh;
+ int lastrun;
+
+ /* Init */
+ if (isize < MINLENGTH)
+ goto _last_literals;
+
+ memset((void *)hashtable, 0, LZ4_MEM_COMPRESS);
+
+ /* First Byte */
+ hashtable[LZ4_HASH_VALUE(ip)] = ip - base;
+ ip++;
+ forwardh = LZ4_HASH_VALUE(ip);
+
+ /* Main Loop */
+ for (;;) {
+ int findmatchattempts = (1U << skipstrength) + 3;
+ const u8 *forwardip = ip;
+ const u8 *ref;
+ u8 *token;
+
+ /* Find a match */
+ do {
+ u32 h = forwardh;
+ int step = findmatchattempts++ >> skipstrength;
+ ip = forwardip;
+ forwardip = ip + step;
+
+ if (unlikely(forwardip > mflimit))
+ goto _last_literals;
+
+ forwardh = LZ4_HASH_VALUE(forwardip);
+ ref = base + hashtable[h];
+ hashtable[h] = ip - base;
+ } while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));
+
+ /* Catch up */
+ while ((ip > anchor) && (ref > (u8 *)source) &&
+ unlikely(ip[-1] == ref[-1])) {
+ ip--;
+ ref--;
+ }
+
+ /* Encode Literal length */
+ length = (int)(ip - anchor);
+ token = op++;
+ /* check output limit */
+ if (unlikely(op + length + (2 + 1 + LASTLITERALS) +
+ (length >> 8) > oend))
+ return 0;
+
+ if (length >= (int)RUN_MASK) {
+ int len;
+ *token = (RUN_MASK << ML_BITS);
+ len = length - RUN_MASK;
+ for (; len > 254 ; len -= 255)
+ *op++ = 255;
+ *op++ = (u8)len;
+ } else
+ *token = (length << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_BLINDCOPY(anchor, op, length);
+_next_match:
+ /* Encode Offset */
+ LZ4_WRITE_LITTLEENDIAN_16(op, (u16)(ip - ref));
+
+ /* Start Counting */
+ ip += MINMATCH;
+ /* MinMatch verified */
+ ref += MINMATCH;
+ anchor = ip;
+ while (likely(ip < MATCHLIMIT - (STEPSIZE - 1))) {
+ #if LZ4_ARCH64
+ u64 diff = A64(ref) ^ A64(ip);
+ #else
+ u32 diff = A32(ref) ^ A32(ip);
+ #endif
+ if (!diff) {
+ ip += STEPSIZE;
+ ref += STEPSIZE;
+ continue;
+ }
+ ip += LZ4_NBCOMMONBYTES(diff);
+ goto _endcount;
+ }
+ #if LZ4_ARCH64
+ if ((ip < (MATCHLIMIT - 3)) && (A32(ref) == A32(ip))) {
+ ip += 4;
+ ref += 4;
+ }
+ #endif
+ if ((ip < (MATCHLIMIT - 1)) && (A16(ref) == A16(ip))) {
+ ip += 2;
+ ref += 2;
+ }
+ if ((ip < MATCHLIMIT) && (*ref == *ip))
+ ip++;
+_endcount:
+ /* Encode MatchLength */
+ length = (int)(ip - anchor);
+ /* Check output limit */
+ if (unlikely(op + (1 + LASTLITERALS) + (length >> 8) > oend))
+ return 0;
+ if (length >= (int)ML_MASK) {
+ *token += ML_MASK;
+ length -= ML_MASK;
+ for (; length > 509 ; length -= 510) {
+ *op++ = 255;
+ *op++ = 255;
+ }
+ if (length > 254) {
+ length -= 255;
+ *op++ = 255;
+ }
+ *op++ = (u8)length;
+ } else
+ *token += length;
+
+ /* Test end of chunk */
+ if (ip > mflimit) {
+ anchor = ip;
+ break;
+ }
+
+ /* Fill table */
+ hashtable[LZ4_HASH_VALUE(ip-2)] = ip - 2 - base;
+
+ /* Test next position */
+ ref = base + hashtable[LZ4_HASH_VALUE(ip)];
+ hashtable[LZ4_HASH_VALUE(ip)] = ip - base;
+ if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) {
+ token = op++;
+ *token = 0;
+ goto _next_match;
+ }
+
+ /* Prepare next loop */
+ anchor = ip++;
+ forwardh = LZ4_HASH_VALUE(ip);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ lastrun = (int)(iend - anchor);
+ if (((char *)op - dest) + lastrun + 1
+ + ((lastrun + 255 - RUN_MASK) / 255) > (u32)maxoutputsize)
+ return 0;
+
+ if (lastrun >= (int)RUN_MASK) {
+ *op++ = (RUN_MASK << ML_BITS);
+ lastrun -= RUN_MASK;
+ for (; lastrun > 254 ; lastrun -= 255)
+ *op++ = 255;
+ *op++ = (u8)lastrun;
+ } else
+ *op++ = (lastrun << ML_BITS);
+ memcpy(op, anchor, iend - anchor);
+ op += iend - anchor;
+
+ /* End */
+ return (int)(((char *)op) - dest);
+}
+
+static inline int lz4_compress64kctx(void *ctx,
+ const char *source,
+ char *dest,
+ int isize,
+ int maxoutputsize)
+{
+ u16 *hashtable = (u16 *)ctx;
+ const u8 *ip = (u8 *) source;
+ const u8 *anchor = ip;
+ const u8 *const base = ip;
+ const u8 *const iend = ip + isize;
+ const u8 *const mflimit = iend - MFLIMIT;
+ #define MATCHLIMIT (iend - LASTLITERALS)
+
+ u8 *op = (u8 *) dest;
+ u8 *const oend = op + maxoutputsize;
+ int len, length;
+ const int skipstrength = SKIPSTRENGTH;
+ u32 forwardh;
+ int lastrun;
+
+ /* Init */
+ if (isize < MINLENGTH)
+ goto _last_literals;
+
+ memset((void *)hashtable, 0, LZ4_MEM_COMPRESS);
+
+ /* First Byte */
+ ip++;
+ forwardh = LZ4_HASH64K_VALUE(ip);
+
+ /* Main Loop */
+ for (;;) {
+ int findmatchattempts = (1U << skipstrength) + 3;
+ const u8 *forwardip = ip;
+ const u8 *ref;
+ u8 *token;
+
+ /* Find a match */
+ do {
+ u32 h = forwardh;
+ int step = findmatchattempts++ >> skipstrength;
+ ip = forwardip;
+ forwardip = ip + step;
+
+ if (forwardip > mflimit)
+ goto _last_literals;
+
+ forwardh = LZ4_HASH64K_VALUE(forwardip);
+ ref = base + hashtable[h];
+ hashtable[h] = (u16)(ip - base);
+ } while (A32(ref) != A32(ip));
+
+ /* Catch up */
+ while ((ip > anchor) && (ref > (u8 *)source)
+ && (ip[-1] == ref[-1])) {
+ ip--;
+ ref--;
+ }
+
+ /* Encode Literal length */
+ length = (int)(ip - anchor);
+ token = op++;
+ /* Check output limit */
+ if (unlikely(op + length + (2 + 1 + LASTLITERALS)
+ + (length >> 8) > oend))
+ return 0;
+ if (length >= (int)RUN_MASK) {
+ *token = (RUN_MASK << ML_BITS);
+ len = length - RUN_MASK;
+ for (; len > 254 ; len -= 255)
+ *op++ = 255;
+ *op++ = (u8)len;
+ } else
+ *token = (length << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_BLINDCOPY(anchor, op, length);
+
+_next_match:
+ /* Encode Offset */
+ LZ4_WRITE_LITTLEENDIAN_16(op, (u16)(ip - ref));
+
+ /* Start Counting */
+ ip += MINMATCH;
+ /* MinMatch verified */
+ ref += MINMATCH;
+ anchor = ip;
+
+ while (ip < MATCHLIMIT - (STEPSIZE - 1)) {
+ #if LZ4_ARCH64
+ u64 diff = A64(ref) ^ A64(ip);
+ #else
+ u32 diff = A32(ref) ^ A32(ip);
+ #endif
+
+ if (!diff) {
+ ip += STEPSIZE;
+ ref += STEPSIZE;
+ continue;
+ }
+ ip += LZ4_NBCOMMONBYTES(diff);
+ goto _endcount;
+ }
+ #if LZ4_ARCH64
+ if ((ip < (MATCHLIMIT - 3)) && (A32(ref) == A32(ip))) {
+ ip += 4;
+ ref += 4;
+ }
+ #endif
+ if ((ip < (MATCHLIMIT - 1)) && (A16(ref) == A16(ip))) {
+ ip += 2;
+ ref += 2;
+ }
+ if ((ip < MATCHLIMIT) && (*ref == *ip))
+ ip++;
+_endcount:
+
+ /* Encode MatchLength */
+ len = (int)(ip - anchor);
+ /* Check output limit */
+ if (unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend))
+ return 0;
+ if (len >= (int)ML_MASK) {
+ *token += ML_MASK;
+ len -= ML_MASK;
+ for (; len > 509 ; len -= 510) {
+ *op++ = 255;
+ *op++ = 255;
+ }
+ if (len > 254) {
+ len -= 255;
+ *op++ = 255;
+ }
+ *op++ = (u8)len;
+ } else
+ *token += len;
+
+ /* Test end of chunk */
+ if (ip > mflimit) {
+ anchor = ip;
+ break;
+ }
+
+ /* Fill table */
+ hashtable[LZ4_HASH64K_VALUE(ip-2)] = (u16)(ip - 2 - base);
+
+ /* Test next position */
+ ref = base + hashtable[LZ4_HASH64K_VALUE(ip)];
+ hashtable[LZ4_HASH64K_VALUE(ip)] = (u16)(ip - base);
+ if (A32(ref) == A32(ip)) {
+ token = op++;
+ *token = 0;
+ goto _next_match;
+ }
+
+ /* Prepare next loop */
+ anchor = ip++;
+ forwardh = LZ4_HASH64K_VALUE(ip);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ lastrun = (int)(iend - anchor);
+ if (op + lastrun + 1 + (lastrun - RUN_MASK + 255) / 255 > oend)
+ return 0;
+ if (lastrun >= (int)RUN_MASK) {
+ *op++ = (RUN_MASK << ML_BITS);
+ lastrun -= RUN_MASK;
+ for (; lastrun > 254 ; lastrun -= 255)
+ *op++ = 255;
+ *op++ = (u8)lastrun;
+ } else
+ *op++ = (lastrun << ML_BITS);
+ memcpy(op, anchor, iend - anchor);
+ op += iend - anchor;
+ /* End */
+ return (int)(((char *)op) - dest);
+}
+
+int lz4_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem)
+{
+ int ret = -1;
+ int out_len = 0;
+
+ if (src_len < LZ4_64KLIMIT)
+ out_len = lz4_compress64kctx(wrkmem, src, dst, src_len,
+ lz4_compressbound(src_len));
+ else
+ out_len = lz4_compressctx(wrkmem, src, dst, src_len,
+ lz4_compressbound(src_len));
+
+ if (out_len < 0)
+ goto exit;
+
+ *dst_len = out_len;
+
+ return 0;
+exit:
+ return ret;
+}
+EXPORT_SYMBOL(lz4_compress);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("LZ4 compressor");
diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c
new file mode 100644
index 0000000..7a85967
--- /dev/null
+++ b/lib/lz4/lz4_decompress.c
@@ -0,0 +1,334 @@
+/*
+ * LZ4 Decompressor for Linux kernel
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
+ *
+ * Based on LZ4 implementation by Yann Collet.
+ *
+ * LZ4 - Fast LZ compression algorithm
+ * Copyright (C) 2011-2012, Yann Collet.
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You can contact the author at :
+ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ * - LZ4 source repository : http://code.google.com/p/lz4/
+ */
+
+#ifndef STATIC
+#include <linux/module.h>
+#include <linux/kernel.h>
+#endif
+#include <linux/lz4.h>
+
+#include <asm/unaligned.h>
+
+#include "lz4defs.h"
+
+static int lz4_uncompress(const char *source, char *dest, int osize)
+{
+ const BYTE *ip = (const BYTE *) source;
+ const BYTE *ref;
+ BYTE *op = (BYTE *) dest;
+ BYTE * const oend = op + osize;
+ BYTE *cpy;
+ unsigned token;
+ size_t length;
+ size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
+#if LZ4_ARCH64
+ size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
+#endif
+
+ while (1) {
+
+ /* get runlength */
+ token = *ip++;
+ length = (token >> ML_BITS);
+ if (length == RUN_MASK) {
+ size_t len;
+
+ len = *ip++;
+ for (; len == 255; length += 255)
+ len = *ip++;
+ if (unlikely(length > (size_t)(length + len)))
+ goto _output_error;
+ length += len;
+ }
+
+ /* copy literals */
+ cpy = op + length;
+ if (unlikely(cpy > oend - COPYLENGTH)) {
+ /*
+ * Error: not enough place for another match
+ * (min 4) + 5 literals
+ */
+ if (cpy != oend)
+ goto _output_error;
+
+ memcpy(op, ip, length);
+ ip += length;
+ break; /* EOF */
+ }
+ LZ4_WILDCOPY(ip, op, cpy);
+ ip -= (op - cpy);
+ op = cpy;
+
+ /* get offset */
+ LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
+ ip += 2;
+
+ /* Error: offset create reference outside destination buffer */
+ if (unlikely(ref < (BYTE *const) dest))
+ goto _output_error;
+
+ /* get matchlength */
+ length = token & ML_MASK;
+ if (length == ML_MASK) {
+ for (; *ip == 255; length += 255)
+ ip++;
+ if (unlikely(length > (size_t)(length + *ip)))
+ goto _output_error;
+ length += *ip++;
+ }
+
+ /* copy repeated sequence */
+ if (unlikely((op - ref) < STEPSIZE)) {
+#if LZ4_ARCH64
+ size_t dec64 = dec64table[op - ref];
+#else
+ const int dec64 = 0;
+#endif
+ op[0] = ref[0];
+ op[1] = ref[1];
+ op[2] = ref[2];
+ op[3] = ref[3];
+ op += 4;
+ ref += 4;
+ ref -= dec32table[op-ref];
+ PUT4(ref, op);
+ op += STEPSIZE - 4;
+ ref -= dec64;
+ } else {
+ LZ4_COPYSTEP(ref, op);
+ }
+ cpy = op + length - (STEPSIZE - 4);
+ if (cpy > (oend - COPYLENGTH)) {
+
+ /* Error: request to write beyond destination buffer */
+ if (cpy > oend)
+ goto _output_error;
+ LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
+ while (op < cpy)
+ *op++ = *ref++;
+ op = cpy;
+ /*
+ * Check EOF (should never happen, since last 5 bytes
+ * are supposed to be literals)
+ */
+ if (op == oend)
+ goto _output_error;
+ continue;
+ }
+ LZ4_SECURECOPY(ref, op, cpy);
+ op = cpy; /* correction */
+ }
+ /* end of decoding */
+ return (int) (((char *)ip) - source);
+
+ /* write overflow error detected */
+_output_error:
+ return -1;
+}
+
+static int lz4_uncompress_unknownoutputsize(const char *source, char *dest,
+ int isize, size_t maxoutputsize)
+{
+ const BYTE *ip = (const BYTE *) source;
+ const BYTE *const iend = ip + isize;
+ const BYTE *ref;
+
+
+ BYTE *op = (BYTE *) dest;
+ BYTE * const oend = op + maxoutputsize;
+ BYTE *cpy;
+
+ size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
+#if LZ4_ARCH64
+ size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
+#endif
+
+ /* Main Loop */
+ while (ip < iend) {
+
+ unsigned token;
+ size_t length;
+
+ /* get runlength */
+ token = *ip++;
+ length = (token >> ML_BITS);
+ if (length == RUN_MASK) {
+ int s = 255;
+ while ((ip < iend) && (s == 255)) {
+ s = *ip++;
+ if (unlikely(length > (size_t)(length + s)))
+ goto _output_error;
+ length += s;
+ }
+ }
+ /* copy literals */
+ cpy = op + length;
+ if ((cpy > oend - COPYLENGTH) ||
+ (ip + length > iend - COPYLENGTH)) {
+
+ if (cpy > oend)
+ goto _output_error;/* writes beyond buffer */
+
+ if (ip + length != iend)
+ goto _output_error;/*
+ * Error: LZ4 format requires
+ * to consume all input
+ * at this stage
+ */
+ memcpy(op, ip, length);
+ op += length;
+ break;/* Necessarily EOF, due to parsing restrictions */
+ }
+ LZ4_WILDCOPY(ip, op, cpy);
+ ip -= (op - cpy);
+ op = cpy;
+
+ /* get offset */
+ LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
+ ip += 2;
+ if (ref < (BYTE * const) dest)
+ goto _output_error;
+ /*
+ * Error : offset creates reference
+ * outside of destination buffer
+ */
+
+ /* get matchlength */
+ length = (token & ML_MASK);
+ if (length == ML_MASK) {
+ while (ip < iend) {
+ int s = *ip++;
+ if (unlikely(length > (size_t)(length + s)))
+ goto _output_error;
+ length += s;
+ if (s == 255)
+ continue;
+ break;
+ }
+ }
+
+ /* copy repeated sequence */
+ if (unlikely((op - ref) < STEPSIZE)) {
+#if LZ4_ARCH64
+ size_t dec64 = dec64table[op - ref];
+#else
+ const int dec64 = 0;
+#endif
+ op[0] = ref[0];
+ op[1] = ref[1];
+ op[2] = ref[2];
+ op[3] = ref[3];
+ op += 4;
+ ref += 4;
+ ref -= dec32table[op - ref];
+ PUT4(ref, op);
+ op += STEPSIZE - 4;
+ ref -= dec64;
+ } else {
+ LZ4_COPYSTEP(ref, op);
+ }
+ cpy = op + length - (STEPSIZE-4);
+ if (cpy > oend - COPYLENGTH) {
+ if (cpy > oend)
+ goto _output_error; /* write outside of buf */
+
+ LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
+ while (op < cpy)
+ *op++ = *ref++;
+ op = cpy;
+ /*
+ * Check EOF (should never happen, since last 5 bytes
+ * are supposed to be literals)
+ */
+ if (op == oend)
+ goto _output_error;
+ continue;
+ }
+ LZ4_SECURECOPY(ref, op, cpy);
+ op = cpy; /* correction */
+ }
+ /* end of decoding */
+ return (int) (((char *) op) - dest);
+
+ /* write overflow error detected */
+_output_error:
+ return -1;
+}
+
+int lz4_decompress(const unsigned char *src, size_t *src_len,
+ unsigned char *dest, size_t actual_dest_len)
+{
+ int ret = -1;
+ int input_len = 0;
+
+ input_len = lz4_uncompress(src, dest, actual_dest_len);
+ if (input_len < 0)
+ goto exit_0;
+ *src_len = input_len;
+
+ return 0;
+exit_0:
+ return ret;
+}
+#ifndef STATIC
+EXPORT_SYMBOL(lz4_decompress);
+#endif
+
+int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len,
+ unsigned char *dest, size_t *dest_len)
+{
+ int ret = -1;
+ int out_len = 0;
+
+ out_len = lz4_uncompress_unknownoutputsize(src, dest, src_len,
+ *dest_len);
+ if (out_len < 0)
+ goto exit_0;
+ *dest_len = out_len;
+
+ return 0;
+exit_0:
+ return ret;
+}
+#ifndef STATIC
+EXPORT_SYMBOL(lz4_decompress_unknownoutputsize);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("LZ4 Decompressor");
+#endif
diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h
new file mode 100644
index 0000000..9b4182f
--- /dev/null
+++ b/lib/lz4/lz4defs.h
@@ -0,0 +1,157 @@
+/*
+ * lz4defs.h -- architecture specific defines
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Detects 64 bits mode
+ */
+#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) \
+ || defined(__ppc64__) || defined(__LP64__))
+#define LZ4_ARCH64 1
+#else
+#define LZ4_ARCH64 0
+#endif
+
+/*
+ * Architecture-specific macros
+ */
+#define ARM_EFFICIENT_UNALIGNED_ACCESS
+#define BYTE u8
+typedef struct _U16_S { u16 v; } U16_S;
+typedef struct _U32_S { u32 v; } U32_S;
+typedef struct _U64_S { u64 v; } U64_S;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) \
+ || defined(CONFIG_ARM) && __LINUX_ARM_ARCH__ >= 6 \
+ && defined(ARM_EFFICIENT_UNALIGNED_ACCESS)
+
+#define A16(x) (((U16_S *)(x))->v)
+#define A32(x) (((U32_S *)(x))->v)
+#define A64(x) (((U64_S *)(x))->v)
+
+#define PUT4(s, d) (A32(d) = A32(s))
+#define PUT8(s, d) (A64(d) = A64(s))
+#define LZ4_WRITE_LITTLEENDIAN_16(p, v) \
+ do { \
+ A16(p) = v; \
+ p += 2; \
+ } while (0)
+#else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+
+#define A64(x) get_unaligned((u64 *)&(((U16_S *)(x))->v))
+#define A32(x) get_unaligned((u32 *)&(((U16_S *)(x))->v))
+#define A16(x) get_unaligned((u16 *)&(((U16_S *)(x))->v))
+
+#define PUT4(s, d) \
+ put_unaligned(get_unaligned((const u32 *) s), (u32 *) d)
+#define PUT8(s, d) \
+ put_unaligned(get_unaligned((const u64 *) s), (u64 *) d)
+
+#define LZ4_WRITE_LITTLEENDIAN_16(p, v) \
+ do { \
+ put_unaligned(v, (u16 *)(p)); \
+ p += 2; \
+ } while (0)
+#endif
+
+#define COPYLENGTH 8
+#define ML_BITS 4
+#define ML_MASK ((1U << ML_BITS) - 1)
+#define RUN_BITS (8 - ML_BITS)
+#define RUN_MASK ((1U << RUN_BITS) - 1)
+#define MEMORY_USAGE 14
+#define MINMATCH 4
+#define SKIPSTRENGTH 6
+#define LASTLITERALS 5
+#define MFLIMIT (COPYLENGTH + MINMATCH)
+#define MINLENGTH (MFLIMIT + 1)
+#define MAXD_LOG 16
+#define MAXD (1 << MAXD_LOG)
+#define MAXD_MASK (u32)(MAXD - 1)
+#define MAX_DISTANCE (MAXD - 1)
+#define HASH_LOG (MAXD_LOG - 1)
+#define HASHTABLESIZE (1 << HASH_LOG)
+#define MAX_NB_ATTEMPTS 256
+#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
+#define LZ4_64KLIMIT ((1<<16) + (MFLIMIT - 1))
+#define HASHLOG64K ((MEMORY_USAGE - 2) + 1)
+#define HASH64KTABLESIZE (1U << HASHLOG64K)
+#define LZ4_HASH_VALUE(p) (((A32(p)) * 2654435761U) >> \
+ ((MINMATCH * 8) - (MEMORY_USAGE-2)))
+#define LZ4_HASH64K_VALUE(p) (((A32(p)) * 2654435761U) >> \
+ ((MINMATCH * 8) - HASHLOG64K))
+#define HASH_VALUE(p) (((A32(p)) * 2654435761U) >> \
+ ((MINMATCH * 8) - HASH_LOG))
+
+#if LZ4_ARCH64/* 64-bit */
+#define STEPSIZE 8
+
+#define LZ4_COPYSTEP(s, d) \
+ do { \
+ PUT8(s, d); \
+ d += 8; \
+ s += 8; \
+ } while (0)
+
+#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d)
+
+#define LZ4_SECURECOPY(s, d, e) \
+ do { \
+ if (d < e) { \
+ LZ4_WILDCOPY(s, d, e); \
+ } \
+ } while (0)
+#define HTYPE u32
+
+#ifdef __BIG_ENDIAN
+#define LZ4_NBCOMMONBYTES(val) (__builtin_clzll(val) >> 3)
+#else
+#define LZ4_NBCOMMONBYTES(val) (__builtin_ctzll(val) >> 3)
+#endif
+
+#else /* 32-bit */
+#define STEPSIZE 4
+
+#define LZ4_COPYSTEP(s, d) \
+ do { \
+ PUT4(s, d); \
+ d += 4; \
+ s += 4; \
+ } while (0)
+
+#define LZ4_COPYPACKET(s, d) \
+ do { \
+ LZ4_COPYSTEP(s, d); \
+ LZ4_COPYSTEP(s, d); \
+ } while (0)
+
+#define LZ4_SECURECOPY LZ4_WILDCOPY
+#define HTYPE const u8*
+
+#ifdef __BIG_ENDIAN
+#define LZ4_NBCOMMONBYTES(val) (__builtin_clz(val) >> 3)
+#else
+#define LZ4_NBCOMMONBYTES(val) (__builtin_ctz(val) >> 3)
+#endif
+
+#endif
+
+#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \
+ (d = s - get_unaligned_le16(p))
+
+#define LZ4_WILDCOPY(s, d, e) \
+ do { \
+ LZ4_COPYPACKET(s, d); \
+ } while (d < e)
+
+#define LZ4_BLINDCOPY(s, d, l) \
+ do { \
+ u8 *e = (d) + l; \
+ LZ4_WILDCOPY(s, d, e); \
+ d = e; \
+ } while (0)
diff --git a/lib/lz4/lz4hc_compress.c b/lib/lz4/lz4hc_compress.c
new file mode 100644
index 0000000..f344f76
--- /dev/null
+++ b/lib/lz4/lz4hc_compress.c
@@ -0,0 +1,539 @@
+/*
+ * LZ4 HC - High Compression Mode of LZ4
+ * Copyright (C) 2011-2012, Yann Collet.
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You can contact the author at :
+ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ * - LZ4 source repository : http://code.google.com/p/lz4/
+ *
+ * Changed for kernel use by:
+ * Chanho Min <chanho.min@lge.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lz4.h>
+#include <asm/unaligned.h>
+#include "lz4defs.h"
+
+struct lz4hc_data {
+ const u8 *base;
+ HTYPE hashtable[HASHTABLESIZE];
+ u16 chaintable[MAXD];
+ const u8 *nexttoupdate;
+} __attribute__((__packed__));
+
+static inline int lz4hc_init(struct lz4hc_data *hc4, const u8 *base)
+{
+ memset((void *)hc4->hashtable, 0, sizeof(hc4->hashtable));
+ memset(hc4->chaintable, 0xFF, sizeof(hc4->chaintable));
+
+#if LZ4_ARCH64
+ hc4->nexttoupdate = base + 1;
+#else
+ hc4->nexttoupdate = base;
+#endif
+ hc4->base = base;
+ return 1;
+}
+
+/* Update chains up to ip (excluded) */
+static inline void lz4hc_insert(struct lz4hc_data *hc4, const u8 *ip)
+{
+ u16 *chaintable = hc4->chaintable;
+ HTYPE *hashtable = hc4->hashtable;
+#if LZ4_ARCH64
+ const BYTE * const base = hc4->base;
+#else
+ const int base = 0;
+#endif
+
+ while (hc4->nexttoupdate < ip) {
+ const u8 *p = hc4->nexttoupdate;
+ size_t delta = p - (hashtable[HASH_VALUE(p)] + base);
+ if (delta > MAX_DISTANCE)
+ delta = MAX_DISTANCE;
+ chaintable[(size_t)(p) & MAXD_MASK] = (u16)delta;
+ hashtable[HASH_VALUE(p)] = (p) - base;
+ hc4->nexttoupdate++;
+ }
+}
+
+static inline size_t lz4hc_commonlength(const u8 *p1, const u8 *p2,
+ const u8 *const matchlimit)
+{
+ const u8 *p1t = p1;
+
+ while (p1t < matchlimit - (STEPSIZE - 1)) {
+#if LZ4_ARCH64
+ u64 diff = A64(p2) ^ A64(p1t);
+#else
+ u32 diff = A32(p2) ^ A32(p1t);
+#endif
+ if (!diff) {
+ p1t += STEPSIZE;
+ p2 += STEPSIZE;
+ continue;
+ }
+ p1t += LZ4_NBCOMMONBYTES(diff);
+ return p1t - p1;
+ }
+#if LZ4_ARCH64
+ if ((p1t < (matchlimit-3)) && (A32(p2) == A32(p1t))) {
+ p1t += 4;
+ p2 += 4;
+ }
+#endif
+
+ if ((p1t < (matchlimit - 1)) && (A16(p2) == A16(p1t))) {
+ p1t += 2;
+ p2 += 2;
+ }
+ if ((p1t < matchlimit) && (*p2 == *p1t))
+ p1t++;
+ return p1t - p1;
+}
+
+static inline int lz4hc_insertandfindbestmatch(struct lz4hc_data *hc4,
+ const u8 *ip, const u8 *const matchlimit, const u8 **matchpos)
+{
+ u16 *const chaintable = hc4->chaintable;
+ HTYPE *const hashtable = hc4->hashtable;
+ const u8 *ref;
+#if LZ4_ARCH64
+ const BYTE * const base = hc4->base;
+#else
+ const int base = 0;
+#endif
+ int nbattempts = MAX_NB_ATTEMPTS;
+ size_t repl = 0, ml = 0;
+ u16 delta;
+
+ /* HC4 match finder */
+ lz4hc_insert(hc4, ip);
+ ref = hashtable[HASH_VALUE(ip)] + base;
+
+ /* potential repetition */
+ if (ref >= ip-4) {
+ /* confirmed */
+ if (A32(ref) == A32(ip)) {
+ delta = (u16)(ip-ref);
+ repl = ml = lz4hc_commonlength(ip + MINMATCH,
+ ref + MINMATCH, matchlimit) + MINMATCH;
+ *matchpos = ref;
+ }
+ ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK];
+ }
+
+ while ((ref >= ip - MAX_DISTANCE) && nbattempts) {
+ nbattempts--;
+ if (*(ref + ml) == *(ip + ml)) {
+ if (A32(ref) == A32(ip)) {
+ size_t mlt =
+ lz4hc_commonlength(ip + MINMATCH,
+ ref + MINMATCH, matchlimit) + MINMATCH;
+ if (mlt > ml) {
+ ml = mlt;
+ *matchpos = ref;
+ }
+ }
+ }
+ ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK];
+ }
+
+ /* Complete table */
+ if (repl) {
+ const BYTE *ptr = ip;
+ const BYTE *end;
+ end = ip + repl - (MINMATCH-1);
+ /* Pre-Load */
+ while (ptr < end - delta) {
+ chaintable[(size_t)(ptr) & MAXD_MASK] = delta;
+ ptr++;
+ }
+ do {
+ chaintable[(size_t)(ptr) & MAXD_MASK] = delta;
+ /* Head of chain */
+ hashtable[HASH_VALUE(ptr)] = (ptr) - base;
+ ptr++;
+ } while (ptr < end);
+ hc4->nexttoupdate = end;
+ }
+
+ return (int)ml;
+}
+
+static inline int lz4hc_insertandgetwidermatch(struct lz4hc_data *hc4,
+ const u8 *ip, const u8 *startlimit, const u8 *matchlimit, int longest,
+ const u8 **matchpos, const u8 **startpos)
+{
+ u16 *const chaintable = hc4->chaintable;
+ HTYPE *const hashtable = hc4->hashtable;
+#if LZ4_ARCH64
+ const BYTE * const base = hc4->base;
+#else
+ const int base = 0;
+#endif
+ const u8 *ref;
+ int nbattempts = MAX_NB_ATTEMPTS;
+ int delta = (int)(ip - startlimit);
+
+ /* First Match */
+ lz4hc_insert(hc4, ip);
+ ref = hashtable[HASH_VALUE(ip)] + base;
+
+ while ((ref >= ip - MAX_DISTANCE) && (ref >= hc4->base)
+ && (nbattempts)) {
+ nbattempts--;
+ if (*(startlimit + longest) == *(ref - delta + longest)) {
+ if (A32(ref) == A32(ip)) {
+ const u8 *reft = ref + MINMATCH;
+ const u8 *ipt = ip + MINMATCH;
+ const u8 *startt = ip;
+
+ while (ipt < matchlimit-(STEPSIZE - 1)) {
+ #if LZ4_ARCH64
+ u64 diff = A64(reft) ^ A64(ipt);
+ #else
+ u32 diff = A32(reft) ^ A32(ipt);
+ #endif
+
+ if (!diff) {
+ ipt += STEPSIZE;
+ reft += STEPSIZE;
+ continue;
+ }
+ ipt += LZ4_NBCOMMONBYTES(diff);
+ goto _endcount;
+ }
+ #if LZ4_ARCH64
+ if ((ipt < (matchlimit - 3))
+ && (A32(reft) == A32(ipt))) {
+ ipt += 4;
+ reft += 4;
+ }
+ ipt += 2;
+ #endif
+ if ((ipt < (matchlimit - 1))
+ && (A16(reft) == A16(ipt))) {
+ reft += 2;
+ }
+ if ((ipt < matchlimit) && (*reft == *ipt))
+ ipt++;
+_endcount:
+ reft = ref;
+
+ while ((startt > startlimit)
+ && (reft > hc4->base)
+ && (startt[-1] == reft[-1])) {
+ startt--;
+ reft--;
+ }
+
+ if ((ipt - startt) > longest) {
+ longest = (int)(ipt - startt);
+ *matchpos = reft;
+ *startpos = startt;
+ }
+ }
+ }
+ ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK];
+ }
+ return longest;
+}
+
+static inline int lz4_encodesequence(const u8 **ip, u8 **op, const u8 **anchor,
+ int ml, const u8 *ref)
+{
+ int length, len;
+ u8 *token;
+
+ /* Encode Literal length */
+ length = (int)(*ip - *anchor);
+ token = (*op)++;
+ if (length >= (int)RUN_MASK) {
+ *token = (RUN_MASK << ML_BITS);
+ len = length - RUN_MASK;
+ for (; len > 254 ; len -= 255)
+ *(*op)++ = 255;
+ *(*op)++ = (u8)len;
+ } else
+ *token = (length << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_BLINDCOPY(*anchor, *op, length);
+
+ /* Encode Offset */
+ LZ4_WRITE_LITTLEENDIAN_16(*op, (u16)(*ip - ref));
+
+ /* Encode MatchLength */
+ len = (int)(ml - MINMATCH);
+ if (len >= (int)ML_MASK) {
+ *token += ML_MASK;
+ len -= ML_MASK;
+ for (; len > 509 ; len -= 510) {
+ *(*op)++ = 255;
+ *(*op)++ = 255;
+ }
+ if (len > 254) {
+ len -= 255;
+ *(*op)++ = 255;
+ }
+ *(*op)++ = (u8)len;
+ } else
+ *token += len;
+
+ /* Prepare next loop */
+ *ip += ml;
+ *anchor = *ip;
+
+ return 0;
+}
+
+static int lz4_compresshcctx(struct lz4hc_data *ctx,
+ const char *source,
+ char *dest,
+ int isize)
+{
+ const u8 *ip = (const u8 *)source;
+ const u8 *anchor = ip;
+ const u8 *const iend = ip + isize;
+ const u8 *const mflimit = iend - MFLIMIT;
+ const u8 *const matchlimit = (iend - LASTLITERALS);
+
+ u8 *op = (u8 *)dest;
+
+ int ml, ml2, ml3, ml0;
+ const u8 *ref = NULL;
+ const u8 *start2 = NULL;
+ const u8 *ref2 = NULL;
+ const u8 *start3 = NULL;
+ const u8 *ref3 = NULL;
+ const u8 *start0;
+ const u8 *ref0;
+ int lastrun;
+
+ ip++;
+
+ /* Main Loop */
+ while (ip < mflimit) {
+ ml = lz4hc_insertandfindbestmatch(ctx, ip, matchlimit, (&ref));
+ if (!ml) {
+ ip++;
+ continue;
+ }
+
+ /* saved, in case we would skip too much */
+ start0 = ip;
+ ref0 = ref;
+ ml0 = ml;
+_search2:
+ if (ip+ml < mflimit)
+ ml2 = lz4hc_insertandgetwidermatch(ctx, ip + ml - 2,
+ ip + 1, matchlimit, ml, &ref2, &start2);
+ else
+ ml2 = ml;
+ /* No better match */
+ if (ml2 == ml) {
+ lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+ continue;
+ }
+
+ if (start0 < ip) {
+ /* empirical */
+ if (start2 < ip + ml0) {
+ ip = start0;
+ ref = ref0;
+ ml = ml0;
+ }
+ }
+ /*
+ * Here, start0==ip
+ * First Match too small : removed
+ */
+ if ((start2 - ip) < 3) {
+ ml = ml2;
+ ip = start2;
+ ref = ref2;
+ goto _search2;
+ }
+
+_search3:
+ /*
+ * Currently we have :
+ * ml2 > ml1, and
+ * ip1+3 <= ip2 (usually < ip1+ml1)
+ */
+ if ((start2 - ip) < OPTIMAL_ML) {
+ int correction;
+ int new_ml = ml;
+ if (new_ml > OPTIMAL_ML)
+ new_ml = OPTIMAL_ML;
+ if (ip + new_ml > start2 + ml2 - MINMATCH)
+ new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
+ correction = new_ml - (int)(start2 - ip);
+ if (correction > 0) {
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ }
+ }
+ /*
+ * Now, we have start2 = ip+new_ml,
+ * with new_ml=min(ml, OPTIMAL_ML=18)
+ */
+ if (start2 + ml2 < mflimit)
+ ml3 = lz4hc_insertandgetwidermatch(ctx,
+ start2 + ml2 - 3, start2, matchlimit,
+ ml2, &ref3, &start3);
+ else
+ ml3 = ml2;
+
+ /* No better match : 2 sequences to encode */
+ if (ml3 == ml2) {
+ /* ip & ref are known; Now for ml */
+ if (start2 < ip+ml)
+ ml = (int)(start2 - ip);
+
+ /* Now, encode 2 sequences */
+ lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+ ip = start2;
+ lz4_encodesequence(&ip, &op, &anchor, ml2, ref2);
+ continue;
+ }
+
+ /* Not enough space for match 2 : remove it */
+ if (start3 < ip + ml + 3) {
+ /*
+ * can write Seq1 immediately ==> Seq2 is removed,
+ * so Seq3 becomes Seq1
+ */
+ if (start3 >= (ip + ml)) {
+ if (start2 < ip + ml) {
+ int correction =
+ (int)(ip + ml - start2);
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ if (ml2 < MINMATCH) {
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+ }
+ }
+
+ lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+ ip = start3;
+ ref = ref3;
+ ml = ml3;
+
+ start0 = start2;
+ ref0 = ref2;
+ ml0 = ml2;
+ goto _search2;
+ }
+
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+ goto _search3;
+ }
+
+ /*
+ * OK, now we have 3 ascending matches; let's write at least
+ * the first one ip & ref are known; Now for ml
+ */
+ if (start2 < ip + ml) {
+ if ((start2 - ip) < (int)ML_MASK) {
+ int correction;
+ if (ml > OPTIMAL_ML)
+ ml = OPTIMAL_ML;
+ if (ip + ml > start2 + ml2 - MINMATCH)
+ ml = (int)(start2 - ip) + ml2
+ - MINMATCH;
+ correction = ml - (int)(start2 - ip);
+ if (correction > 0) {
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ }
+ } else
+ ml = (int)(start2 - ip);
+ }
+ lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+
+ ip = start2;
+ ref = ref2;
+ ml = ml2;
+
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+
+ goto _search3;
+ }
+
+ /* Encode Last Literals */
+ lastrun = (int)(iend - anchor);
+ if (lastrun >= (int)RUN_MASK) {
+ *op++ = (RUN_MASK << ML_BITS);
+ lastrun -= RUN_MASK;
+ for (; lastrun > 254 ; lastrun -= 255)
+ *op++ = 255;
+ *op++ = (u8) lastrun;
+ } else
+ *op++ = (lastrun << ML_BITS);
+ memcpy(op, anchor, iend - anchor);
+ op += iend - anchor;
+ /* End */
+ return (int) (((char *)op) - dest);
+}
+
+int lz4hc_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem)
+{
+ int ret = -1;
+ int out_len = 0;
+
+ struct lz4hc_data *hc4 = (struct lz4hc_data *)wrkmem;
+ lz4hc_init(hc4, (const u8 *)src);
+ out_len = lz4_compresshcctx((struct lz4hc_data *)hc4, (const u8 *)src,
+ (char *)dst, (int)src_len);
+
+ if (out_len < 0)
+ goto exit;
+
+ *dst_len = out_len;
+ return 0;
+
+exit:
+ return ret;
+}
+EXPORT_SYMBOL(lz4hc_compress);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("LZ4HC compressor");
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
index e764116..f0f7d7c 100644
--- a/lib/lzo/Makefile
+++ b/lib/lzo/Makefile
@@ -1,5 +1,5 @@
lzo_compress-objs := lzo1x_compress.o
-lzo_decompress-objs := lzo1x_decompress.o
+lzo_decompress-objs := lzo1x_decompress_safe.o
obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
index a604099..236eb21 100644
--- a/lib/lzo/lzo1x_compress.c
+++ b/lib/lzo/lzo1x_compress.c
@@ -1,194 +1,243 @@
/*
- * LZO1X Compressor from MiniLZO
+ * LZO1X Compressor from LZO
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/lzo.h>
#include <asm/unaligned.h>
+#include <linux/lzo.h>
#include "lzodefs.h"
static noinline size_t
-_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len, void *wrkmem)
+lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ size_t ti, void *wrkmem)
{
+ const unsigned char *ip;
+ unsigned char *op;
const unsigned char * const in_end = in + in_len;
- const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
- const unsigned char ** const dict = wrkmem;
- const unsigned char *ip = in, *ii = ip;
- const unsigned char *end, *m, *m_pos;
- size_t m_off, m_len, dindex;
- unsigned char *op = out;
+ const unsigned char * const ip_end = in + in_len - 20;
+ const unsigned char *ii;
+ lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
- ip += 4;
+ op = out;
+ ip = in;
+ ii = ip;
+ ip += ti < 4 ? 4 - ti : 0;
for (;;) {
- dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
- m_pos = dict[dindex];
-
- if (m_pos < in)
- goto literal;
-
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
- goto literal;
-
- m_off = ip - m_pos;
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
- goto try_match;
-
- dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
- m_pos = dict[dindex];
-
- if (m_pos < in)
- goto literal;
-
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
- goto literal;
-
- m_off = ip - m_pos;
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
- goto try_match;
-
- goto literal;
-
-try_match:
- if (get_unaligned((const unsigned short *)m_pos)
- == get_unaligned((const unsigned short *)ip)) {
- if (likely(m_pos[2] == ip[2]))
- goto match;
- }
-
+ const unsigned char *m_pos;
+ size_t t, m_len, m_off;
+ u32 dv;
literal:
- dict[dindex] = ip;
- ++ip;
+ ip += 1 + ((ip - ii) >> 5);
+next:
if (unlikely(ip >= ip_end))
break;
- continue;
-
-match:
- dict[dindex] = ip;
- if (ip != ii) {
- size_t t = ip - ii;
+ dv = get_unaligned_le32(ip);
+ t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
+ m_pos = in + dict[t];
+ dict[t] = (lzo_dict_t) (ip - in);
+ if (unlikely(dv != get_unaligned_le32(m_pos)))
+ goto literal;
+ ii -= ti;
+ ti = 0;
+ t = ip - ii;
+ if (t != 0) {
if (t <= 3) {
op[-2] |= t;
- } else if (t <= 18) {
+ COPY4(op, ii);
+ op += t;
+ } else if (t <= 16) {
*op++ = (t - 3);
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += t;
} else {
- size_t tt = t - 18;
-
- *op++ = 0;
- while (tt > 255) {
- tt -= 255;
+ if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
*op++ = 0;
+ while (unlikely(tt > 255)) {
+ tt -= 255;
+ *op++ = 0;
+ }
+ *op++ = tt;
}
- *op++ = tt;
+ do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
+ *op++ = *ii++;
+ } while (--t > 0);
}
- do {
- *op++ = *ii++;
- } while (--t > 0);
}
- ip += 3;
- if (m_pos[3] != *ip++ || m_pos[4] != *ip++
- || m_pos[5] != *ip++ || m_pos[6] != *ip++
- || m_pos[7] != *ip++ || m_pos[8] != *ip++) {
- --ip;
- m_len = ip - ii;
+ m_len = 4;
+ {
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
+ u64 v;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 8;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctzll(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clzll(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
+ u32 v;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (v != 0)
+ break;
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctz(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clz(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#else
+ if (unlikely(ip[m_len] == m_pos[m_len])) {
+ do {
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (ip[m_len] == m_pos[m_len]);
+ }
+#endif
+ }
+m_len_done:
- if (m_off <= M2_MAX_OFFSET) {
- m_off -= 1;
- *op++ = (((m_len - 1) << 5)
- | ((m_off & 7) << 2));
- *op++ = (m_off >> 3);
- } else if (m_off <= M3_MAX_OFFSET) {
- m_off -= 1;
+ m_off = ip - m_pos;
+ ip += m_len;
+ ii = ip;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
+ m_off -= 1;
+ *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = (m_off >> 3);
+ } else if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
*op++ = (M3_MARKER | (m_len - 2));
- goto m3_m4_offset;
- } else {
- m_off -= 0x4000;
-
- *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
- | (m_len - 2));
- goto m3_m4_offset;
+ else {
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ *op++ = (m_len);
}
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
} else {
- end = in_end;
- m = m_pos + M2_MAX_LEN + 1;
-
- while (ip < end && *m == *ip) {
- m++;
- ip++;
- }
- m_len = ip - ii;
-
- if (m_off <= M3_MAX_OFFSET) {
- m_off -= 1;
- if (m_len <= 33) {
- *op++ = (M3_MARKER | (m_len - 2));
- } else {
- m_len -= 33;
- *op++ = M3_MARKER | 0;
- goto m3_m4_len;
- }
- } else {
- m_off -= 0x4000;
- if (m_len <= M4_MAX_LEN) {
- *op++ = (M4_MARKER
- | ((m_off & 0x4000) >> 11)
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8)
| (m_len - 2));
- } else {
- m_len -= M4_MAX_LEN;
- *op++ = (M4_MARKER
- | ((m_off & 0x4000) >> 11));
-m3_m4_len:
- while (m_len > 255) {
- m_len -= 255;
- *op++ = 0;
- }
-
- *op++ = (m_len);
+ else {
+ m_len -= M4_MAX_LEN;
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8));
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
}
+ *op++ = (m_len);
}
-m3_m4_offset:
- *op++ = ((m_off & 63) << 2);
+ *op++ = (m_off << 2);
*op++ = (m_off >> 6);
}
-
- ii = ip;
- if (unlikely(ip >= ip_end))
- break;
+ goto next;
}
-
*out_len = op - out;
- return in_end - ii;
+ return in_end - (ii - ti);
}
-int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
- size_t *out_len, void *wrkmem)
+int lzo1x_1_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem)
{
- const unsigned char *ii;
+ const unsigned char *ip = in;
unsigned char *op = out;
- size_t t;
+ size_t l = in_len;
+ size_t t = 0;
- if (unlikely(in_len <= M2_MAX_LEN + 5)) {
- t = in_len;
- } else {
- t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+ while (l > 20) {
+ size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
+ uintptr_t ll_end = (uintptr_t) ip + ll;
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end)
+ break;
+ BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
+ memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
+ t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
+ ip += ll;
op += *out_len;
+ l -= ll;
}
+ t += l;
if (t > 0) {
- ii = in + in_len - t;
+ const unsigned char *ii = in + in_len - t;
if (op == out && t <= 238) {
*op++ = (17 + t);
@@ -198,16 +247,21 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
*op++ = (t - 3);
} else {
size_t tt = t - 18;
-
*op++ = 0;
while (tt > 255) {
tt -= 255;
*op++ = 0;
}
-
*op++ = tt;
}
- do {
+ if (t >= 16) do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
*op++ = *ii++;
} while (--t > 0);
}
@@ -223,4 +277,3 @@ EXPORT_SYMBOL_GPL(lzo1x_1_compress);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO1X-1 Compressor");
-
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
deleted file mode 100644
index f2fd098..0000000
--- a/lib/lzo/lzo1x_decompress.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * LZO1X Decompressor from MiniLZO
- *
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
- *
- * The full LZO package can be found at:
- * http://www.oberhumer.com/opensource/lzo/
- *
- * Changed for kernel use by:
- * Nitin Gupta <nitingupta910@gmail.com>
- * Richard Purdie <rpurdie@openedhand.com>
- */
-
-#ifndef STATIC
-#include <linux/module.h>
-#include <linux/kernel.h>
-#endif
-
-#include <asm/unaligned.h>
-#include <linux/lzo.h>
-#include "lzodefs.h"
-
-#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
-#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
-#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
-
-#define COPY4(dst, src) \
- put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
-
-int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len)
-{
- const unsigned char * const ip_end = in + in_len;
- unsigned char * const op_end = out + *out_len;
- const unsigned char *ip = in, *m_pos;
- unsigned char *op = out;
- size_t t;
-
- *out_len = 0;
-
- if (*ip > 17) {
- t = *ip++ - 17;
- if (t < 4)
- goto match_next;
- if (HAVE_OP(t, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 1, ip_end, ip))
- goto input_overrun;
- do {
- *op++ = *ip++;
- } while (--t > 0);
- goto first_literal_run;
- }
-
- while ((ip < ip_end)) {
- t = *ip++;
- if (t >= 16)
- goto match;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 15 + *ip++;
- }
- if (HAVE_OP(t + 3, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 4, ip_end, ip))
- goto input_overrun;
-
- COPY4(op, ip);
- op += 4;
- ip += 4;
- if (--t > 0) {
- if (t >= 4) {
- do {
- COPY4(op, ip);
- op += 4;
- ip += 4;
- t -= 4;
- } while (t >= 4);
- if (t > 0) {
- do {
- *op++ = *ip++;
- } while (--t > 0);
- }
- } else {
- do {
- *op++ = *ip++;
- } while (--t > 0);
- }
- }
-
-first_literal_run:
- t = *ip++;
- if (t >= 16)
- goto match;
- m_pos = op - (1 + M2_MAX_OFFSET);
- m_pos -= t >> 2;
- m_pos -= *ip++ << 2;
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
-
- if (HAVE_OP(3, op_end, op))
- goto output_overrun;
- *op++ = *m_pos++;
- *op++ = *m_pos++;
- *op++ = *m_pos;
-
- goto match_done;
-
- do {
-match:
- if (t >= 64) {
- m_pos = op - 1;
- m_pos -= (t >> 2) & 7;
- m_pos -= *ip++ << 3;
- t = (t >> 5) - 1;
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(t + 3 - 1, op_end, op))
- goto output_overrun;
- goto copy_match;
- } else if (t >= 32) {
- t &= 31;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 31 + *ip++;
- }
- m_pos = op - 1;
- m_pos -= get_unaligned_le16(ip) >> 2;
- ip += 2;
- } else if (t >= 16) {
- m_pos = op;
- m_pos -= (t & 8) << 11;
-
- t &= 7;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 7 + *ip++;
- }
- m_pos -= get_unaligned_le16(ip) >> 2;
- ip += 2;
- if (m_pos == op)
- goto eof_found;
- m_pos -= 0x4000;
- } else {
- m_pos = op - 1;
- m_pos -= t >> 2;
- m_pos -= *ip++ << 2;
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(2, op_end, op))
- goto output_overrun;
-
- *op++ = *m_pos++;
- *op++ = *m_pos;
- goto match_done;
- }
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(t + 3 - 1, op_end, op))
- goto output_overrun;
-
- if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
- COPY4(op, m_pos);
- op += 4;
- m_pos += 4;
- t -= 4 - (3 - 1);
- do {
- COPY4(op, m_pos);
- op += 4;
- m_pos += 4;
- t -= 4;
- } while (t >= 4);
- if (t > 0)
- do {
- *op++ = *m_pos++;
- } while (--t > 0);
- } else {
-copy_match:
- *op++ = *m_pos++;
- *op++ = *m_pos++;
- do {
- *op++ = *m_pos++;
- } while (--t > 0);
- }
-match_done:
- t = ip[-2] & 3;
- if (t == 0)
- break;
-match_next:
- if (HAVE_OP(t, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 1, ip_end, ip))
- goto input_overrun;
-
- *op++ = *ip++;
- if (t > 1) {
- *op++ = *ip++;
- if (t > 2)
- *op++ = *ip++;
- }
-
- t = *ip++;
- } while (ip < ip_end);
- }
-
- *out_len = op - out;
- return LZO_E_EOF_NOT_FOUND;
-
-eof_found:
- *out_len = op - out;
- return (ip == ip_end ? LZO_E_OK :
- (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
-input_overrun:
- *out_len = op - out;
- return LZO_E_INPUT_OVERRUN;
-
-output_overrun:
- *out_len = op - out;
- return LZO_E_OUTPUT_OVERRUN;
-
-lookbehind_overrun:
- *out_len = op - out;
- return LZO_E_LOOKBEHIND_OVERRUN;
-}
-#ifndef STATIC
-EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("LZO1X Decompressor");
-
-#endif
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
new file mode 100644
index 0000000..a5f3d0e
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -0,0 +1,261 @@
+/*
+ * LZO1X Decompressor from LZO
+ *
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for Linux kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#ifndef STATIC
+#include <linux/module.h>
+#include <linux/kernel.h>
+#endif
+#include <asm/unaligned.h>
+#include <linux/lzo.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(t, x) \
+ (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \
+ (((t + x) >= t) && ((t + x) >= x)))
+
+#define HAVE_OP(t, x) \
+ (((size_t)(op_end - op) >= (size_t)(t + x)) && \
+ (((t + x) >= t) && ((t + x) >= x)))
+
+#define NEED_IP(t, x) \
+ do { \
+ if (!HAVE_IP(t, x)) \
+ goto input_overrun; \
+ } while (0)
+
+#define NEED_OP(t, x) \
+ do { \
+ if (!HAVE_OP(t, x)) \
+ goto output_overrun; \
+ } while (0)
+
+#define TEST_LB(m_pos) \
+ do { \
+ if ((m_pos) < out) \
+ goto lookbehind_overrun; \
+ } while (0)
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ unsigned char *op;
+ const unsigned char *ip;
+ size_t t, next;
+ size_t state = 0;
+ const unsigned char *m_pos;
+ const unsigned char * const ip_end = in + in_len;
+ unsigned char * const op_end = out + *out_len;
+
+ op = out;
+ ip = in;
+
+ if (unlikely(in_len < 3))
+ goto input_overrun;
+ if (*ip > 17) {
+ t = *ip++ - 17;
+ if (t < 4) {
+ next = t;
+ goto match_next;
+ }
+ goto copy_literal_run;
+ }
+
+ for (;;) {
+ t = *ip++;
+ if (t < 16) {
+ if (likely(state == 0)) {
+ if (unlikely(t == 0)) {
+ while (unlikely(*ip == 0)) {
+ t += 255;
+ ip++;
+ NEED_IP(1, 0);
+ }
+ t += 15 + *ip++;
+ }
+ t += 3;
+copy_literal_run:
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) {
+ const unsigned char *ie = ip + t;
+ unsigned char *oe = op + t;
+ do {
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+# if !defined(__arm__)
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+# endif
+ } while (ip < ie);
+ ip = ie;
+ op = oe;
+ } else
+#endif
+ {
+ NEED_OP(t, 0);
+ NEED_IP(t, 3);
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ state = 4;
+ continue;
+ } else if (state != 4) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ TEST_LB(m_pos);
+ NEED_OP(2, 0);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ goto match_next;
+ } else {
+ next = t & 3;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ t = 3;
+ }
+ } else if (t >= 64) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1 + (3 - 1);
+ } else if (t >= 32) {
+ t = (t & 31) + (3 - 1);
+ if (unlikely(t == 2)) {
+ while (unlikely(*ip == 0)) {
+ t += 255;
+ ip++;
+ NEED_IP(1, 0);
+ }
+ t += 31 + *ip++;
+ NEED_IP(2, 0);
+ }
+ m_pos = op - 1;
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ } else {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+ t = (t & 7) + (3 - 1);
+ if (unlikely(t == 2)) {
+ while (unlikely(*ip == 0)) {
+ t += 255;
+ ip++;
+ NEED_IP(1, 0);
+ }
+ t += 7 + *ip++;
+ NEED_IP(2, 0);
+ }
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ }
+ TEST_LB(m_pos);
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (op - m_pos >= 8) {
+ unsigned char *oe = op + t;
+ if (likely(HAVE_OP(t, 15))) {
+ do {
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+# if !defined(__arm__)
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+# endif
+ } while (op < oe);
+ op = oe;
+ if (HAVE_IP(6, 0)) {
+ state = next;
+ COPY4(op, ip);
+ op += next;
+ ip += next;
+ continue;
+ }
+ } else {
+ NEED_OP(t, 0);
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
+ } else
+#endif
+ {
+ unsigned char *oe = op + t;
+ NEED_OP(t, 0);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ m_pos += 2;
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
+match_next:
+ state = next;
+ t = next;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) {
+ COPY4(op, ip);
+ op += t;
+ ip += t;
+ } else
+#endif
+ {
+ NEED_IP(t, 3);
+ NEED_OP(t, 0);
+ while (t > 0) {
+ *op++ = *ip++;
+ t--;
+ }
+ }
+ }
+
+eof_found:
+ *out_len = op - out;
+ return (t != 3 ? LZO_E_ERROR :
+ ip == ip_end ? LZO_E_OK :
+ ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
+
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+}
+#ifndef STATIC
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X Decompressor");
+
+#endif
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index b6d482c..db756cc 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -1,19 +1,43 @@
/*
* lzodefs.h -- architecture, OS and compiler specific defines
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
-#define LZO_VERSION 0x2020
-#define LZO_VERSION_STRING "2.02"
-#define LZO_VERSION_DATE "Oct 17 2005"
+
+#if 1 && defined(__arm__) && ((__LINUX_ARM_ARCH__ >= 6) || defined(__ARM_FEATURE_UNALIGNED))
+#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
+#define COPY4(dst, src) \
+ * (u32 *) (void *) (dst) = * (const u32 *) (const void *) (src)
+#else
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#endif
+#if defined(__x86_64__)
+#define COPY8(dst, src) \
+ put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
+#else
+#define COPY8(dst, src) \
+ COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
+#endif
+
+#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+#error "conflicting endian definitions"
+#elif defined(__x86_64__)
+#define LZO_USE_CTZ64 1
+#define LZO_USE_CTZ32 1
+#elif defined(__i386__) || defined(__powerpc__)
+#define LZO_USE_CTZ32 1
+#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
+#define LZO_USE_CTZ32 1
+#endif
#define M1_MAX_OFFSET 0x0400
#define M2_MAX_OFFSET 0x0800
@@ -34,10 +58,8 @@
#define M3_MARKER 32
#define M4_MARKER 16
-#define D_BITS 14
-#define D_MASK ((1u << D_BITS) - 1)
+#define lzo_dict_t unsigned short
+#define D_BITS 13
+#define D_SIZE (1u << D_BITS)
+#define D_MASK (D_SIZE - 1)
#define D_HIGH ((D_MASK >> 1) + 1)
-
-#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
- << (s1)) ^ (p)[0])
-#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
diff --git a/mm/Kconfig b/mm/Kconfig
index dcecf12..6c733a7 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -371,6 +371,31 @@ config CLEANCACHE
If unsure, say Y to enable cleancache
+config ZSMALLOC
+ bool "Memory allocator for compressed pages"
+ depends on MMU
+ default n
+ help
+ zsmalloc is a slab-based memory allocator designed to store
+ compressed RAM pages. zsmalloc uses virtual memory mapping
+ in order to reduce fragmentation. However, this results in a
+ non-standard allocator interface where a handle, not a pointer, is
+ returned by an alloc(). This handle must be mapped in order to
+ access the allocated space.
+
+config PGTABLE_MAPPING
+ bool "Use page table mapping to access object in zsmalloc"
+ depends on ZSMALLOC
+ help
+ By default, zsmalloc uses a copy-based object mapping method to
+ access allocations that span two pages. However, if a particular
+ architecture (ex, ARM) performs VM mapping faster than copying,
+ then you should select this. This causes zsmalloc to use page table
+ mapping rather than copying for object mapping.
+
+ You can check speed with zsmalloc benchmark[1].
+ [1] https://github.com/spartacus06/zsmalloc
+
config CMA
bool "Contiguous Memory Allocator framework"
# Currently there is only one allocator so force it on
diff --git a/mm/Makefile b/mm/Makefile
index 9b994ce..47ebf93 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -78,5 +78,7 @@ obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o
obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
obj-$(CONFIG_CLEANCACHE) += cleancache.o
+obj-$(CONFIG_ZSMALLOC) += zsmalloc.o
+
obj-$(CONFIG_CMA) += cma.o
obj-$(CONFIG_CMA_BEST_FIT) += cma-best-fit.o
diff --git a/mm/cleancache.c b/mm/cleancache.c
index bcaae4c..83a8241 100644
--- a/mm/cleancache.c
+++ b/mm/cleancache.c
@@ -160,7 +160,8 @@ void __cleancache_flush_page(struct address_space *mapping, struct page *page)
if (pool_id >= 0) {
VM_BUG_ON(!PageLocked(page));
if (cleancache_get_key(mapping->host, &key) >= 0) {
- (*cleancache_ops.flush_page)(pool_id, key, page->index);
+ (*cleancache_ops.invalidate_page)(pool_id,
+ key, page->index);
cleancache_flushes++;
}
}
@@ -178,7 +179,7 @@ void __cleancache_flush_inode(struct address_space *mapping)
struct cleancache_filekey key = { .u.key = { 0 } };
if (pool_id >= 0 && cleancache_get_key(mapping->host, &key) >= 0)
- (*cleancache_ops.flush_inode)(pool_id, key);
+ (*cleancache_ops.invalidate_inode)(pool_id, key);
}
EXPORT_SYMBOL(__cleancache_flush_inode);
@@ -192,7 +193,7 @@ void __cleancache_flush_fs(struct super_block *sb)
if (sb->cleancache_poolid >= 0) {
int old_poolid = sb->cleancache_poolid;
sb->cleancache_poolid = -1;
- (*cleancache_ops.flush_fs)(old_poolid);
+ (*cleancache_ops.invalidate_fs)(old_poolid);
}
}
EXPORT_SYMBOL(__cleancache_flush_fs);
diff --git a/mm/madvise.c b/mm/madvise.c
index deabe5f6..5a273af 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -87,7 +87,8 @@ static long madvise_behavior(struct vm_area_struct * vma,
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
*prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma,
- vma->vm_file, pgoff, vma_policy(vma));
+ vma->vm_file, pgoff, vma_policy(vma),
+ vma_get_anon_name(vma));
if (*prev) {
vma = *prev;
goto success;
diff --git a/mm/memory.c b/mm/memory.c
index 5331e67..29c8112 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1436,6 +1436,16 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
}
EXPORT_SYMBOL_GPL(zap_vma_ptes);
+/*
+ * FOLL_FORCE can write to even unwritable pte's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
+{
+ return pte_write(pte) ||
+ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
+}
+
/**
* follow_page - look up a page descriptor from a user-virtual address
* @vma: vm_area_struct mapping @address
@@ -1518,7 +1528,7 @@ split_fallthrough:
pte = *ptep;
if (!pte_present(pte))
goto no_page;
- if ((flags & FOLL_WRITE) && !pte_write(pte))
+ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags))
goto unlock;
page = vm_normal_page(vma, address, pte);
@@ -1832,7 +1842,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
*/
if ((ret & VM_FAULT_WRITE) &&
!(vma->vm_flags & VM_WRITE))
- foll_flags &= ~FOLL_WRITE;
+ foll_flags |= FOLL_COW;
cond_resched();
}
@@ -3140,7 +3150,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
mem_cgroup_commit_charge_swapin(page, ptr);
swap_free(entry);
- if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
+ if ((PageSwapCache(page) && vm_swap_full(page_swap_info(page))) ||
+ (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
try_to_free_swap(page);
unlock_page(page);
if (swapcache) {
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 7065fb3..7c8caa9 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -664,8 +664,9 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
vmend = min(end, vma->vm_end);
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
- prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags,
- vma->anon_vma, vma->vm_file, pgoff, new_pol);
+ prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags,
+ vma->anon_vma, vma->vm_file, pgoff,
+ new_pol, vma_get_anon_name(name));
if (prev) {
vma = prev;
next = vma->vm_next;
diff --git a/mm/mlock.c b/mm/mlock.c
index b41b3b7..734fd7f 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -321,7 +321,8 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
*prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma,
- vma->vm_file, pgoff, vma_policy(vma));
+ vma->vm_file, pgoff, vma_policy(vma),
+ vma_get_anon_name(vma));
if (*prev) {
vma = *prev;
goto success;
diff --git a/mm/mmap.c b/mm/mmap.c
index d1cf520..96f124e 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -656,7 +656,8 @@ again: remove_next = 1 + (end > next->vm_end);
* per-vma resources, so we don't attempt to merge those.
*/
static inline int is_mergeable_vma(struct vm_area_struct *vma,
- struct file *file, unsigned long vm_flags)
+ struct file *file, unsigned long vm_flags,
+ const char __user *anon_name)
{
/* VM_CAN_NONLINEAR may get set later by f_op->mmap() */
if ((vma->vm_flags ^ vm_flags) & ~VM_CAN_NONLINEAR)
@@ -665,6 +666,8 @@ static inline int is_mergeable_vma(struct vm_area_struct *vma,
return 0;
if (vma->vm_ops && vma->vm_ops->close)
return 0;
+ if (vma_get_anon_name(vma) != anon_name)
+ return 0;
return 1;
}
@@ -695,9 +698,10 @@ static inline int is_mergeable_anon_vma(struct anon_vma *anon_vma1,
*/
static int
can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
- struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
+ struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff,
+ const char __user *anon_name)
{
- if (is_mergeable_vma(vma, file, vm_flags) &&
+ if (is_mergeable_vma(vma, file, vm_flags, anon_name) &&
is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
if (vma->vm_pgoff == vm_pgoff)
return 1;
@@ -714,9 +718,10 @@ can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
*/
static int
can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
- struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
+ struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff,
+ const char __user *anon_name)
{
- if (is_mergeable_vma(vma, file, vm_flags) &&
+ if (is_mergeable_vma(vma, file, vm_flags, anon_name) &&
is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
pgoff_t vm_pglen;
vm_pglen = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
@@ -727,9 +732,9 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
}
/*
- * Given a mapping request (addr,end,vm_flags,file,pgoff), figure out
- * whether that can be merged with its predecessor or its successor.
- * Or both (it neatly fills a hole).
+ * Given a mapping request (addr,end,vm_flags,file,pgoff,anon_name),
+ * figure out whether that can be merged with its predecessor or its
+ * successor. Or both (it neatly fills a hole).
*
* In most cases - when called for mmap, brk or mremap - [addr,end) is
* certain not to be mapped by the time vma_merge is called; but when
@@ -759,7 +764,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
struct vm_area_struct *prev, unsigned long addr,
unsigned long end, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file,
- pgoff_t pgoff, struct mempolicy *policy)
+ pgoff_t pgoff, struct mempolicy *policy,
+ const char __user *anon_name)
{
pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
struct vm_area_struct *area, *next;
@@ -785,15 +791,15 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
*/
if (prev && prev->vm_end == addr &&
mpol_equal(vma_policy(prev), policy) &&
- can_vma_merge_after(prev, vm_flags,
- anon_vma, file, pgoff)) {
+ can_vma_merge_after(prev, vm_flags, anon_vma,
+ file, pgoff, anon_name)) {
/*
* OK, it can. Can we now merge in the successor as well?
*/
if (next && end == next->vm_start &&
mpol_equal(policy, vma_policy(next)) &&
- can_vma_merge_before(next, vm_flags,
- anon_vma, file, pgoff+pglen) &&
+ can_vma_merge_before(next, vm_flags, anon_vma,
+ file, pgoff+pglen, anon_name) &&
is_mergeable_anon_vma(prev->anon_vma,
next->anon_vma, NULL)) {
/* cases 1, 6 */
@@ -813,8 +819,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
*/
if (next && end == next->vm_start &&
mpol_equal(policy, vma_policy(next)) &&
- can_vma_merge_before(next, vm_flags,
- anon_vma, file, pgoff+pglen)) {
+ can_vma_merge_before(next, vm_flags, anon_vma,
+ file, pgoff+pglen, anon_name)) {
if (prev && addr < prev->vm_end) /* case 4 */
err = vma_adjust(prev, prev->vm_start,
addr, prev->vm_pgoff, NULL);
@@ -1251,7 +1257,8 @@ munmap_back:
/*
* Can we just expand an old mapping?
*/
- vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, NULL);
+ vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff,
+ NULL, NULL);
if (vma)
goto out;
@@ -2202,7 +2209,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
/* Can we just expand an old private anonymous mapping? */
vma = vma_merge(mm, prev, addr, addr + len, flags,
- NULL, NULL, pgoff, NULL);
+ NULL, NULL, pgoff, NULL, NULL);
if (vma)
goto out;
@@ -2340,7 +2347,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
- vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma));
+ vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
+ vma_get_anon_name(vma));
if (new_vma) {
/*
* Source vma may have been merged into new_vma
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 5a688a2..5f168eb 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -179,7 +179,8 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
*/
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
*pprev = vma_merge(mm, *pprev, start, end, newflags,
- vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma));
+ vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
+ vma_get_anon_name(vma));
if (*pprev) {
vma = *pprev;
goto success;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 7c72487..678cf2b 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -38,6 +38,28 @@ int sysctl_oom_kill_allocating_task;
int sysctl_oom_dump_tasks = 1;
static DEFINE_SPINLOCK(zone_scan_lock);
+/*
+ * compare_swap_oom_score_adj() - compare and swap current's oom_score_adj
+ * @old_val: old oom_score_adj for compare
+ * @new_val: new oom_score_adj for swap
+ *
+ * Sets the oom_score_adj value for current to @new_val iff its present value is
+ * @old_val. Usually used to reinstate a previous value to prevent racing with
+ * userspacing tuning the value in the interim.
+ */
+void compare_swap_oom_score_adj(int old_val, int new_val)
+{
+ struct sighand_struct *sighand = current->sighand;
+
+ spin_lock_irq(&sighand->siglock);
+ if (current->signal->oom_score_adj == old_val) {
+ current->signal->oom_score_adj = new_val;
+ delete_from_adj_tree(current);
+ add_2_adj_tree(current);
+ }
+ spin_unlock_irq(&sighand->siglock);
+}
+
/**
* test_set_oom_score_adj() - set current's oom_score_adj and return old value
* @new_val: new oom_score_adj value
diff --git a/mm/page_io.c b/mm/page_io.c
index dc76b4d..f57da45 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -18,6 +18,8 @@
#include <linux/bio.h>
#include <linux/swapops.h>
#include <linux/writeback.h>
+#include <linux/aio.h>
+#include <linux/blkdev.h>
#include <asm/pgtable.h>
static struct bio *get_swap_bio(gfp_t gfp_flags,
@@ -78,9 +80,49 @@ void end_swap_bio_read(struct bio *bio, int err)
imajor(bio->bi_bdev->bd_inode),
iminor(bio->bi_bdev->bd_inode),
(unsigned long long)bio->bi_sector);
- } else {
- SetPageUptodate(page);
+ goto out;
+ }
+
+ SetPageUptodate(page);
+
+ /*
+ * There is no guarantee that the page is in swap cache - the software
+ * suspend code (at least) uses end_swap_bio_read() against a non-
+ * swapcache page. So we must check PG_swapcache before proceeding with
+ * this optimization.
+ */
+ if (likely(PageSwapCache(page))) {
+ /*
+ * The swap subsystem performs lazy swap slot freeing,
+ * expecting that the page will be swapped out again.
+ * So we can avoid an unnecessary write if the page
+ * isn't redirtied.
+ * This is good for real swap storage because we can
+ * reduce unnecessary I/O and enhance wear-leveling
+ * if an SSD is used as the as swap device.
+ * But if in-memory swap device (eg zram) is used,
+ * this causes a duplicated copy between uncompressed
+ * data in VM-owned memory and compressed data in
+ * zram-owned memory. So let's free zram-owned memory
+ * and make the VM-owned decompressed page *dirty*,
+ * so the page should be swapped out somewhere again if
+ * we again wish to reclaim it.
+ */
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+ if (disk->fops->swap_slot_free_notify) {
+ swp_entry_t entry;
+ unsigned long offset;
+
+ entry.val = page_private(page);
+ offset = swp_offset(entry);
+
+ SetPageDirty(page);
+ disk->fops->swap_slot_free_notify(bio->bi_bdev,
+ offset);
+ }
}
+
+out:
unlock_page(page);
bio_put(bio);
}
diff --git a/mm/shmem.c b/mm/shmem.c
index a858b67..bcfa97d 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1060,17 +1060,8 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
info = SHMEM_I(inode);
if (info->flags & VM_LOCKED)
goto redirty;
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- /*
- * Modification for compcache
- * shmem_writepage can be reason of kernel panic when using swap.
- * This modification prevent using swap by shmem.
- */
- goto redirty;
-#else
if (!total_swap_pages)
goto redirty;
-#endif
/*
* shmem_backing_dev_info's capabilities prevent regular writeback or
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 3e5a3a7..4add436 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -69,6 +69,26 @@ static inline unsigned char swap_count(unsigned char ent)
return ent & ~SWAP_HAS_CACHE; /* may include SWAP_HAS_CONT flag */
}
+bool is_swap_fast(swp_entry_t entry)
+{
+ struct swap_info_struct *p;
+ unsigned long type;
+
+ if (non_swap_entry(entry))
+ return false;
+
+ type = swp_type(entry);
+ if (type >= nr_swapfiles)
+ return false;
+
+ p = swap_info[type];
+
+ if (p->flags & SWP_FAST)
+ return true;
+
+ return false;
+}
+
/* returns 1 if swap entry is freed */
static int
__try_to_reclaim_swap(struct swap_info_struct *si, unsigned long offset)
@@ -289,7 +309,7 @@ checks:
scan_base = offset = si->lowest_bit;
/* reuse swap entry of cache-only swap if not busy. */
- if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
+ if (vm_swap_full(si) && si->swap_map[offset] == SWAP_HAS_CACHE) {
int swap_was_freed;
spin_unlock(&swap_lock);
swap_was_freed = __try_to_reclaim_swap(si, offset);
@@ -378,7 +398,8 @@ scan:
spin_lock(&swap_lock);
goto checks;
}
- if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
+ if (vm_swap_full(si) &&
+ si->swap_map[offset] == SWAP_HAS_CACHE) {
spin_lock(&swap_lock);
goto checks;
}
@@ -393,7 +414,8 @@ scan:
spin_lock(&swap_lock);
goto checks;
}
- if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
+ if (vm_swap_full(si) &&
+ si->swap_map[offset] == SWAP_HAS_CACHE) {
spin_lock(&swap_lock);
goto checks;
}
@@ -708,7 +730,8 @@ int free_swap_and_cache(swp_entry_t entry)
* Also recheck PageSwapCache now page is locked (above).
*/
if (PageSwapCache(page) && !PageWriteback(page) &&
- (!page_mapped(page) || vm_swap_full())) {
+ (!page_mapped(page) ||
+ vm_swap_full(page_swap_info(page)))) {
delete_from_swap_cache(page);
SetPageDirty(page);
}
@@ -2012,159 +2035,6 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p,
return nr_extents;
}
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-int swapon(char *name, int swap_flags)
-{
- struct swap_info_struct *p;
-
- struct file *swap_file = NULL;
- struct address_space *mapping;
- int i;
- int prio;
- int error;
- union swap_header *swap_header;
- int nr_extents;
- sector_t span;
- unsigned long maxpages;
- unsigned char *swap_map = NULL;
- struct page *page = NULL;
- struct inode *inode = NULL;
-
- p = alloc_swap_info();
- if (IS_ERR(p))
- return PTR_ERR(p);
-
- swap_file = filp_open(name, O_RDWR | O_LARGEFILE, 0);
- if (IS_ERR(swap_file)) {
- error = PTR_ERR(swap_file);
- swap_file = NULL;
- printk("zfqin, filp_open failed\n");
- goto bad_swap;
- }
-
- printk("zfqin, filp_open succeeded\n");
- p->swap_file = swap_file;
- mapping = swap_file->f_mapping;
-
- for (i = 0; i < nr_swapfiles; i++) {
- struct swap_info_struct *q = swap_info[i];
-
- if (q == p || !q->swap_file)
- continue;
- if (mapping == q->swap_file->f_mapping) {
- error = -EBUSY;
- goto bad_swap;
- }
- }
-
- inode = mapping->host;
- /* If S_ISREG(inode->i_mode) will do mutex_lock(&inode->i_mutex); */
- error = claim_swapfile(p, inode);
- if (unlikely(error))
- goto bad_swap;
-
- /*
- * Read the swap header.
- */
- if (!mapping->a_ops->readpage) {
- error = -EINVAL;
- goto bad_swap;
- }
- page = read_mapping_page(mapping, 0, swap_file);
- if (IS_ERR(page)) {
- error = PTR_ERR(page);
- goto bad_swap;
- }
- swap_header = kmap(page);
-
- maxpages = read_swap_header(p, swap_header, inode);
- if (unlikely(!maxpages)) {
- error = -EINVAL;
- goto bad_swap;
- }
-
- /* OK, set up the swap map and apply the bad block list */
- swap_map = vzalloc(maxpages);
- if (!swap_map) {
- error = -ENOMEM;
- goto bad_swap;
- }
-
- error = swap_cgroup_swapon(p->type, maxpages);
- if (error)
- goto bad_swap;
-
- nr_extents = setup_swap_map_and_extents(p, swap_header, swap_map,
- maxpages, &span);
- if (unlikely(nr_extents < 0)) {
- error = nr_extents;
- goto bad_swap;
- }
-
- if (p->bdev) {
- if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
- p->flags |= SWP_SOLIDSTATE;
- p->cluster_next = 1 + (random32() % p->highest_bit);
- }
- if (discard_swap(p) == 0 && (swap_flags & SWAP_FLAG_DISCARD))
- p->flags |= SWP_DISCARDABLE;
- }
-
- mutex_lock(&swapon_mutex);
- prio = -1;
- if (swap_flags & SWAP_FLAG_PREFER)
- prio =
- (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
- enable_swap_info(p, prio, swap_map);
-
- printk(KERN_INFO "Adding %uk swap on %s. "
- "Priority:%d extents:%d across:%lluk %s%s\n",
- p->pages << (PAGE_SHIFT - 10), name, p->prio,
- nr_extents, (unsigned long long)span << (PAGE_SHIFT - 10),
- (p->flags & SWP_SOLIDSTATE) ? "SS" : "",
- (p->flags & SWP_DISCARDABLE) ? "D" : "");
-
- mutex_unlock(&swapon_mutex);
- atomic_inc(&proc_poll_event);
- wake_up_interruptible(&proc_poll_wait);
-
- if (S_ISREG(inode->i_mode))
- inode->i_flags |= S_SWAPFILE;
- error = 0;
- goto out;
- bad_swap:
- if (inode && S_ISBLK(inode->i_mode) && p->bdev) {
- set_blocksize(p->bdev, p->old_block_size);
- blkdev_put(p->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
- }
- destroy_swap_extents(p);
- swap_cgroup_swapoff(p->type);
- spin_lock(&swap_lock);
- p->swap_file = NULL;
- p->flags = 0;
- spin_unlock(&swap_lock);
- vfree(swap_map);
- if (swap_file) {
- if (inode && S_ISREG(inode->i_mode)) {
- mutex_unlock(&inode->i_mutex);
- inode = NULL;
- }
- filp_close(swap_file, NULL);
- }
- out:
- if (page && !IS_ERR(page)) {
- kunmap(page);
- page_cache_release(page);
- }
-
- if (inode && S_ISREG(inode->i_mode))
- mutex_unlock(&inode->i_mutex);
- return error;
-}
-
-EXPORT_SYMBOL(swapon);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
{
struct swap_info_struct *p;
@@ -2267,6 +2137,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
}
if (discard_swap(p) == 0 && (swap_flags & SWAP_FLAG_DISCARD))
p->flags |= SWP_DISCARDABLE;
+ if (blk_queue_fast(bdev_get_queue(p->bdev)))
+ p->flags |= SWP_FAST;
}
mutex_lock(&swapon_mutex);
@@ -2449,6 +2321,13 @@ int swapcache_prepare(swp_entry_t entry)
return __swap_duplicate(entry, SWAP_HAS_CACHE);
}
+struct swap_info_struct *page_swap_info(struct page *page)
+{
+ swp_entry_t swap = { .val = page_private(page) };
+ BUG_ON(!PageSwapCache(page));
+ return swap_info[swp_type(swap)];
+}
+
/*
* swap_lock prevents swap_map being freed. Don't grab an extra
* reference on the swaphandle, it doesn't matter if it becomes unused.
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b0d3366..ce6e2e5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -624,6 +624,10 @@ void putback_lru_page(struct page *page)
int was_unevictable = PageUnevictable(page);
VM_BUG_ON(PageLRU(page));
+#ifdef CONFIG_CLEANCACHE
+ if (active)
+ SetPageWasActive(page);
+#endif
redo:
ClearPageUnevictable(page);
@@ -771,9 +775,6 @@ static noinline_for_stack void free_page_list(struct list_head *free_pages)
/*
* shrink_page_list() returns the number of reclaimed pages
*/
-#ifndef CONFIG_ZRAM_FOR_ANDROID
-static
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
unsigned long shrink_page_list(struct list_head *page_list,
struct zone *zone,
struct scan_control *sc)
@@ -989,7 +990,7 @@ cull_mlocked:
activate_locked:
/* Not a candidate for swapping, so reclaim swap space. */
- if (PageSwapCache(page) && vm_swap_full())
+ if (PageSwapCache(page) && vm_swap_full(page_swap_info(page)))
try_to_free_swap(page);
VM_BUG_ON(PageActive(page));
SetPageActive(page);
@@ -1281,9 +1282,6 @@ static unsigned long isolate_pages_global(unsigned long nr,
* clear_active_flags() is a helper for shrink_active_list(), clearing
* any active bits from the pages in the list.
*/
-#ifndef CONFIG_ZRAM_FOR_ANDROID
-static
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
unsigned long clear_active_flags(struct list_head *page_list,
unsigned int *count)
{
@@ -1297,6 +1295,9 @@ unsigned long clear_active_flags(struct list_head *page_list,
if (PageActive(page)) {
lru += LRU_ACTIVE;
ClearPageActive(page);
+#ifdef CONFIG_CLEANCACHE
+ SetPageWasActive(page);
+#endif
nr_active += numpages;
}
if (count)
@@ -1354,40 +1355,6 @@ int isolate_lru_page(struct page *page)
return ret;
}
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-/**
- * isolate_lru_page_compcache - tries to isolate a page for compcache
- * @page: page to isolate from its LRU list
- *
- * Isolates a @page from an LRU list, clears PageLRU,but
- * does not adjusts the vmstat statistic
- * Returns 0 if the page was removed from an LRU list.
- * Returns -EBUSY if the page was not on an LRU list.
- */
-int isolate_lru_page_compcache(struct page *page)
-{
- int ret = -EBUSY;
-
- VM_BUG_ON(!page_count(page));
-
- if (PageLRU(page)) {
- struct zone *zone = page_zone(page);
-
- spin_lock_irq(&zone->lru_lock);
- if (PageLRU(page)) {
- int lru = page_lru(page);
- ret = 0;
- get_page(page);
- ClearPageLRU(page);
- list_del(&page->lru);
- mem_cgroup_del_lru_list(page, lru);
- }
- spin_unlock_irq(&zone->lru_lock);
- }
- return ret;
-}
-#endif
-
/*
* Are there way too many processes in the direct reclaim path already?
*/
@@ -1624,44 +1591,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
return nr_reclaimed;
}
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-unsigned long
-zone_id_shrink_pagelist(struct zone *zone, struct list_head *page_list)
-{
- unsigned long nr_reclaimed = 0;
- unsigned long nr_anon;
- unsigned long nr_file;
-
- struct scan_control sc = {
- .gfp_mask = GFP_USER,
- .may_writepage = 1,
- .nr_to_reclaim = SWAP_CLUSTER_MAX,
- .may_unmap = 1,
- .may_swap = 1,
- .swappiness = vm_swappiness,
- .order = 0,
- .mem_cgroup = NULL,
- .nodemask = NULL,
- };
-
- spin_lock_irq(&zone->lru_lock);
-
- update_isolated_counts(zone, &sc, &nr_anon, &nr_file, page_list);
-
- spin_unlock_irq(&zone->lru_lock);
-
- nr_reclaimed = shrink_page_list(page_list, zone, &sc);
-
- __count_zone_vm_events(PGSTEAL, zone, nr_reclaimed);
-
- putback_lru_pages(zone, &sc, nr_anon, nr_file, page_list);
-
- return nr_reclaimed;
-}
-
-EXPORT_SYMBOL(zone_id_shrink_pagelist);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
/*
* This moves pages from the active list to the inactive list.
*
@@ -1790,6 +1719,9 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
}
ClearPageActive(page); /* we are de-activating */
+#ifdef CONFIG_CLEANCACHE
+ SetPageWasActive(page);
+#endif
list_add(&page->lru, &l_inactive);
}
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
new file mode 100644
index 0000000..5e17643
--- /dev/null
+++ b/mm/zsmalloc.c
@@ -0,0 +1,1148 @@
+/*
+ * zsmalloc memory allocator
+ *
+ * Copyright (C) 2011 Nitin Gupta
+ * Copyright (C) 2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the license that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ */
+
+/*
+ * This allocator is designed for use with zram. Thus, the allocator is
+ * supposed to work well under low memory conditions. In particular, it
+ * never attempts higher order page allocation which is very likely to
+ * fail under memory pressure. On the other hand, if we just use single
+ * (0-order) pages, it would suffer from very high fragmentation --
+ * any object of size PAGE_SIZE/2 or larger would occupy an entire page.
+ * This was one of the major issues with its predecessor (xvmalloc).
+ *
+ * To overcome these issues, zsmalloc allocates a bunch of 0-order pages
+ * and links them together using various 'struct page' fields. These linked
+ * pages act as a single higher-order page i.e. an object can span 0-order
+ * page boundaries. The code refers to these linked pages as a single entity
+ * called zspage.
+ *
+ * For simplicity, zsmalloc can only allocate objects of size up to PAGE_SIZE
+ * since this satisfies the requirements of all its current users (in the
+ * worst case, page is incompressible and is thus stored "as-is" i.e. in
+ * uncompressed form). For allocation requests larger than this size, failure
+ * is returned (see zs_malloc).
+ *
+ * Additionally, zs_malloc() does not return a dereferenceable pointer.
+ * Instead, it returns an opaque handle (unsigned long) which encodes actual
+ * location of the allocated object. The reason for this indirection is that
+ * zsmalloc does not keep zspages permanently mapped since that would cause
+ * issues on 32-bit systems where the VA region for kernel space mappings
+ * is very small. So, before using the allocating memory, the object has to
+ * be mapped using zs_map_object() to get a usable pointer and subsequently
+ * unmapped using zs_unmap_object().
+ *
+ * Following is how we use various fields and flags of underlying
+ * struct page(s) to form a zspage.
+ *
+ * Usage of struct page fields:
+ * page->first_page: points to the first component (0-order) page
+ * page->index (union with page->freelist): offset of the first object
+ * starting in this page. For the first page, this is
+ * always 0, so we use this field (aka freelist) to point
+ * to the first free object in zspage.
+ * page->lru: links together all component pages (except the first page)
+ * of a zspage
+ *
+ * For _first_ page only:
+ *
+ * page->private (union with page->first_page): refers to the
+ * component page after the first page
+ * page->freelist: points to the first free object in zspage.
+ * Free objects are linked together using in-place
+ * metadata.
+ * page->objects: maximum number of objects we can store in this
+ * zspage (class->zspage_order * PAGE_SIZE / class->size)
+ * page->lru: links together first pages of various zspages.
+ * Basically forming list of zspages in a fullness group.
+ * page->mapping: class index and fullness group of the zspage
+ *
+ * Usage of struct page flags:
+ * PG_private: identifies the first component page
+ * PG_private2: identifies the last component page
+ *
+ */
+
+#ifdef CONFIG_ZSMALLOC_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <linux/cpumask.h>
+#include <linux/cpu.h>
+#include <linux/vmalloc.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/zsmalloc.h>
+
+/*
+ * This must be power of 2 and greater than of equal to sizeof(link_free).
+ * These two conditions ensure that any 'struct link_free' itself doesn't
+ * span more than 1 page which avoids complex case of mapping 2 pages simply
+ * to restore link_free pointer values.
+ */
+#define ZS_ALIGN 8
+
+/*
+ * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
+ * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
+ */
+#define ZS_MAX_ZSPAGE_ORDER 2
+#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
+
+/*
+ * Object location (<PFN>, <obj_idx>) is encoded as
+ * as single (unsigned long) handle value.
+ *
+ * Note that object index <obj_idx> is relative to system
+ * page <PFN> it is stored in, so for each sub-page belonging
+ * to a zspage, obj_idx starts with 0.
+ *
+ * This is made more complicated by various memory models and PAE.
+ */
+
+#ifndef MAX_PHYSMEM_BITS
+#ifdef CONFIG_HIGHMEM64G
+#define MAX_PHYSMEM_BITS 36
+#else /* !CONFIG_HIGHMEM64G */
+/*
+ * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just
+ * be PAGE_SHIFT
+ */
+#define MAX_PHYSMEM_BITS BITS_PER_LONG
+#endif
+#endif
+#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT)
+#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS)
+#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1)
+
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
+#define ZS_MIN_ALLOC_SIZE \
+ MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
+#define ZS_MAX_ALLOC_SIZE PAGE_SIZE
+
+/*
+ * On systems with 4K page size, this gives 254 size classes! There is a
+ * trader-off here:
+ * - Large number of size classes is potentially wasteful as free page are
+ * spread across these classes
+ * - Small number of size classes causes large internal fragmentation
+ * - Probably its better to use specific size classes (empirically
+ * determined). NOTE: all those class sizes must be set as multiple of
+ * ZS_ALIGN to make sure link_free itself never has to span 2 pages.
+ *
+ * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
+ * (reason above)
+ */
+#define ZS_SIZE_CLASS_DELTA (PAGE_SIZE >> 8)
+#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \
+ ZS_SIZE_CLASS_DELTA + 1)
+
+/*
+ * We do not maintain any list for completely empty or full pages
+ */
+enum fullness_group {
+ ZS_ALMOST_FULL,
+ ZS_ALMOST_EMPTY,
+ _ZS_NR_FULLNESS_GROUPS,
+
+ ZS_EMPTY,
+ ZS_FULL
+};
+
+/*
+ * We assign a page to ZS_ALMOST_EMPTY fullness group when:
+ * n <= N / f, where
+ * n = number of allocated objects
+ * N = total number of objects zspage can store
+ * f = 1/fullness_threshold_frac
+ *
+ * Similarly, we assign zspage to:
+ * ZS_ALMOST_FULL when n > N / f
+ * ZS_EMPTY when n == 0
+ * ZS_FULL when n == N
+ *
+ * (see: fix_fullness_group())
+ */
+static const int fullness_threshold_frac = 4;
+
+struct size_class {
+ /*
+ * Size of objects stored in this class. Must be multiple
+ * of ZS_ALIGN.
+ */
+ int size;
+ unsigned int index;
+
+ /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
+ int pages_per_zspage;
+
+ spinlock_t lock;
+
+ struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS];
+};
+
+/*
+ * Placed within free objects to form a singly linked list.
+ * For every zspage, first_page->freelist gives head of this list.
+ *
+ * This must be power of 2 and less than or equal to ZS_ALIGN
+ */
+struct link_free {
+ /* Handle of next free chunk (encodes <PFN, obj_idx>) */
+ void *next;
+};
+
+struct zs_pool {
+ struct size_class *size_class[ZS_SIZE_CLASSES];
+
+ gfp_t flags; /* allocation flags used when growing pool */
+ atomic_long_t pages_allocated;
+};
+
+/*
+ * A zspage's class index and fullness group
+ * are encoded in its (first)page->mapping
+ */
+#define CLASS_IDX_BITS 28
+#define FULLNESS_BITS 4
+#define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1)
+#define FULLNESS_MASK ((1 << FULLNESS_BITS) - 1)
+
+struct mapping_area {
+#ifdef CONFIG_PGTABLE_MAPPING
+ struct vm_struct *vm; /* vm area for mapping object that span pages */
+#else
+ char *vm_buf; /* copy buffer for objects that span pages */
+#endif
+ char *vm_addr; /* address of kmap_atomic()'ed pages */
+ enum zs_mapmode vm_mm; /* mapping mode */
+};
+
+/* per-cpu VM mapping areas for zspage accesses that cross page boundaries */
+static DEFINE_PER_CPU(struct mapping_area, zs_map_area);
+
+static int is_first_page(struct page *page)
+{
+ return PagePrivate(page);
+}
+
+static int is_last_page(struct page *page)
+{
+ return PagePrivate2(page);
+}
+
+static void get_zspage_mapping(struct page *page, unsigned int *class_idx,
+ enum fullness_group *fullness)
+{
+ unsigned long m;
+ BUG_ON(!is_first_page(page));
+
+ m = (unsigned long)page->mapping;
+ *fullness = m & FULLNESS_MASK;
+ *class_idx = (m >> FULLNESS_BITS) & CLASS_IDX_MASK;
+}
+
+static void set_zspage_mapping(struct page *page, unsigned int class_idx,
+ enum fullness_group fullness)
+{
+ unsigned long m;
+ BUG_ON(!is_first_page(page));
+
+ m = ((class_idx & CLASS_IDX_MASK) << FULLNESS_BITS) |
+ (fullness & FULLNESS_MASK);
+ page->mapping = (struct address_space *)m;
+}
+
+/*
+ * zsmalloc divides the pool into various size classes where each
+ * class maintains a list of zspages where each zspage is divided
+ * into equal sized chunks. Each allocation falls into one of these
+ * classes depending on its size. This function returns index of the
+ * size class which has chunk size big enough to hold the give size.
+ */
+static int get_size_class_index(int size)
+{
+ int idx = 0;
+
+ if (likely(size > ZS_MIN_ALLOC_SIZE))
+ idx = DIV_ROUND_UP(size - ZS_MIN_ALLOC_SIZE,
+ ZS_SIZE_CLASS_DELTA);
+
+ return idx;
+}
+
+/*
+ * For each size class, zspages are divided into different groups
+ * depending on how "full" they are. This was done so that we could
+ * easily find empty or nearly empty zspages when we try to shrink
+ * the pool (not yet implemented). This function returns fullness
+ * status of the given page.
+ */
+static enum fullness_group get_fullness_group(struct page *page)
+{
+ int inuse, max_objects;
+ enum fullness_group fg;
+ BUG_ON(!is_first_page(page));
+
+ inuse = page->inuse;
+ max_objects = page->objects;
+
+ if (inuse == 0)
+ fg = ZS_EMPTY;
+ else if (inuse == max_objects)
+ fg = ZS_FULL;
+ else if (inuse <= max_objects / fullness_threshold_frac)
+ fg = ZS_ALMOST_EMPTY;
+ else
+ fg = ZS_ALMOST_FULL;
+
+ return fg;
+}
+
+/*
+ * Each size class maintains various freelists and zspages are assigned
+ * to one of these freelists based on the number of live objects they
+ * have. This functions inserts the given zspage into the freelist
+ * identified by <class, fullness_group>.
+ */
+static void insert_zspage(struct page *page, struct size_class *class,
+ enum fullness_group fullness)
+{
+ struct page **head;
+
+ BUG_ON(!is_first_page(page));
+
+ if (fullness >= _ZS_NR_FULLNESS_GROUPS)
+ return;
+
+ head = &class->fullness_list[fullness];
+ if (*head)
+ list_add_tail(&page->lru, &(*head)->lru);
+
+ *head = page;
+}
+
+/*
+ * This function removes the given zspage from the freelist identified
+ * by <class, fullness_group>.
+ */
+static void remove_zspage(struct page *page, struct size_class *class,
+ enum fullness_group fullness)
+{
+ struct page **head;
+
+ BUG_ON(!is_first_page(page));
+
+ if (fullness >= _ZS_NR_FULLNESS_GROUPS)
+ return;
+
+ head = &class->fullness_list[fullness];
+ BUG_ON(!*head);
+ if (list_empty(&(*head)->lru))
+ *head = NULL;
+ else if (*head == page)
+ *head = (struct page *)list_entry((*head)->lru.next,
+ struct page, lru);
+
+ list_del_init(&page->lru);
+}
+
+/*
+ * Each size class maintains zspages in different fullness groups depending
+ * on the number of live objects they contain. When allocating or freeing
+ * objects, the fullness status of the page can change, say, from ALMOST_FULL
+ * to ALMOST_EMPTY when freeing an object. This function checks if such
+ * a status change has occurred for the given page and accordingly moves the
+ * page from the freelist of the old fullness group to that of the new
+ * fullness group.
+ */
+static enum fullness_group fix_fullness_group(struct zs_pool *pool,
+ struct page *page)
+{
+ int class_idx;
+ struct size_class *class;
+ enum fullness_group currfg, newfg;
+
+ BUG_ON(!is_first_page(page));
+
+ get_zspage_mapping(page, &class_idx, &currfg);
+ newfg = get_fullness_group(page);
+ if (newfg == currfg)
+ goto out;
+
+ class = pool->size_class[class_idx];
+ remove_zspage(page, class, currfg);
+ insert_zspage(page, class, newfg);
+ set_zspage_mapping(page, class_idx, newfg);
+
+out:
+ return newfg;
+}
+
+/*
+ * We have to decide on how many pages to link together
+ * to form a zspage for each size class. This is important
+ * to reduce wastage due to unusable space left at end of
+ * each zspage which is given as:
+ * wastage = Zp - Zp % size_class
+ * where Zp = zspage size = k * PAGE_SIZE where k = 1, 2, ...
+ *
+ * For example, for size class of 3/8 * PAGE_SIZE, we should
+ * link together 3 PAGE_SIZE sized pages to form a zspage
+ * since then we can perfectly fit in 8 such objects.
+ */
+static int get_pages_per_zspage(int class_size)
+{
+ int i, max_usedpc = 0;
+ /* zspage order which gives maximum used size per KB */
+ int max_usedpc_order = 1;
+
+ for (i = 1; i <= ZS_MAX_PAGES_PER_ZSPAGE; i++) {
+ int zspage_size;
+ int waste, usedpc;
+
+ zspage_size = i * PAGE_SIZE;
+ waste = zspage_size % class_size;
+ usedpc = (zspage_size - waste) * 100 / zspage_size;
+
+ if (usedpc > max_usedpc) {
+ max_usedpc = usedpc;
+ max_usedpc_order = i;
+ }
+ }
+
+ return max_usedpc_order;
+}
+
+/*
+ * A single 'zspage' is composed of many system pages which are
+ * linked together using fields in struct page. This function finds
+ * the first/head page, given any component page of a zspage.
+ */
+static struct page *get_first_page(struct page *page)
+{
+ if (is_first_page(page))
+ return page;
+ else
+ return page->first_page;
+}
+
+static struct page *get_next_page(struct page *page)
+{
+ struct page *next;
+
+ if (is_last_page(page))
+ next = NULL;
+ else if (is_first_page(page))
+ next = (struct page *)page_private(page);
+ else
+ next = list_entry(page->lru.next, struct page, lru);
+
+ return next;
+}
+
+/*
+ * Encode <page, obj_idx> as a single handle value.
+ * On hardware platforms with physical memory starting at 0x0 the pfn
+ * could be 0 so we ensure that the handle will never be 0 by adjusting the
+ * encoded obj_idx value before encoding.
+ */
+static void *obj_location_to_handle(struct page *page, unsigned long obj_idx)
+{
+ unsigned long handle;
+
+ if (!page) {
+ BUG_ON(obj_idx);
+ return NULL;
+ }
+
+ handle = page_to_pfn(page) << OBJ_INDEX_BITS;
+ handle |= ((obj_idx + 1) & OBJ_INDEX_MASK);
+
+ return (void *)handle;
+}
+
+/*
+ * Decode <page, obj_idx> pair from the given object handle. We adjust the
+ * decoded obj_idx back to its original value since it was adjusted in
+ * obj_location_to_handle().
+ */
+static void obj_handle_to_location(unsigned long handle, struct page **page,
+ unsigned long *obj_idx)
+{
+ *page = pfn_to_page(handle >> OBJ_INDEX_BITS);
+ *obj_idx = (handle & OBJ_INDEX_MASK) - 1;
+}
+
+static unsigned long obj_idx_to_offset(struct page *page,
+ unsigned long obj_idx, int class_size)
+{
+ unsigned long off = 0;
+
+ if (!is_first_page(page))
+ off = page->index;
+
+ return off + obj_idx * class_size;
+}
+
+static void reset_page(struct page *page)
+{
+ clear_bit(PG_private, &page->flags);
+ clear_bit(PG_private_2, &page->flags);
+ set_page_private(page, 0);
+ page->mapping = NULL;
+ page->freelist = NULL;
+ reset_page_mapcount(page);
+}
+
+static void free_zspage(struct page *first_page)
+{
+ struct page *nextp, *tmp, *head_extra;
+
+ BUG_ON(!is_first_page(first_page));
+ BUG_ON(first_page->inuse);
+
+ head_extra = (struct page *)page_private(first_page);
+
+ reset_page(first_page);
+ __free_page(first_page);
+
+ /* zspage with only 1 system page */
+ if (!head_extra)
+ return;
+
+ list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) {
+ list_del(&nextp->lru);
+ reset_page(nextp);
+ __free_page(nextp);
+ }
+ reset_page(head_extra);
+ __free_page(head_extra);
+}
+
+/* Initialize a newly allocated zspage */
+static void init_zspage(struct page *first_page, struct size_class *class)
+{
+ unsigned long off = 0;
+ struct page *page = first_page;
+
+ BUG_ON(!is_first_page(first_page));
+ while (page) {
+ struct page *next_page;
+ struct link_free *link;
+ unsigned int i = 1;
+ void *vaddr;
+
+ /*
+ * page->index stores offset of first object starting
+ * in the page. For the first page, this is always 0,
+ * so we use first_page->index (aka ->freelist) to store
+ * head of corresponding zspage's freelist.
+ */
+ if (page != first_page)
+ page->index = off;
+
+ vaddr = kmap_atomic(page);
+ link = (struct link_free *)vaddr + off / sizeof(*link);
+
+ while ((off += class->size) < PAGE_SIZE) {
+ link->next = obj_location_to_handle(page, i++);
+ link += class->size / sizeof(*link);
+ }
+
+ /*
+ * We now come to the last (full or partial) object on this
+ * page, which must point to the first object on the next
+ * page (if present)
+ */
+ next_page = get_next_page(page);
+ link->next = obj_location_to_handle(next_page, 0);
+ kunmap_atomic(vaddr);
+ page = next_page;
+ off %= PAGE_SIZE;
+ }
+}
+
+/*
+ * Allocate a zspage for the given size class
+ */
+static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
+{
+ int i, error;
+ struct page *first_page = NULL, *uninitialized_var(prev_page);
+
+ /*
+ * Allocate individual pages and link them together as:
+ * 1. first page->private = first sub-page
+ * 2. all sub-pages are linked together using page->lru
+ * 3. each sub-page is linked to the first page using page->first_page
+ *
+ * For each size class, First/Head pages are linked together using
+ * page->lru. Also, we set PG_private to identify the first page
+ * (i.e. no other sub-page has this flag set) and PG_private_2 to
+ * identify the last page.
+ */
+ error = -ENOMEM;
+ for (i = 0; i < class->pages_per_zspage; i++) {
+ struct page *page;
+
+ page = alloc_page(flags);
+ if (!page)
+ goto cleanup;
+
+ INIT_LIST_HEAD(&page->lru);
+ if (i == 0) { /* first page */
+ SetPagePrivate(page);
+ set_page_private(page, 0);
+ first_page = page;
+ first_page->inuse = 0;
+ }
+ if (i == 1)
+ set_page_private(first_page, (unsigned long)page);
+ if (i >= 1)
+ page->first_page = first_page;
+ if (i >= 2)
+ list_add(&page->lru, &prev_page->lru);
+ if (i == class->pages_per_zspage - 1) /* last page */
+ SetPagePrivate2(page);
+ prev_page = page;
+ }
+
+ init_zspage(first_page, class);
+
+ first_page->freelist = obj_location_to_handle(first_page, 0);
+ /* Maximum number of objects we can store in this zspage */
+ first_page->objects = class->pages_per_zspage * PAGE_SIZE / class->size;
+
+ error = 0; /* Success */
+
+cleanup:
+ if (unlikely(error) && first_page) {
+ free_zspage(first_page);
+ first_page = NULL;
+ }
+
+ return first_page;
+}
+
+static struct page *find_get_zspage(struct size_class *class)
+{
+ int i;
+ struct page *page;
+
+ for (i = 0; i < _ZS_NR_FULLNESS_GROUPS; i++) {
+ page = class->fullness_list[i];
+ if (page)
+ break;
+ }
+
+ return page;
+}
+
+#ifdef CONFIG_PGTABLE_MAPPING
+static inline int __zs_cpu_up(struct mapping_area *area)
+{
+ /*
+ * Make sure we don't leak memory if a cpu UP notification
+ * and zs_init() race and both call zs_cpu_up() on the same cpu
+ */
+ if (area->vm)
+ return 0;
+ area->vm = alloc_vm_area(PAGE_SIZE * 2, NULL);
+ if (!area->vm)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void __zs_cpu_down(struct mapping_area *area)
+{
+ if (area->vm)
+ free_vm_area(area->vm);
+ area->vm = NULL;
+}
+
+static inline void *__zs_map_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
+{
+ BUG_ON(map_vm_area(area->vm, PAGE_KERNEL, &pages));
+ area->vm_addr = area->vm->addr;
+ return area->vm_addr + off;
+}
+
+static inline void __zs_unmap_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
+{
+ unsigned long addr = (unsigned long)area->vm_addr;
+
+ unmap_kernel_range(addr, PAGE_SIZE * 2);
+}
+
+#else /* CONFIG_PGTABLE_MAPPING */
+
+static inline int __zs_cpu_up(struct mapping_area *area)
+{
+ /*
+ * Make sure we don't leak memory if a cpu UP notification
+ * and zs_init() race and both call zs_cpu_up() on the same cpu
+ */
+ if (area->vm_buf)
+ return 0;
+ area->vm_buf = (char *)__get_free_page(GFP_KERNEL);
+ if (!area->vm_buf)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void __zs_cpu_down(struct mapping_area *area)
+{
+ if (area->vm_buf)
+ free_page((unsigned long)area->vm_buf);
+ area->vm_buf = NULL;
+}
+
+static void *__zs_map_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
+{
+ int sizes[2];
+ void *addr;
+ char *buf = area->vm_buf;
+
+ /* disable page faults to match kmap_atomic() return conditions */
+ pagefault_disable();
+
+ /* no read fastpath */
+ if (area->vm_mm == ZS_MM_WO)
+ goto out;
+
+ sizes[0] = PAGE_SIZE - off;
+ sizes[1] = size - sizes[0];
+
+ /* copy object to per-cpu buffer */
+ addr = kmap_atomic(pages[0]);
+ memcpy(buf, addr + off, sizes[0]);
+ kunmap_atomic(addr);
+ addr = kmap_atomic(pages[1]);
+ memcpy(buf + sizes[0], addr, sizes[1]);
+ kunmap_atomic(addr);
+out:
+ return area->vm_buf;
+}
+
+static void __zs_unmap_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
+{
+ int sizes[2];
+ void *addr;
+ char *buf = area->vm_buf;
+
+ /* no write fastpath */
+ if (area->vm_mm == ZS_MM_RO)
+ goto out;
+
+ sizes[0] = PAGE_SIZE - off;
+ sizes[1] = size - sizes[0];
+
+ /* copy per-cpu buffer to object */
+ addr = kmap_atomic(pages[0]);
+ memcpy(addr + off, buf, sizes[0]);
+ kunmap_atomic(addr);
+ addr = kmap_atomic(pages[1]);
+ memcpy(addr, buf + sizes[0], sizes[1]);
+ kunmap_atomic(addr);
+
+out:
+ /* enable page faults to match kunmap_atomic() return conditions */
+ pagefault_enable();
+}
+
+#endif /* CONFIG_PGTABLE_MAPPING */
+
+static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action,
+ void *pcpu)
+{
+ int ret, cpu = (long)pcpu;
+ struct mapping_area *area;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ area = &per_cpu(zs_map_area, cpu);
+ ret = __zs_cpu_up(area);
+ if (ret)
+ return notifier_from_errno(ret);
+ break;
+ case CPU_DEAD:
+ case CPU_UP_CANCELED:
+ area = &per_cpu(zs_map_area, cpu);
+ __zs_cpu_down(area);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block zs_cpu_nb = {
+ .notifier_call = zs_cpu_notifier
+};
+
+static void zs_exit(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ zs_cpu_notifier(NULL, CPU_DEAD, (void *)(long)cpu);
+ unregister_cpu_notifier(&zs_cpu_nb);
+}
+
+static int zs_init(void)
+{
+ int cpu, ret;
+
+ register_cpu_notifier(&zs_cpu_nb);
+ for_each_online_cpu(cpu) {
+ ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
+ if (notifier_to_errno(ret))
+ goto fail;
+ }
+ return 0;
+fail:
+ zs_exit();
+ return notifier_to_errno(ret);
+}
+
+static unsigned int get_maxobj_per_zspage(int size, int pages_per_zspage)
+{
+ return pages_per_zspage * PAGE_SIZE / size;
+}
+
+static bool can_merge(struct size_class *prev, int size, int pages_per_zspage)
+{
+ if (prev->pages_per_zspage != pages_per_zspage)
+ return false;
+
+ if (get_maxobj_per_zspage(prev->size, prev->pages_per_zspage)
+ != get_maxobj_per_zspage(size, pages_per_zspage))
+ return false;
+
+ return true;
+}
+
+/**
+ * zs_create_pool - Creates an allocation pool to work from.
+ * @flags: allocation flags used to allocate pool metadata
+ *
+ * This function must be called before anything when using
+ * the zsmalloc allocator.
+ *
+ * On success, a pointer to the newly created pool is returned,
+ * otherwise NULL.
+ */
+struct zs_pool *zs_create_pool(gfp_t flags)
+{
+ int i;
+ struct zs_pool *pool;
+
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+ if (!pool)
+ return NULL;
+
+ /*
+ * Iterate reversly, because, size of size_class that we want to use
+ * for merging should be larger or equal to current size.
+ */
+ for (i = ZS_SIZE_CLASSES - 1; i >= 0; i--) {
+ int size;
+ int pages_per_zspage;
+ struct size_class *class;
+ struct size_class *prev_class;
+
+ size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA;
+ if (size > ZS_MAX_ALLOC_SIZE)
+ size = ZS_MAX_ALLOC_SIZE;
+ pages_per_zspage = get_pages_per_zspage(size);
+
+ /*
+ * size_class is used for normal zsmalloc operation such
+ * as alloc/free for that size. Although it is natural that we
+ * have one size_class for each size, there is a chance that we
+ * can get more memory utilization if we use one size_class for
+ * many different sizes whose size_class have same
+ * characteristics. So, we makes size_class point to
+ * previous size_class if possible.
+ */
+ if (i < ZS_SIZE_CLASSES - 1) {
+ prev_class = pool->size_class[i + 1];
+ if (can_merge(prev_class, size, pages_per_zspage)) {
+ pool->size_class[i] = prev_class;
+ continue;
+ }
+ }
+
+ class = kzalloc(sizeof(struct size_class), GFP_KERNEL);
+ if (!class)
+ goto err;
+
+ class->size = size;
+ class->index = i;
+ class->pages_per_zspage = pages_per_zspage;
+ spin_lock_init(&class->lock);
+ pool->size_class[i] = class;
+ }
+
+ pool->flags = flags;
+
+ return pool;
+
+err:
+ zs_destroy_pool(pool);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(zs_create_pool);
+
+void zs_destroy_pool(struct zs_pool *pool)
+{
+ int i;
+
+ for (i = 0; i < ZS_SIZE_CLASSES; i++) {
+ int fg;
+ struct size_class *class = pool->size_class[i];
+
+ if (!class)
+ continue;
+
+ if (class->index != i)
+ continue;
+
+ for (fg = 0; fg < _ZS_NR_FULLNESS_GROUPS; fg++) {
+ if (class->fullness_list[fg]) {
+ pr_info("Freeing non-empty class with size %db, fullness group %d\n",
+ class->size, fg);
+ }
+ }
+ kfree(class);
+ }
+ kfree(pool);
+}
+EXPORT_SYMBOL_GPL(zs_destroy_pool);
+
+/**
+ * zs_malloc - Allocate block of given size from pool.
+ * @pool: pool to allocate from
+ * @size: size of block to allocate
+ *
+ * On success, handle to the allocated object is returned,
+ * otherwise 0.
+ * Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail.
+ */
+unsigned long zs_malloc(struct zs_pool *pool, size_t size)
+{
+ unsigned long obj;
+ struct link_free *link;
+ struct size_class *class;
+ void *vaddr;
+
+ struct page *first_page, *m_page;
+ unsigned long m_objidx, m_offset;
+
+ if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE))
+ return 0;
+
+ class = pool->size_class[get_size_class_index(size)];
+
+ spin_lock(&class->lock);
+ first_page = find_get_zspage(class);
+
+ if (!first_page) {
+ spin_unlock(&class->lock);
+ first_page = alloc_zspage(class, pool->flags);
+ if (unlikely(!first_page))
+ return 0;
+
+ set_zspage_mapping(first_page, class->index, ZS_EMPTY);
+ atomic_long_add(class->pages_per_zspage,
+ &pool->pages_allocated);
+ spin_lock(&class->lock);
+ }
+
+ obj = (unsigned long)first_page->freelist;
+ obj_handle_to_location(obj, &m_page, &m_objidx);
+ m_offset = obj_idx_to_offset(m_page, m_objidx, class->size);
+
+ vaddr = kmap_atomic(m_page);
+ link = (struct link_free *)vaddr + m_offset / sizeof(*link);
+ first_page->freelist = link->next;
+ memset(link, POISON_INUSE, sizeof(*link));
+ kunmap_atomic(vaddr);
+
+ first_page->inuse++;
+ /* Now move the zspage to another fullness group, if required */
+ fix_fullness_group(pool, first_page);
+ spin_unlock(&class->lock);
+
+ return obj;
+}
+EXPORT_SYMBOL_GPL(zs_malloc);
+
+void zs_free(struct zs_pool *pool, unsigned long obj)
+{
+ struct link_free *link;
+ struct page *first_page, *f_page;
+ unsigned long f_objidx, f_offset;
+ void *vaddr;
+
+ int class_idx;
+ struct size_class *class;
+ enum fullness_group fullness;
+
+ if (unlikely(!obj))
+ return;
+
+ obj_handle_to_location(obj, &f_page, &f_objidx);
+ first_page = get_first_page(f_page);
+
+ get_zspage_mapping(first_page, &class_idx, &fullness);
+ class = pool->size_class[class_idx];
+ f_offset = obj_idx_to_offset(f_page, f_objidx, class->size);
+
+ spin_lock(&class->lock);
+
+ /* Insert this object in containing zspage's freelist */
+ vaddr = kmap_atomic(f_page);
+ link = (struct link_free *)(vaddr + f_offset);
+ link->next = first_page->freelist;
+ kunmap_atomic(vaddr);
+ first_page->freelist = (void *)obj;
+
+ first_page->inuse--;
+ fullness = fix_fullness_group(pool, first_page);
+ spin_unlock(&class->lock);
+
+ if (fullness == ZS_EMPTY) {
+ atomic_long_sub(class->pages_per_zspage,
+ &pool->pages_allocated);
+ free_zspage(first_page);
+ }
+}
+EXPORT_SYMBOL_GPL(zs_free);
+
+/**
+ * zs_map_object - get address of allocated object from handle.
+ * @pool: pool from which the object was allocated
+ * @handle: handle returned from zs_malloc
+ *
+ * Before using an object allocated from zs_malloc, it must be mapped using
+ * this function. When done with the object, it must be unmapped using
+ * zs_unmap_object.
+ *
+ * Only one object can be mapped per cpu at a time. There is no protection
+ * against nested mappings.
+ *
+ * This function returns with preemption and page faults disabled.
+ */
+void *zs_map_object(struct zs_pool *pool, unsigned long handle,
+ enum zs_mapmode mm)
+{
+ struct page *page;
+ unsigned long obj_idx, off;
+
+ unsigned int class_idx;
+ enum fullness_group fg;
+ struct size_class *class;
+ struct mapping_area *area;
+ struct page *pages[2];
+
+ BUG_ON(!handle);
+
+ /*
+ * Because we use per-cpu mapping areas shared among the
+ * pools/users, we can't allow mapping in interrupt context
+ * because it can corrupt another users mappings.
+ */
+ BUG_ON(in_interrupt());
+
+ obj_handle_to_location(handle, &page, &obj_idx);
+ get_zspage_mapping(get_first_page(page), &class_idx, &fg);
+ class = pool->size_class[class_idx];
+ off = obj_idx_to_offset(page, obj_idx, class->size);
+
+ area = &get_cpu_var(zs_map_area);
+ area->vm_mm = mm;
+ if (off + class->size <= PAGE_SIZE) {
+ /* this object is contained entirely within a page */
+ area->vm_addr = kmap_atomic(page);
+ return area->vm_addr + off;
+ }
+
+ /* this object spans two pages */
+ pages[0] = page;
+ pages[1] = get_next_page(page);
+ BUG_ON(!pages[1]);
+
+ return __zs_map_object(area, pages, off, class->size);
+}
+EXPORT_SYMBOL_GPL(zs_map_object);
+
+void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
+{
+ struct page *page;
+ unsigned long obj_idx, off;
+
+ unsigned int class_idx;
+ enum fullness_group fg;
+ struct size_class *class;
+ struct mapping_area *area;
+
+ BUG_ON(!handle);
+
+ obj_handle_to_location(handle, &page, &obj_idx);
+ get_zspage_mapping(get_first_page(page), &class_idx, &fg);
+ class = pool->size_class[class_idx];
+ off = obj_idx_to_offset(page, obj_idx, class->size);
+
+ area = &__get_cpu_var(zs_map_area);
+ if (off + class->size <= PAGE_SIZE)
+ kunmap_atomic(area->vm_addr);
+ else {
+ struct page *pages[2];
+
+ pages[0] = page;
+ pages[1] = get_next_page(page);
+ BUG_ON(!pages[1]);
+
+ __zs_unmap_object(area, pages, off, class->size);
+ }
+ put_cpu_var(zs_map_area);
+}
+EXPORT_SYMBOL_GPL(zs_unmap_object);
+
+unsigned long zs_get_total_pages(struct zs_pool *pool)
+{
+ return atomic_long_read(&pool->pages_allocated);
+}
+EXPORT_SYMBOL_GPL(zs_get_total_pages);
+
+module_init(zs_init);
+module_exit(zs_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b6aaa7a..75727c6 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -915,14 +915,14 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias);
if (1) {
- struct rtnl_link_ifmap map = {
- .mem_start = dev->mem_start,
- .mem_end = dev->mem_end,
- .base_addr = dev->base_addr,
- .irq = dev->irq,
- .dma = dev->dma,
- .port = dev->if_port,
- };
+ struct rtnl_link_ifmap map;
+ memset(&map, 0, sizeof(map));
+ map.mem_start = dev->mem_start;
+ map.mem_end = dev->mem_end;
+ map.base_addr = dev->base_addr;
+ map.irq = dev->irq;
+ map.dma = dev->dma;
+ map.port = dev->if_port;
NLA_PUT(skb, IFLA_MAP, sizeof(map), &map);
}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 76db592..085d63f 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -327,6 +327,9 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
ASSERT_RTNL();
+ if (in_dev->dead)
+ goto no_promotions;
+
/* 1. Deleting primary ifaddr forces deletion all secondaries
* unless alias promotion is set
**/
@@ -373,6 +376,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
fib_del_ifaddr(ifa, ifa1);
}
+no_promotions:
/* 2. Unlink it */
*ifap = ifa1->ifa_next;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index a54817a..f7b8dbe 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -765,6 +765,9 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim)
subnet = 1;
}
+ if (in_dev->dead)
+ goto no_promotions;
+
/* Deletion is more complicated than add.
* We should take care of not to delete too much :-)
*
@@ -840,6 +843,7 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim)
}
}
+no_promotions:
if (!(ok & BRD_OK))
fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
if (subnet && ifa->ifa_prefixlen < 31) {
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index fd7a3f6..42536c6 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -350,11 +350,12 @@ unsigned int arpt_do_table(struct sk_buff *skb,
}
/* All zeroes == unconditional rule. */
-static inline bool unconditional(const struct arpt_arp *arp)
+static inline bool unconditional(const struct arpt_entry *e)
{
static const struct arpt_arp uncond;
- return memcmp(arp, &uncond, sizeof(uncond)) == 0;
+ return e->target_offset == sizeof(struct arpt_entry) &&
+ memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
}
/* Figures out from what hook each rule can be called: returns 0 if
@@ -393,11 +394,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
|= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
/* Unconditional return/END. */
- if ((e->target_offset == sizeof(struct arpt_entry) &&
+ if ((unconditional(e) &&
(strcmp(t->target.u.user.name,
XT_STANDARD_TARGET) == 0) &&
- t->verdict < 0 && unconditional(&e->arp)) ||
- visited) {
+ t->verdict < 0) || visited) {
unsigned int oldpos, size;
if ((strcmp(t->target.u.user.name,
@@ -542,7 +542,7 @@ static bool check_underflow(const struct arpt_entry *e)
const struct xt_entry_target *t;
unsigned int verdict;
- if (!unconditional(&e->arp))
+ if (!unconditional(e))
return false;
t = arpt_get_target_c(e);
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
@@ -563,7 +563,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
unsigned int h;
if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 ||
- (unsigned char *)e + sizeof(struct arpt_entry) >= limit) {
+ (unsigned char *)e + sizeof(struct arpt_entry) >= limit ||
+ (unsigned char *)e + e->next_offset > limit) {
duprintf("Bad offset %p\n", e);
return -EINVAL;
}
@@ -583,9 +584,9 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
newinfo->hook_entry[h] = hook_entries[h];
if ((unsigned char *)e - base == underflows[h]) {
if (!check_underflow(e)) {
- pr_err("Underflows must be unconditional and "
- "use the STANDARD target with "
- "ACCEPT/DROP\n");
+ pr_debug("Underflows must be unconditional and "
+ "use the STANDARD target with "
+ "ACCEPT/DROP\n");
return -EINVAL;
}
newinfo->underflow[h] = underflows[h];
@@ -1217,7 +1218,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
- (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) {
+ (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit ||
+ (unsigned char *)e + e->next_offset > limit) {
duprintf("Bad offset %p, limit = %p\n", e, limit);
return -EINVAL;
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 24e556e..2f5ef5b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -168,11 +168,12 @@ get_entry(const void *base, unsigned int offset)
/* All zeroes == unconditional rule. */
/* Mildly perf critical (only if packet tracing is on) */
-static inline bool unconditional(const struct ipt_ip *ip)
+static inline bool unconditional(const struct ipt_entry *e)
{
static const struct ipt_ip uncond;
- return memcmp(ip, &uncond, sizeof(uncond)) == 0;
+ return e->target_offset == sizeof(struct ipt_entry) &&
+ memcmp(&e->ip, &uncond, sizeof(uncond)) == 0;
#undef FWINV
}
@@ -230,11 +231,10 @@ get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
} else if (s == e) {
(*rulenum)++;
- if (s->target_offset == sizeof(struct ipt_entry) &&
+ if (unconditional(s) &&
strcmp(t->target.u.kernel.target->name,
XT_STANDARD_TARGET) == 0 &&
- t->verdict < 0 &&
- unconditional(&s->ip)) {
+ t->verdict < 0) {
/* Tail of chains: STANDARD target (return/policy) */
*comment = *chainname == hookname
? comments[NF_IP_TRACE_COMMENT_POLICY]
@@ -468,11 +468,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
/* Unconditional return/END. */
- if ((e->target_offset == sizeof(struct ipt_entry) &&
+ if ((unconditional(e) &&
(strcmp(t->target.u.user.name,
XT_STANDARD_TARGET) == 0) &&
- t->verdict < 0 && unconditional(&e->ip)) ||
- visited) {
+ t->verdict < 0) || visited) {
unsigned int oldpos, size;
if ((strcmp(t->target.u.user.name,
@@ -705,7 +704,7 @@ static bool check_underflow(const struct ipt_entry *e)
const struct xt_entry_target *t;
unsigned int verdict;
- if (!unconditional(&e->ip))
+ if (!unconditional(e))
return false;
t = ipt_get_target_c(e);
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
@@ -727,7 +726,8 @@ check_entry_size_and_hooks(struct ipt_entry *e,
unsigned int h;
if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
- (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
+ (unsigned char *)e + sizeof(struct ipt_entry) >= limit ||
+ (unsigned char *)e + e->next_offset > limit) {
duprintf("Bad offset %p\n", e);
return -EINVAL;
}
@@ -747,9 +747,9 @@ check_entry_size_and_hooks(struct ipt_entry *e,
newinfo->hook_entry[h] = hook_entries[h];
if ((unsigned char *)e - base == underflows[h]) {
if (!check_underflow(e)) {
- pr_err("Underflows must be unconditional and "
- "use the STANDARD target with "
- "ACCEPT/DROP\n");
+ pr_debug("Underflows must be unconditional and "
+ "use the STANDARD target with "
+ "ACCEPT/DROP\n");
return -EINVAL;
}
newinfo->underflow[h] = underflows[h];
@@ -1484,7 +1484,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
- (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
+ (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit ||
+ (unsigned char *)e + e->next_offset > limit) {
duprintf("Bad offset %p, limit = %p\n", e, limit);
return -EINVAL;
}
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 9931152..9a30807 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -123,8 +123,16 @@ static int masq_inet_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
- struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
- return masq_device_event(this, event, dev);
+ struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev;
+ /* The masq_dev_notifier will catch the case of the device going
+ * down. So if the inetdev is dead and being destroyed we have
+ * no work to do. Otherwise this is an individual address removal
+ * and we have to perform the flush.
+ */
+ if (idev->dead)
+ return NOTIFY_DONE;
+
+ return masq_device_event(this, event, idev->dev);
}
static struct notifier_block masq_dev_notifier = {
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 93fbd72..02743c2 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -641,7 +641,7 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
void *user_icmph, size_t icmph_len) {
u8 type, code;
- if (len > 0xFFFF)
+ if (len > 0xFFFF || len < icmph_len)
return -EMSGSIZE;
/*
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 14cb310..387fc82 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -208,11 +208,12 @@ get_entry(const void *base, unsigned int offset)
/* All zeroes == unconditional rule. */
/* Mildly perf critical (only if packet tracing is on) */
-static inline bool unconditional(const struct ip6t_ip6 *ipv6)
+static inline bool unconditional(const struct ip6t_entry *e)
{
static const struct ip6t_ip6 uncond;
- return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
+ return e->target_offset == sizeof(struct ip6t_entry) &&
+ memcmp(&e->ipv6, &uncond, sizeof(uncond)) == 0;
}
static inline const struct xt_entry_target *
@@ -269,11 +270,10 @@ get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
} else if (s == e) {
(*rulenum)++;
- if (s->target_offset == sizeof(struct ip6t_entry) &&
+ if (unconditional(s) &&
strcmp(t->target.u.kernel.target->name,
XT_STANDARD_TARGET) == 0 &&
- t->verdict < 0 &&
- unconditional(&s->ipv6)) {
+ t->verdict < 0) {
/* Tail of chains: STANDARD target (return/policy) */
*comment = *chainname == hookname
? comments[NF_IP6_TRACE_COMMENT_POLICY]
@@ -490,11 +490,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
/* Unconditional return/END. */
- if ((e->target_offset == sizeof(struct ip6t_entry) &&
+ if ((unconditional(e) &&
(strcmp(t->target.u.user.name,
XT_STANDARD_TARGET) == 0) &&
- t->verdict < 0 &&
- unconditional(&e->ipv6)) || visited) {
+ t->verdict < 0) || visited) {
unsigned int oldpos, size;
if ((strcmp(t->target.u.user.name,
@@ -728,7 +727,7 @@ static bool check_underflow(const struct ip6t_entry *e)
const struct xt_entry_target *t;
unsigned int verdict;
- if (!unconditional(&e->ipv6))
+ if (!unconditional(e))
return false;
t = ip6t_get_target_c(e);
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
@@ -750,7 +749,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
unsigned int h;
if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 ||
- (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
+ (unsigned char *)e + sizeof(struct ip6t_entry) >= limit ||
+ (unsigned char *)e + e->next_offset > limit) {
duprintf("Bad offset %p\n", e);
return -EINVAL;
}
@@ -770,9 +770,9 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
newinfo->hook_entry[h] = hook_entries[h];
if ((unsigned char *)e - base == underflows[h]) {
if (!check_underflow(e)) {
- pr_err("Underflows must be unconditional and "
- "use the STANDARD target with "
- "ACCEPT/DROP\n");
+ pr_debug("Underflows must be unconditional and "
+ "use the STANDARD target with "
+ "ACCEPT/DROP\n");
return -EINVAL;
}
newinfo->underflow[h] = underflows[h];
@@ -1508,7 +1508,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
- (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) {
+ (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit ||
+ (unsigned char *)e + e->next_offset > limit) {
duprintf("Bad offset %p, limit = %p\n", e, limit);
return -EINVAL;
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3b44d0f..b4da958 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -177,7 +177,7 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
static void
clean_from_lists(struct nf_conn *ct)
{
- pr_debug("clean_from_lists(%p)\n", ct);
+ pr_debug("clean_from_lists(%pK)\n", ct);
hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode);
@@ -192,7 +192,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
struct net *net = nf_ct_net(ct);
struct nf_conntrack_l4proto *l4proto;
- pr_debug("destroy_conntrack(%p)\n", ct);
+ pr_debug("destroy_conntrack(%pK)\n", ct);
NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
NF_CT_ASSERT(!timer_pending(&ct->timeout));
@@ -225,7 +225,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
if (ct->master)
nf_ct_put(ct->master);
- pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct);
+ pr_debug("destroy_conntrack: returning ct=%pK to slab\n", ct);
nf_conntrack_free(ct);
}
@@ -470,7 +470,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
/* No external references means no one else could have
confirmed us. */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
- pr_debug("Confirming conntrack %p\n", ct);
+ pr_debug("Confirming conntrack %pK\n", ct);
spin_lock_bh(&nf_conntrack_lock);
@@ -786,7 +786,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
spin_lock_bh(&nf_conntrack_lock);
exp = nf_ct_find_expectation(net, zone, tuple);
if (exp) {
- pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
+ pr_debug("conntrack: expectation arrives ct=%pK exp=%pK\n",
ct, exp);
/* Welcome, Mr. Bond. We've been expecting you... */
__set_bit(IPS_EXPECTED_BIT, &ct->status);
@@ -871,14 +871,14 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
} else {
/* Once we've had two way comms, always ESTABLISHED. */
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
- pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
+ pr_debug("nf_conntrack_in: normal packet for %pK\n", ct);
*ctinfo = IP_CT_ESTABLISHED;
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
- pr_debug("nf_conntrack_in: related packet for %p\n",
+ pr_debug("nf_conntrack_in: related packet for %pK\n",
ct);
*ctinfo = IP_CT_RELATED;
} else {
- pr_debug("nf_conntrack_in: new packet for %p\n", ct);
+ pr_debug("nf_conntrack_in: new packet for %pK\n", ct);
*ctinfo = IP_CT_NEW;
}
*set_reply = 0;
@@ -1016,7 +1016,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
/* Should be unconfirmed, so not in hash table yet */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
- pr_debug("Altering reply tuple of %p to ", ct);
+ pr_debug("Altering reply tuple of %pK to ", ct);
nf_ct_dump_tuple(newreply);
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
@@ -1516,7 +1516,7 @@ static int nf_conntrack_init_net(struct net *net)
goto err_stat;
}
- net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net);
+ net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%pK", net);
if (!net->ct.slabname) {
ret = -ENOMEM;
goto err_slabname;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index b0869fe..9d4ad83 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -663,6 +663,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
{
struct xt_table_info *newinfo;
int cpu;
+ size_t sz = sizeof(*newinfo) + size;
+
+ if (sz < sizeof(*newinfo))
+ return NULL;
/* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index c8a53e5..5fa5e46 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1987,7 +1987,7 @@ static int qtaguid_ctrl_proc_read(char *page, char **num_items_returned,
f_count = atomic_long_read(
&sock_tag_entry->socket->file->f_count);
len = snprintf(outp, char_count,
- "sock=%p tag=0x%llx (uid=%u) pid=%u "
+ "sock=%pK tag=0x%llx (uid=%u) pid=%u "
"f_count=%lu\n",
sock_tag_entry->sk,
sock_tag_entry->tag, uid,
diff --git a/net/socket.c b/net/socket.c
index e4c7f90..3b5e6bb 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1683,6 +1683,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
if (len > INT_MAX)
len = INT_MAX;
+ if (unlikely(!access_ok(VERIFY_READ, buff, len)))
+ return -EFAULT;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out;
@@ -1742,6 +1744,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
if (size > INT_MAX)
size = INT_MAX;
+ if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size)))
+ return -EFAULT;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out;
@@ -2294,31 +2298,31 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
break;
}
-out_put:
- fput_light(sock->file, fput_needed);
-
if (err == 0)
- return datagrams;
+ goto out_put;
+
+ if (datagrams == 0) {
+ datagrams = err;
+ goto out_put;
+ }
- if (datagrams != 0) {
+ /*
+ * We may return less entries than requested (vlen) if the
+ * sock is non block and there aren't enough datagrams...
+ */
+ if (err != -EAGAIN) {
/*
- * We may return less entries than requested (vlen) if the
- * sock is non block and there aren't enough datagrams...
+ * ... or if recvmsg returns an error after we
+ * received some datagrams, where we record the
+ * error to return on the next call or if the
+ * app asks about it using getsockopt(SO_ERROR).
*/
- if (err != -EAGAIN) {
- /*
- * ... or if recvmsg returns an error after we
- * received some datagrams, where we record the
- * error to return on the next call or if the
- * app asks about it using getsockopt(SO_ERROR).
- */
- sock->sk->sk_err = -err;
- }
-
- return datagrams;
+ sock->sk->sk_err = -err;
}
+out_put:
+ fput_light(sock->file, fput_needed);
- return err;
+ return datagrams;
}
SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 93b2b59..7eb36fd 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -262,6 +262,11 @@ cmd_lzo = (cat $(filter-out FORCE,$^) | \
lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
+quiet_cmd_lz4 = LZ4 $@
+cmd_lz4 = (cat $(filter-out FORCE,$^) | \
+ lz4c -l -c1 stdin stdout && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
# XZ
# ---------------------------------------------------------------------------
# Use xzkern to compress the kernel image and xzmisc to compress other things.
diff --git a/security/keys/key.c b/security/keys/key.c
index e1704f6..d2765e4 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -580,7 +580,7 @@ int key_reject_and_link(struct key *key,
mutex_unlock(&key_construction_mutex);
- if (keyring)
+ if (keyring && link_ret == 0)
__key_link_end(keyring, key->type, prealloc);
/* wake up anyone waiting for a key to be constructed */
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 49bbc97..3f7b410 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -188,7 +188,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
struct timespec now;
unsigned long timo;
key_ref_t key_ref, skey_ref;
- char xbuf[12];
+ char xbuf[16];
int rc;
key_ref = make_key_ref(key, 0);
diff --git a/sound/core/control.c b/sound/core/control.c
index 6128f69..2b79043 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1077,9 +1077,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
long private_size;
struct user_element *ue;
int idx, err;
-
- if (card->user_ctl_count >= MAX_USER_CONTROLS)
- return -ENOMEM;
+
if (info->count < 1)
return -EINVAL;
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
@@ -1088,21 +1086,16 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
info->id.numid = 0;
memset(&kctl, 0, sizeof(kctl));
- down_write(&card->controls_rwsem);
- _kctl = snd_ctl_find_id(card, &info->id);
- err = 0;
- if (_kctl) {
- if (replace)
- err = snd_ctl_remove(card, _kctl);
- else
- err = -EBUSY;
- } else {
- if (replace)
- err = -ENOENT;
+
+ if (replace) {
+ err = snd_ctl_remove_user_ctl(file, &info->id);
+ if (err)
+ return err;
}
- up_write(&card->controls_rwsem);
- if (err < 0)
- return err;
+
+ if (card->user_ctl_count >= MAX_USER_CONTROLS)
+ return -ENOMEM;
+
memcpy(&kctl.id, &info->id, sizeof(info->id));
kctl.count = info->owner ? info->owner : 1;
access |= SNDRV_CTL_ELEM_ACCESS_USER;
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
index b8b31c4..14d483d 100644
--- a/sound/core/hrtimer.c
+++ b/sound/core/hrtimer.c
@@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_timer *t)
struct snd_hrtimer *stime = t->private_data;
atomic_set(&stime->running, 0);
- hrtimer_cancel(&stime->hrt);
+ hrtimer_try_to_cancel(&stime->hrt);
hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
HRTIMER_MODE_REL);
atomic_set(&stime->running, 1);
@@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
{
struct snd_hrtimer *stime = t->private_data;
atomic_set(&stime->running, 0);
+ hrtimer_try_to_cancel(&stime->hrt);
return 0;
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 950eed0..22c43b3 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -72,7 +72,7 @@ struct snd_timer_user {
struct timespec tstamp; /* trigger tstamp */
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
- struct mutex tread_sem;
+ struct mutex ioctl_lock;
};
/* list of timers */
@@ -214,11 +214,13 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
slave->slave_id == master->slave_id) {
list_move_tail(&slave->open_list, &master->slave_list_head);
spin_lock_irq(&slave_active_lock);
+ spin_lock(&master->timer->lock);
slave->master = master;
slave->timer = master->timer;
if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
list_add_tail(&slave->active_list,
&master->slave_active_head);
+ spin_unlock(&master->timer->lock);
spin_unlock_irq(&slave_active_lock);
}
}
@@ -342,15 +344,18 @@ int snd_timer_close(struct snd_timer_instance *timeri)
timer->hw.close)
timer->hw.close(timer);
/* remove slave links */
+ spin_lock_irq(&slave_active_lock);
+ spin_lock(&timer->lock);
list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
open_list) {
- spin_lock_irq(&slave_active_lock);
- _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
list_move_tail(&slave->open_list, &snd_timer_slave_list);
slave->master = NULL;
slave->timer = NULL;
- spin_unlock_irq(&slave_active_lock);
+ list_del_init(&slave->ack_list);
+ list_del_init(&slave->active_list);
}
+ spin_unlock(&timer->lock);
+ spin_unlock_irq(&slave_active_lock);
mutex_unlock(&register_mutex);
}
if (timeri->private_free)
@@ -436,9 +441,12 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
spin_lock_irqsave(&slave_active_lock, flags);
timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
- if (timeri->master)
+ if (timeri->master && timeri->timer) {
+ spin_lock(&timeri->timer->lock);
list_add_tail(&timeri->active_list,
&timeri->master->slave_active_head);
+ spin_unlock(&timeri->timer->lock);
+ }
spin_unlock_irqrestore(&slave_active_lock, flags);
return 1; /* delayed start */
}
@@ -484,6 +492,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
if (!keep_flag) {
spin_lock_irqsave(&slave_active_lock, flags);
timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
spin_unlock_irqrestore(&slave_active_lock, flags);
}
goto __end;
@@ -689,7 +699,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
} else {
ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
if (--timer->running)
- list_del(&ti->active_list);
+ list_del_init(&ti->active_list);
}
if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
(ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -1170,6 +1180,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
tu->tstamp = *tstamp;
if ((tu->filter & (1 << event)) == 0 || !tu->tread)
return;
+ memset(&r1, 0, sizeof(r1));
r1.event = event;
r1.tstamp = *tstamp;
r1.val = resolution;
@@ -1204,6 +1215,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
}
if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
tu->last_resolution != resolution) {
+ memset(&r1, 0, sizeof(r1));
r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
r1.tstamp = tstamp;
r1.val = resolution;
@@ -1252,7 +1264,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
return -ENOMEM;
spin_lock_init(&tu->qlock);
init_waitqueue_head(&tu->qchange_sleep);
- mutex_init(&tu->tread_sem);
+ mutex_init(&tu->ioctl_lock);
tu->ticks = 1;
tu->queue_size = 128;
tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
@@ -1272,8 +1284,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
if (file->private_data) {
tu = file->private_data;
file->private_data = NULL;
+ mutex_lock(&tu->ioctl_lock);
if (tu->timeri)
snd_timer_close(tu->timeri);
+ mutex_unlock(&tu->ioctl_lock);
kfree(tu->queue);
kfree(tu->tqueue);
kfree(tu);
@@ -1511,7 +1525,6 @@ static int snd_timer_user_tselect(struct file *file,
int err = 0;
tu = file->private_data;
- mutex_lock(&tu->tread_sem);
if (tu->timeri) {
snd_timer_close(tu->timeri);
tu->timeri = NULL;
@@ -1555,7 +1568,6 @@ static int snd_timer_user_tselect(struct file *file,
}
__err:
- mutex_unlock(&tu->tread_sem);
return err;
}
@@ -1669,6 +1681,7 @@ static int snd_timer_user_params(struct file *file,
if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
if (tu->tread) {
struct snd_timer_tread tread;
+ memset(&tread, 0, sizeof(tread));
tread.event = SNDRV_TIMER_EVENT_EARLY;
tread.tstamp.tv_sec = 0;
tread.tstamp.tv_nsec = 0;
@@ -1768,7 +1781,7 @@ enum {
SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
};
-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct snd_timer_user *tu;
@@ -1785,17 +1798,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
{
int xarg;
- mutex_lock(&tu->tread_sem);
- if (tu->timeri) { /* too late */
- mutex_unlock(&tu->tread_sem);
+ if (tu->timeri) /* too late */
return -EBUSY;
- }
- if (get_user(xarg, p)) {
- mutex_unlock(&tu->tread_sem);
+ if (get_user(xarg, p))
return -EFAULT;
- }
tu->tread = xarg ? 1 : 0;
- mutex_unlock(&tu->tread_sem);
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO:
@@ -1828,6 +1835,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
return -ENOTTY;
}
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct snd_timer_user *tu = file->private_data;
+ long ret;
+
+ mutex_lock(&tu->ioctl_lock);
+ ret = __snd_timer_user_ioctl(file, cmd, arg);
+ mutex_unlock(&tu->ioctl_lock);
+ return ret;
+}
+
static int snd_timer_user_fasync(int fd, struct file * file, int on)
{
struct snd_timer_user *tu;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 05842c8..2d7b5e7 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -393,6 +393,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
* (fp->maxpacksize & 0x7ff);
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
fp->clock = clock;
+ INIT_LIST_HEAD(&fp->list);
/* some quirks for attributes here */
@@ -434,6 +435,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
err = snd_usb_add_audio_endpoint(chip, stream, fp);
if (err < 0) {
+ list_del(&fp->list); /* unlink for avoiding double-free */
kfree(fp->rate_table);
kfree(fp);
return err;
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index c635a2d..9e864e9 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2213,7 +2213,6 @@ int snd_usbmidi_create(struct snd_card *card,
else
err = snd_usbmidi_create_endpoints(umidi, endpoints);
if (err < 0) {
- snd_usbmidi_free(umidi);
return err;
}
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 4a650ab..d7f1822 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -139,6 +139,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
kfree(fp);
return -EINVAL;
}
+ INIT_LIST_HEAD(&fp->list);
if (fp->nr_rates > 0) {
rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
if (!rate_table) {
@@ -152,24 +153,31 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
stream = (fp->endpoint & USB_DIR_IN)
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
err = snd_usb_add_audio_endpoint(chip, stream, fp);
- if (err < 0) {
- kfree(fp);
- kfree(rate_table);
- return err;
- }
+ if (err < 0)
+ goto error;
if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
fp->altset_idx >= iface->num_altsetting) {
- kfree(fp);
- kfree(rate_table);
- return -EINVAL;
+ err = -EINVAL;
+ goto error;
}
alts = &iface->altsetting[fp->altset_idx];
+ if (get_iface_desc(alts)->bNumEndpoints < 1) {
+ err = -EINVAL;
+ goto error;
+ }
+
fp->datainterval = snd_usb_parse_datainterval(chip, alts);
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
usb_set_interface(chip->dev, fp->iface, 0);
snd_usb_init_pitch(chip, fp->iface, alts, fp);
snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
return 0;
+
+ error:
+ list_del(&fp->list); /* unlink for avoiding double-free */
+ kfree(fp);
+ kfree(rate_table);
+ return err;
}
/*
@@ -237,6 +245,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
fp->datainterval = 0;
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+ INIT_LIST_HEAD(&fp->list);
switch (fp->maxpacksize) {
case 0x120:
@@ -260,6 +269,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
err = snd_usb_add_audio_endpoint(chip, stream, fp);
if (err < 0) {
+ list_del(&fp->list); /* unlink for avoiding double-free */
kfree(fp);
return err;
}
diff --git a/usr/Kconfig b/usr/Kconfig
index 65b845b..16ffe99 100644
--- a/usr/Kconfig
+++ b/usr/Kconfig
@@ -90,6 +90,15 @@ config RD_LZO
Support loading of a LZO encoded initial ramdisk or cpio buffer
If unsure, say N.
+config RD_LZ4
+ bool "Support initial ramdisks compressed using LZ4" if EXPERT
+ default !EXPERT
+ depends on BLK_DEV_INITRD
+ select DECOMPRESS_LZ4
+ help
+ Support loading of a LZ4 encoded initial ramdisk or cpio buffer
+ If unsure, say N.
+
choice
prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!=""
help